refactor more field tests into submodules #1983
This commit is contained in:
parent
28606e9985
commit
b9cc8a4ca9
File diff suppressed because it is too large
Load Diff
49
tests/fields/test_boolean_field.py
Normal file
49
tests/fields/test_boolean_field.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase, get_as_pymongo
|
||||||
|
|
||||||
|
|
||||||
|
class TestBooleanField(MongoDBTestCase):
|
||||||
|
def test_storage(self):
|
||||||
|
class Person(Document):
|
||||||
|
admin = BooleanField()
|
||||||
|
|
||||||
|
person = Person(admin=True)
|
||||||
|
person.save()
|
||||||
|
self.assertEqual(
|
||||||
|
get_as_pymongo(person),
|
||||||
|
{'_id': person.id,
|
||||||
|
'admin': True})
|
||||||
|
|
||||||
|
def test_validation(self):
|
||||||
|
"""Ensure that invalid values cannot be assigned to boolean
|
||||||
|
fields.
|
||||||
|
"""
|
||||||
|
class Person(Document):
|
||||||
|
admin = BooleanField()
|
||||||
|
|
||||||
|
person = Person()
|
||||||
|
person.admin = True
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
person.admin = 2
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.admin = 'Yes'
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.admin = 'False'
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
def test_weirdness_constructor(self):
|
||||||
|
"""When attribute is set in contructor, it gets cast into a bool
|
||||||
|
which causes some weird behavior. We dont necessarily want to maintain this behavior
|
||||||
|
but its a known issue
|
||||||
|
"""
|
||||||
|
class Person(Document):
|
||||||
|
admin = BooleanField()
|
||||||
|
|
||||||
|
new_person = Person(admin='False')
|
||||||
|
self.assertTrue(new_person.admin)
|
||||||
|
|
||||||
|
new_person = Person(admin='0')
|
||||||
|
self.assertTrue(new_person.admin)
|
443
tests/fields/test_cached_reference_field.py
Normal file
443
tests/fields/test_cached_reference_field.py
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestCachedReferenceField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_get_and_save(self):
|
||||||
|
"""
|
||||||
|
Tests #1047: CachedReferenceField creates DBRefs on to_python,
|
||||||
|
but can't save them on to_mongo.
|
||||||
|
"""
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocorrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = CachedReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocorrence.drop_collection()
|
||||||
|
|
||||||
|
Ocorrence(person="testte",
|
||||||
|
animal=Animal(name="Leopard", tag="heavy").save()).save()
|
||||||
|
p = Ocorrence.objects.get()
|
||||||
|
p.person = 'new_testte'
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
def test_general_things(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocorrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = CachedReferenceField(
|
||||||
|
Animal, fields=['tag'])
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocorrence.drop_collection()
|
||||||
|
|
||||||
|
a = Animal(name="Leopard", tag="heavy")
|
||||||
|
a.save()
|
||||||
|
|
||||||
|
self.assertEqual(Animal._cached_reference_fields, [Ocorrence.animal])
|
||||||
|
o = Ocorrence(person="teste", animal=a)
|
||||||
|
o.save()
|
||||||
|
|
||||||
|
p = Ocorrence(person="Wilson")
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
self.assertEqual(Ocorrence.objects(animal=None).count(), 1)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
a.to_mongo(fields=['tag']), {'tag': 'heavy', "_id": a.pk})
|
||||||
|
|
||||||
|
self.assertEqual(o.to_mongo()['animal']['tag'], 'heavy')
|
||||||
|
|
||||||
|
# counts
|
||||||
|
Ocorrence(person="teste 2").save()
|
||||||
|
Ocorrence(person="teste 3").save()
|
||||||
|
|
||||||
|
count = Ocorrence.objects(animal__tag='heavy').count()
|
||||||
|
self.assertEqual(count, 1)
|
||||||
|
|
||||||
|
ocorrence = Ocorrence.objects(animal__tag='heavy').first()
|
||||||
|
self.assertEqual(ocorrence.person, "teste")
|
||||||
|
self.assertIsInstance(ocorrence.animal, Animal)
|
||||||
|
|
||||||
|
def test_with_decimal(self):
|
||||||
|
class PersonAuto(Document):
|
||||||
|
name = StringField()
|
||||||
|
salary = DecimalField()
|
||||||
|
|
||||||
|
class SocialTest(Document):
|
||||||
|
group = StringField()
|
||||||
|
person = CachedReferenceField(
|
||||||
|
PersonAuto,
|
||||||
|
fields=('salary',))
|
||||||
|
|
||||||
|
PersonAuto.drop_collection()
|
||||||
|
SocialTest.drop_collection()
|
||||||
|
|
||||||
|
p = PersonAuto(name="Alberto", salary=Decimal('7000.00'))
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
s = SocialTest(group="dev", person=p)
|
||||||
|
s.save()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
SocialTest.objects._collection.find_one({'person.salary': 7000.00}), {
|
||||||
|
'_id': s.pk,
|
||||||
|
'group': s.group,
|
||||||
|
'person': {
|
||||||
|
'_id': p.pk,
|
||||||
|
'salary': 7000.00
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_cached_reference_field_reference(self):
|
||||||
|
class Group(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
name = StringField()
|
||||||
|
group = ReferenceField(Group)
|
||||||
|
|
||||||
|
class SocialData(Document):
|
||||||
|
obs = StringField()
|
||||||
|
tags = ListField(
|
||||||
|
StringField())
|
||||||
|
person = CachedReferenceField(
|
||||||
|
Person,
|
||||||
|
fields=('group',))
|
||||||
|
|
||||||
|
Group.drop_collection()
|
||||||
|
Person.drop_collection()
|
||||||
|
SocialData.drop_collection()
|
||||||
|
|
||||||
|
g1 = Group(name='dev')
|
||||||
|
g1.save()
|
||||||
|
|
||||||
|
g2 = Group(name="designers")
|
||||||
|
g2.save()
|
||||||
|
|
||||||
|
p1 = Person(name="Alberto", group=g1)
|
||||||
|
p1.save()
|
||||||
|
|
||||||
|
p2 = Person(name="Andre", group=g1)
|
||||||
|
p2.save()
|
||||||
|
|
||||||
|
p3 = Person(name="Afro design", group=g2)
|
||||||
|
p3.save()
|
||||||
|
|
||||||
|
s1 = SocialData(obs="testing 123", person=p1, tags=['tag1', 'tag2'])
|
||||||
|
s1.save()
|
||||||
|
|
||||||
|
s2 = SocialData(obs="testing 321", person=p3, tags=['tag3', 'tag4'])
|
||||||
|
s2.save()
|
||||||
|
|
||||||
|
self.assertEqual(SocialData.objects._collection.find_one(
|
||||||
|
{'tags': 'tag2'}), {
|
||||||
|
'_id': s1.pk,
|
||||||
|
'obs': 'testing 123',
|
||||||
|
'tags': ['tag1', 'tag2'],
|
||||||
|
'person': {
|
||||||
|
'_id': p1.pk,
|
||||||
|
'group': g1.pk
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(SocialData.objects(person__group=g2).count(), 1)
|
||||||
|
self.assertEqual(SocialData.objects(person__group=g2).first(), s2)
|
||||||
|
|
||||||
|
def test_cached_reference_field_push_with_fields(self):
|
||||||
|
class Product(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
Product.drop_collection()
|
||||||
|
|
||||||
|
class Basket(Document):
|
||||||
|
products = ListField(CachedReferenceField(Product, fields=['name']))
|
||||||
|
|
||||||
|
Basket.drop_collection()
|
||||||
|
product1 = Product(name='abc').save()
|
||||||
|
product2 = Product(name='def').save()
|
||||||
|
basket = Basket(products=[product1]).save()
|
||||||
|
self.assertEqual(
|
||||||
|
Basket.objects._collection.find_one(),
|
||||||
|
{
|
||||||
|
'_id': basket.pk,
|
||||||
|
'products': [
|
||||||
|
{
|
||||||
|
'_id': product1.pk,
|
||||||
|
'name': product1.name
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# push to list
|
||||||
|
basket.update(push__products=product2)
|
||||||
|
basket.reload()
|
||||||
|
self.assertEqual(
|
||||||
|
Basket.objects._collection.find_one(),
|
||||||
|
{
|
||||||
|
'_id': basket.pk,
|
||||||
|
'products': [
|
||||||
|
{
|
||||||
|
'_id': product1.pk,
|
||||||
|
'name': product1.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'_id': product2.pk,
|
||||||
|
'name': product2.name
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_cached_reference_field_update_all(self):
|
||||||
|
class Person(Document):
|
||||||
|
TYPES = (
|
||||||
|
('pf', "PF"),
|
||||||
|
('pj', "PJ")
|
||||||
|
)
|
||||||
|
name = StringField()
|
||||||
|
tp = StringField(
|
||||||
|
choices=TYPES
|
||||||
|
)
|
||||||
|
|
||||||
|
father = CachedReferenceField('self', fields=('tp',))
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
a1 = Person(name="Wilson Father", tp="pj")
|
||||||
|
a1.save()
|
||||||
|
|
||||||
|
a2 = Person(name='Wilson Junior', tp='pf', father=a1)
|
||||||
|
a2.save()
|
||||||
|
|
||||||
|
self.assertEqual(dict(a2.to_mongo()), {
|
||||||
|
"_id": a2.pk,
|
||||||
|
"name": u"Wilson Junior",
|
||||||
|
"tp": u"pf",
|
||||||
|
"father": {
|
||||||
|
"_id": a1.pk,
|
||||||
|
"tp": u"pj"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(Person.objects(father=a1)._query, {
|
||||||
|
'father._id': a1.pk
|
||||||
|
})
|
||||||
|
self.assertEqual(Person.objects(father=a1).count(), 1)
|
||||||
|
|
||||||
|
Person.objects.update(set__tp="pf")
|
||||||
|
Person.father.sync_all()
|
||||||
|
|
||||||
|
a2.reload()
|
||||||
|
self.assertEqual(dict(a2.to_mongo()), {
|
||||||
|
"_id": a2.pk,
|
||||||
|
"name": u"Wilson Junior",
|
||||||
|
"tp": u"pf",
|
||||||
|
"father": {
|
||||||
|
"_id": a1.pk,
|
||||||
|
"tp": u"pf"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_cached_reference_fields_on_embedded_documents(self):
|
||||||
|
with self.assertRaises(InvalidDocumentError):
|
||||||
|
class Test(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
type('WrongEmbeddedDocument', (
|
||||||
|
EmbeddedDocument,), {
|
||||||
|
'test': CachedReferenceField(Test)
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_cached_reference_auto_sync(self):
|
||||||
|
class Person(Document):
|
||||||
|
TYPES = (
|
||||||
|
('pf', "PF"),
|
||||||
|
('pj', "PJ")
|
||||||
|
)
|
||||||
|
name = StringField()
|
||||||
|
tp = StringField(
|
||||||
|
choices=TYPES
|
||||||
|
)
|
||||||
|
|
||||||
|
father = CachedReferenceField('self', fields=('tp',))
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
a1 = Person(name="Wilson Father", tp="pj")
|
||||||
|
a1.save()
|
||||||
|
|
||||||
|
a2 = Person(name='Wilson Junior', tp='pf', father=a1)
|
||||||
|
a2.save()
|
||||||
|
|
||||||
|
a1.tp = 'pf'
|
||||||
|
a1.save()
|
||||||
|
|
||||||
|
a2.reload()
|
||||||
|
self.assertEqual(dict(a2.to_mongo()), {
|
||||||
|
'_id': a2.pk,
|
||||||
|
'name': 'Wilson Junior',
|
||||||
|
'tp': 'pf',
|
||||||
|
'father': {
|
||||||
|
'_id': a1.pk,
|
||||||
|
'tp': 'pf'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_cached_reference_auto_sync_disabled(self):
|
||||||
|
class Persone(Document):
|
||||||
|
TYPES = (
|
||||||
|
('pf', "PF"),
|
||||||
|
('pj', "PJ")
|
||||||
|
)
|
||||||
|
name = StringField()
|
||||||
|
tp = StringField(
|
||||||
|
choices=TYPES
|
||||||
|
)
|
||||||
|
|
||||||
|
father = CachedReferenceField(
|
||||||
|
'self', fields=('tp',), auto_sync=False)
|
||||||
|
|
||||||
|
Persone.drop_collection()
|
||||||
|
|
||||||
|
a1 = Persone(name="Wilson Father", tp="pj")
|
||||||
|
a1.save()
|
||||||
|
|
||||||
|
a2 = Persone(name='Wilson Junior', tp='pf', father=a1)
|
||||||
|
a2.save()
|
||||||
|
|
||||||
|
a1.tp = 'pf'
|
||||||
|
a1.save()
|
||||||
|
|
||||||
|
self.assertEqual(Persone.objects._collection.find_one({'_id': a2.pk}), {
|
||||||
|
'_id': a2.pk,
|
||||||
|
'name': 'Wilson Junior',
|
||||||
|
'tp': 'pf',
|
||||||
|
'father': {
|
||||||
|
'_id': a1.pk,
|
||||||
|
'tp': 'pj'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_cached_reference_embedded_fields(self):
|
||||||
|
class Owner(EmbeddedDocument):
|
||||||
|
TPS = (
|
||||||
|
('n', "Normal"),
|
||||||
|
('u', "Urgent")
|
||||||
|
)
|
||||||
|
name = StringField()
|
||||||
|
tp = StringField(
|
||||||
|
verbose_name="Type",
|
||||||
|
db_field="t",
|
||||||
|
choices=TPS)
|
||||||
|
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
owner = EmbeddedDocumentField(Owner)
|
||||||
|
|
||||||
|
class Ocorrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = CachedReferenceField(
|
||||||
|
Animal, fields=['tag', 'owner.tp'])
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocorrence.drop_collection()
|
||||||
|
|
||||||
|
a = Animal(name="Leopard", tag="heavy",
|
||||||
|
owner=Owner(tp='u', name="Wilson Júnior")
|
||||||
|
)
|
||||||
|
a.save()
|
||||||
|
|
||||||
|
o = Ocorrence(person="teste", animal=a)
|
||||||
|
o.save()
|
||||||
|
self.assertEqual(dict(a.to_mongo(fields=['tag', 'owner.tp'])), {
|
||||||
|
'_id': a.pk,
|
||||||
|
'tag': 'heavy',
|
||||||
|
'owner': {
|
||||||
|
't': 'u'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertEqual(o.to_mongo()['animal']['tag'], 'heavy')
|
||||||
|
self.assertEqual(o.to_mongo()['animal']['owner']['t'], 'u')
|
||||||
|
|
||||||
|
# counts
|
||||||
|
Ocorrence(person="teste 2").save()
|
||||||
|
Ocorrence(person="teste 3").save()
|
||||||
|
|
||||||
|
count = Ocorrence.objects(
|
||||||
|
animal__tag='heavy', animal__owner__tp='u').count()
|
||||||
|
self.assertEqual(count, 1)
|
||||||
|
|
||||||
|
ocorrence = Ocorrence.objects(
|
||||||
|
animal__tag='heavy',
|
||||||
|
animal__owner__tp='u').first()
|
||||||
|
self.assertEqual(ocorrence.person, "teste")
|
||||||
|
self.assertIsInstance(ocorrence.animal, Animal)
|
||||||
|
|
||||||
|
def test_cached_reference_embedded_list_fields(self):
|
||||||
|
class Owner(EmbeddedDocument):
|
||||||
|
name = StringField()
|
||||||
|
tags = ListField(StringField())
|
||||||
|
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
owner = EmbeddedDocumentField(Owner)
|
||||||
|
|
||||||
|
class Ocorrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = CachedReferenceField(
|
||||||
|
Animal, fields=['tag', 'owner.tags'])
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocorrence.drop_collection()
|
||||||
|
|
||||||
|
a = Animal(name="Leopard", tag="heavy",
|
||||||
|
owner=Owner(tags=['cool', 'funny'],
|
||||||
|
name="Wilson Júnior")
|
||||||
|
)
|
||||||
|
a.save()
|
||||||
|
|
||||||
|
o = Ocorrence(person="teste 2", animal=a)
|
||||||
|
o.save()
|
||||||
|
self.assertEqual(dict(a.to_mongo(fields=['tag', 'owner.tags'])), {
|
||||||
|
'_id': a.pk,
|
||||||
|
'tag': 'heavy',
|
||||||
|
'owner': {
|
||||||
|
'tags': ['cool', 'funny']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(o.to_mongo()['animal']['tag'], 'heavy')
|
||||||
|
self.assertEqual(o.to_mongo()['animal']['owner']['tags'],
|
||||||
|
['cool', 'funny'])
|
||||||
|
|
||||||
|
# counts
|
||||||
|
Ocorrence(person="teste 2").save()
|
||||||
|
Ocorrence(person="teste 3").save()
|
||||||
|
|
||||||
|
query = Ocorrence.objects(
|
||||||
|
animal__tag='heavy', animal__owner__tags='cool')._query
|
||||||
|
self.assertEqual(
|
||||||
|
query, {'animal.owner.tags': 'cool', 'animal.tag': 'heavy'})
|
||||||
|
|
||||||
|
ocorrence = Ocorrence.objects(
|
||||||
|
animal__tag='heavy',
|
||||||
|
animal__owner__tags='cool').first()
|
||||||
|
self.assertEqual(ocorrence.person, "teste 2")
|
||||||
|
self.assertIsInstance(ocorrence.animal, Animal)
|
@ -4,11 +4,6 @@ import math
|
|||||||
import itertools
|
import itertools
|
||||||
import re
|
import re
|
||||||
|
|
||||||
try:
|
|
||||||
from bson.int64 import Int64
|
|
||||||
except ImportError:
|
|
||||||
Int64 = long
|
|
||||||
|
|
||||||
from mongoengine import *
|
from mongoengine import *
|
||||||
|
|
||||||
from tests.utils import MongoDBTestCase
|
from tests.utils import MongoDBTestCase
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import datetime
|
import datetime
|
||||||
import unittest
|
|
||||||
import uuid
|
|
||||||
import math
|
|
||||||
import itertools
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from nose.plugins.skip import SkipTest
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -15,18 +7,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
dateutil = None
|
dateutil = None
|
||||||
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
from bson import Binary, DBRef, ObjectId, SON
|
|
||||||
try:
|
|
||||||
from bson.int64 import Int64
|
|
||||||
except ImportError:
|
|
||||||
Int64 = long
|
|
||||||
|
|
||||||
from mongoengine import *
|
from mongoengine import *
|
||||||
from mongoengine.connection import get_db
|
|
||||||
from mongoengine.base import (BaseDict, BaseField, EmbeddedDocumentList,
|
|
||||||
_document_registry, LazyReference)
|
|
||||||
|
|
||||||
from tests.utils import MongoDBTestCase
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
@ -7,11 +7,6 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
dateutil = None
|
dateutil = None
|
||||||
|
|
||||||
try:
|
|
||||||
from bson.int64 import Int64
|
|
||||||
except ImportError:
|
|
||||||
Int64 = long
|
|
||||||
|
|
||||||
from mongoengine import *
|
from mongoengine import *
|
||||||
from mongoengine import connection
|
from mongoengine import connection
|
||||||
|
|
||||||
|
91
tests/fields/test_decimal_field.py
Normal file
91
tests/fields/test_decimal_field.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestDecimalField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_validation(self):
|
||||||
|
"""Ensure that invalid values cannot be assigned to decimal fields.
|
||||||
|
"""
|
||||||
|
class Person(Document):
|
||||||
|
height = DecimalField(min_value=Decimal('0.1'),
|
||||||
|
max_value=Decimal('3.5'))
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
Person(height=Decimal('1.89')).save()
|
||||||
|
person = Person.objects.first()
|
||||||
|
self.assertEqual(person.height, Decimal('1.89'))
|
||||||
|
|
||||||
|
person.height = '2.0'
|
||||||
|
person.save()
|
||||||
|
person.height = 0.01
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.height = Decimal('0.01')
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.height = Decimal('4.0')
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.height = 'something invalid'
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
person_2 = Person(height='something invalid')
|
||||||
|
self.assertRaises(ValidationError, person_2.validate)
|
||||||
|
|
||||||
|
def test_comparison(self):
|
||||||
|
class Person(Document):
|
||||||
|
money = DecimalField()
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
Person(money=6).save()
|
||||||
|
Person(money=7).save()
|
||||||
|
Person(money=8).save()
|
||||||
|
Person(money=10).save()
|
||||||
|
|
||||||
|
self.assertEqual(2, Person.objects(money__gt=Decimal("7")).count())
|
||||||
|
self.assertEqual(2, Person.objects(money__gt=7).count())
|
||||||
|
self.assertEqual(2, Person.objects(money__gt="7").count())
|
||||||
|
|
||||||
|
self.assertEqual(3, Person.objects(money__gte="7").count())
|
||||||
|
|
||||||
|
def test_storage(self):
|
||||||
|
class Person(Document):
|
||||||
|
float_value = DecimalField(precision=4)
|
||||||
|
string_value = DecimalField(precision=4, force_string=True)
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
values_to_store = [10, 10.1, 10.11, "10.111", Decimal("10.1111"), Decimal("10.11111")]
|
||||||
|
for store_at_creation in [True, False]:
|
||||||
|
for value in values_to_store:
|
||||||
|
# to_python is called explicitly if values were sent in the kwargs of __init__
|
||||||
|
if store_at_creation:
|
||||||
|
Person(float_value=value, string_value=value).save()
|
||||||
|
else:
|
||||||
|
person = Person.objects.create()
|
||||||
|
person.float_value = value
|
||||||
|
person.string_value = value
|
||||||
|
person.save()
|
||||||
|
|
||||||
|
# How its stored
|
||||||
|
expected = [
|
||||||
|
{'float_value': 10.0, 'string_value': '10.0000'},
|
||||||
|
{'float_value': 10.1, 'string_value': '10.1000'},
|
||||||
|
{'float_value': 10.11, 'string_value': '10.1100'},
|
||||||
|
{'float_value': 10.111, 'string_value': '10.1110'},
|
||||||
|
{'float_value': 10.1111, 'string_value': '10.1111'},
|
||||||
|
{'float_value': 10.1111, 'string_value': '10.1111'}]
|
||||||
|
expected.extend(expected)
|
||||||
|
actual = list(Person.objects.exclude('id').as_pymongo())
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
# How it comes out locally
|
||||||
|
expected = [Decimal('10.0000'), Decimal('10.1000'), Decimal('10.1100'),
|
||||||
|
Decimal('10.1110'), Decimal('10.1111'), Decimal('10.1111')]
|
||||||
|
expected.extend(expected)
|
||||||
|
for field_name in ['float_value', 'string_value']:
|
||||||
|
actual = list(Person.objects().scalar(field_name))
|
||||||
|
self.assertEqual(expected, actual)
|
303
tests/fields/test_dict_field.py
Normal file
303
tests/fields/test_dict_field.py
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from mongoengine import *
|
||||||
|
from mongoengine.base import BaseDict
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase, get_as_pymongo
|
||||||
|
|
||||||
|
|
||||||
|
class TestDictField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_storage(self):
|
||||||
|
class BlogPost(Document):
|
||||||
|
info = DictField()
|
||||||
|
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
info = {'testkey': 'testvalue'}
|
||||||
|
post = BlogPost(info=info).save()
|
||||||
|
self.assertEqual(
|
||||||
|
get_as_pymongo(post),
|
||||||
|
{
|
||||||
|
'_id': post.id,
|
||||||
|
'info': info
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_general_things(self):
|
||||||
|
"""Ensure that dict types work as expected."""
|
||||||
|
class BlogPost(Document):
|
||||||
|
info = DictField()
|
||||||
|
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
post = BlogPost()
|
||||||
|
post.info = 'my post'
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = ['test', 'test']
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {'$title': 'test'}
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {'nested': {'$title': 'test'}}
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {'the.title': 'test'}
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {'nested': {'the.title': 'test'}}
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {1: 'test'}
|
||||||
|
self.assertRaises(ValidationError, post.validate)
|
||||||
|
|
||||||
|
post.info = {'title': 'test'}
|
||||||
|
post.save()
|
||||||
|
|
||||||
|
post = BlogPost()
|
||||||
|
post.info = {'title': 'dollar_sign', 'details': {'te$t': 'test'}}
|
||||||
|
post.save()
|
||||||
|
|
||||||
|
post = BlogPost()
|
||||||
|
post.info = {'details': {'test': 'test'}}
|
||||||
|
post.save()
|
||||||
|
|
||||||
|
post = BlogPost()
|
||||||
|
post.info = {'details': {'test': 3}}
|
||||||
|
post.save()
|
||||||
|
|
||||||
|
self.assertEqual(BlogPost.objects.count(), 4)
|
||||||
|
self.assertEqual(
|
||||||
|
BlogPost.objects.filter(info__title__exact='test').count(), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
BlogPost.objects.filter(info__details__test__exact='test').count(), 1)
|
||||||
|
|
||||||
|
post = BlogPost.objects.filter(info__title__exact='dollar_sign').first()
|
||||||
|
self.assertIn('te$t', post['info']['details'])
|
||||||
|
|
||||||
|
# Confirm handles non strings or non existing keys
|
||||||
|
self.assertEqual(
|
||||||
|
BlogPost.objects.filter(info__details__test__exact=5).count(), 0)
|
||||||
|
self.assertEqual(
|
||||||
|
BlogPost.objects.filter(info__made_up__test__exact='test').count(), 0)
|
||||||
|
|
||||||
|
post = BlogPost.objects.create(info={'title': 'original'})
|
||||||
|
post.info.update({'title': 'updated'})
|
||||||
|
post.save()
|
||||||
|
post.reload()
|
||||||
|
self.assertEqual('updated', post.info['title'])
|
||||||
|
|
||||||
|
post.info.setdefault('authors', [])
|
||||||
|
post.save()
|
||||||
|
post.reload()
|
||||||
|
self.assertEqual([], post.info['authors'])
|
||||||
|
|
||||||
|
def test_dictfield_dump_document(self):
|
||||||
|
"""Ensure a DictField can handle another document's dump."""
|
||||||
|
class Doc(Document):
|
||||||
|
field = DictField()
|
||||||
|
|
||||||
|
class ToEmbed(Document):
|
||||||
|
id = IntField(primary_key=True, default=1)
|
||||||
|
recursive = DictField()
|
||||||
|
|
||||||
|
class ToEmbedParent(Document):
|
||||||
|
id = IntField(primary_key=True, default=1)
|
||||||
|
recursive = DictField()
|
||||||
|
|
||||||
|
meta = {'allow_inheritance': True}
|
||||||
|
|
||||||
|
class ToEmbedChild(ToEmbedParent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
to_embed_recursive = ToEmbed(id=1).save()
|
||||||
|
to_embed = ToEmbed(
|
||||||
|
id=2, recursive=to_embed_recursive.to_mongo().to_dict()).save()
|
||||||
|
doc = Doc(field=to_embed.to_mongo().to_dict())
|
||||||
|
doc.save()
|
||||||
|
assert isinstance(doc.field, dict)
|
||||||
|
assert doc.field == {'_id': 2, 'recursive': {'_id': 1, 'recursive': {}}}
|
||||||
|
# Same thing with a Document with a _cls field
|
||||||
|
to_embed_recursive = ToEmbedChild(id=1).save()
|
||||||
|
to_embed_child = ToEmbedChild(
|
||||||
|
id=2, recursive=to_embed_recursive.to_mongo().to_dict()).save()
|
||||||
|
doc = Doc(field=to_embed_child.to_mongo().to_dict())
|
||||||
|
doc.save()
|
||||||
|
assert isinstance(doc.field, dict)
|
||||||
|
assert doc.field == {
|
||||||
|
'_id': 2, '_cls': 'ToEmbedParent.ToEmbedChild',
|
||||||
|
'recursive': {'_id': 1, '_cls': 'ToEmbedParent.ToEmbedChild', 'recursive': {}}
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_dictfield_strict(self):
|
||||||
|
"""Ensure that dict field handles validation if provided a strict field type."""
|
||||||
|
class Simple(Document):
|
||||||
|
mapping = DictField(field=IntField())
|
||||||
|
|
||||||
|
Simple.drop_collection()
|
||||||
|
|
||||||
|
e = Simple()
|
||||||
|
e.mapping['someint'] = 1
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
# try creating an invalid mapping
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
e.mapping['somestring'] = "abc"
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
def test_dictfield_complex(self):
|
||||||
|
"""Ensure that the dict field can handle the complex types."""
|
||||||
|
class SettingBase(EmbeddedDocument):
|
||||||
|
meta = {'allow_inheritance': True}
|
||||||
|
|
||||||
|
class StringSetting(SettingBase):
|
||||||
|
value = StringField()
|
||||||
|
|
||||||
|
class IntegerSetting(SettingBase):
|
||||||
|
value = IntField()
|
||||||
|
|
||||||
|
class Simple(Document):
|
||||||
|
mapping = DictField()
|
||||||
|
|
||||||
|
Simple.drop_collection()
|
||||||
|
|
||||||
|
e = Simple()
|
||||||
|
e.mapping['somestring'] = StringSetting(value='foo')
|
||||||
|
e.mapping['someint'] = IntegerSetting(value=42)
|
||||||
|
e.mapping['nested_dict'] = {'number': 1, 'string': 'Hi!',
|
||||||
|
'float': 1.001,
|
||||||
|
'complex': IntegerSetting(value=42),
|
||||||
|
'list': [IntegerSetting(value=42),
|
||||||
|
StringSetting(value='foo')]}
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
e2 = Simple.objects.get(id=e.id)
|
||||||
|
self.assertIsInstance(e2.mapping['somestring'], StringSetting)
|
||||||
|
self.assertIsInstance(e2.mapping['someint'], IntegerSetting)
|
||||||
|
|
||||||
|
# Test querying
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__someint__value=42).count(), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__number=1).count(), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__complex__value=42).count(), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__list__0__value=42).count(), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__list__1__value='foo').count(), 1)
|
||||||
|
|
||||||
|
# Confirm can update
|
||||||
|
Simple.objects().update(
|
||||||
|
set__mapping={"someint": IntegerSetting(value=10)})
|
||||||
|
Simple.objects().update(
|
||||||
|
set__mapping__nested_dict__list__1=StringSetting(value='Boo'))
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__list__1__value='foo').count(), 0)
|
||||||
|
self.assertEqual(
|
||||||
|
Simple.objects.filter(mapping__nested_dict__list__1__value='Boo').count(), 1)
|
||||||
|
|
||||||
|
def test_ensure_unique_default_instances(self):
|
||||||
|
"""Ensure that every field has it's own unique default instance."""
|
||||||
|
class D(Document):
|
||||||
|
data = DictField()
|
||||||
|
data2 = DictField(default=lambda: {})
|
||||||
|
|
||||||
|
d1 = D()
|
||||||
|
d1.data['foo'] = 'bar'
|
||||||
|
d1.data2['foo'] = 'bar'
|
||||||
|
d2 = D()
|
||||||
|
self.assertEqual(d2.data, {})
|
||||||
|
self.assertEqual(d2.data2, {})
|
||||||
|
|
||||||
|
def test_dict_field_invalid_dict_value(self):
|
||||||
|
class DictFieldTest(Document):
|
||||||
|
dictionary = DictField(required=True)
|
||||||
|
|
||||||
|
DictFieldTest.drop_collection()
|
||||||
|
|
||||||
|
test = DictFieldTest(dictionary=None)
|
||||||
|
test.dictionary # Just access to test getter
|
||||||
|
self.assertRaises(ValidationError, test.validate)
|
||||||
|
|
||||||
|
test = DictFieldTest(dictionary=False)
|
||||||
|
test.dictionary # Just access to test getter
|
||||||
|
self.assertRaises(ValidationError, test.validate)
|
||||||
|
|
||||||
|
def test_dict_field_raises_validation_error_if_wrongly_assign_embedded_doc(self):
|
||||||
|
class DictFieldTest(Document):
|
||||||
|
dictionary = DictField(required=True)
|
||||||
|
|
||||||
|
DictFieldTest.drop_collection()
|
||||||
|
|
||||||
|
class Embedded(EmbeddedDocument):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
embed = Embedded(name='garbage')
|
||||||
|
doc = DictFieldTest(dictionary=embed)
|
||||||
|
with self.assertRaises(ValidationError) as ctx_err:
|
||||||
|
doc.validate()
|
||||||
|
self.assertIn("'dictionary'", str(ctx_err.exception))
|
||||||
|
self.assertIn('Only dictionaries may be used in a DictField', str(ctx_err.exception))
|
||||||
|
|
||||||
|
def test_atomic_update_dict_field(self):
|
||||||
|
"""Ensure that the entire DictField can be atomically updated."""
|
||||||
|
class Simple(Document):
|
||||||
|
mapping = DictField(field=ListField(IntField(required=True)))
|
||||||
|
|
||||||
|
Simple.drop_collection()
|
||||||
|
|
||||||
|
e = Simple()
|
||||||
|
e.mapping['someints'] = [1, 2]
|
||||||
|
e.save()
|
||||||
|
e.update(set__mapping={"ints": [3, 4]})
|
||||||
|
e.reload()
|
||||||
|
self.assertEqual(BaseDict, type(e.mapping))
|
||||||
|
self.assertEqual({"ints": [3, 4]}, e.mapping)
|
||||||
|
|
||||||
|
# try creating an invalid mapping
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e.update(set__mapping={"somestrings": ["foo", "bar", ]})
|
||||||
|
|
||||||
|
def test_dictfield_with_referencefield_complex_nesting_cases(self):
|
||||||
|
"""Ensure complex nesting inside DictField handles dereferencing of ReferenceField(dbref=True | False)"""
|
||||||
|
# Relates to Issue #1453
|
||||||
|
class Doc(Document):
|
||||||
|
s = StringField()
|
||||||
|
|
||||||
|
class Simple(Document):
|
||||||
|
mapping0 = DictField(ReferenceField(Doc, dbref=True))
|
||||||
|
mapping1 = DictField(ReferenceField(Doc, dbref=False))
|
||||||
|
mapping2 = DictField(ListField(ReferenceField(Doc, dbref=True)))
|
||||||
|
mapping3 = DictField(ListField(ReferenceField(Doc, dbref=False)))
|
||||||
|
mapping4 = DictField(DictField(field=ReferenceField(Doc, dbref=True)))
|
||||||
|
mapping5 = DictField(DictField(field=ReferenceField(Doc, dbref=False)))
|
||||||
|
mapping6 = DictField(ListField(DictField(ReferenceField(Doc, dbref=True))))
|
||||||
|
mapping7 = DictField(ListField(DictField(ReferenceField(Doc, dbref=False))))
|
||||||
|
mapping8 = DictField(ListField(DictField(ListField(ReferenceField(Doc, dbref=True)))))
|
||||||
|
mapping9 = DictField(ListField(DictField(ListField(ReferenceField(Doc, dbref=False)))))
|
||||||
|
|
||||||
|
Doc.drop_collection()
|
||||||
|
Simple.drop_collection()
|
||||||
|
|
||||||
|
d = Doc(s='aa').save()
|
||||||
|
e = Simple()
|
||||||
|
e.mapping0['someint'] = e.mapping1['someint'] = d
|
||||||
|
e.mapping2['someint'] = e.mapping3['someint'] = [d]
|
||||||
|
e.mapping4['someint'] = e.mapping5['someint'] = {'d': d}
|
||||||
|
e.mapping6['someint'] = e.mapping7['someint'] = [{'d': d}]
|
||||||
|
e.mapping8['someint'] = e.mapping9['someint'] = [{'d': [d]}]
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
s = Simple.objects.first()
|
||||||
|
self.assertIsInstance(s.mapping0['someint'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping1['someint'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping2['someint'][0], Doc)
|
||||||
|
self.assertIsInstance(s.mapping3['someint'][0], Doc)
|
||||||
|
self.assertIsInstance(s.mapping4['someint']['d'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping5['someint']['d'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping6['someint'][0]['d'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping7['someint'][0]['d'], Doc)
|
||||||
|
self.assertIsInstance(s.mapping8['someint'][0]['d'][0], Doc)
|
||||||
|
self.assertIsInstance(s.mapping9['someint'][0]['d'][0], Doc)
|
120
tests/fields/test_email_field.py
Normal file
120
tests/fields/test_email_field.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
from unittest import SkipTest
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestEmailField(MongoDBTestCase):
|
||||||
|
def test_generic_behavior(self):
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField()
|
||||||
|
|
||||||
|
user = User(email='ross@example.com')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
user = User(email='ross@example.co.uk')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
user = User(email=('Kofq@rhom0e4klgauOhpbpNdogawnyIKvQS0wk2mjqrgGQ5S'
|
||||||
|
'aJIazqqWkm7.net'))
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
user = User(email='new-tld@example.technology')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
user = User(email='ross@example.com.')
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# unicode domain
|
||||||
|
user = User(email=u'user@пример.рф')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
# invalid unicode domain
|
||||||
|
user = User(email=u'user@пример')
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# invalid data type
|
||||||
|
user = User(email=123)
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
def test_email_field_unicode_user(self):
|
||||||
|
# Don't run this test on pypy3, which doesn't support unicode regex:
|
||||||
|
# https://bitbucket.org/pypy/pypy/issues/1821/regular-expression-doesnt-find-unicode
|
||||||
|
if sys.version_info[:2] == (3, 2):
|
||||||
|
raise SkipTest('unicode email addresses are not supported on PyPy 3')
|
||||||
|
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField()
|
||||||
|
|
||||||
|
# unicode user shouldn't validate by default...
|
||||||
|
user = User(email=u'Dörte@Sörensen.example.com')
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# ...but it should be fine with allow_utf8_user set to True
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField(allow_utf8_user=True)
|
||||||
|
|
||||||
|
user = User(email=u'Dörte@Sörensen.example.com')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
def test_email_field_domain_whitelist(self):
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField()
|
||||||
|
|
||||||
|
# localhost domain shouldn't validate by default...
|
||||||
|
user = User(email='me@localhost')
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# ...but it should be fine if it's whitelisted
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField(domain_whitelist=['localhost'])
|
||||||
|
|
||||||
|
user = User(email='me@localhost')
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
def test_email_field_ip_domain(self):
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField()
|
||||||
|
|
||||||
|
valid_ipv4 = 'email@[127.0.0.1]'
|
||||||
|
valid_ipv6 = 'email@[2001:dB8::1]'
|
||||||
|
invalid_ip = 'email@[324.0.0.1]'
|
||||||
|
|
||||||
|
# IP address as a domain shouldn't validate by default...
|
||||||
|
user = User(email=valid_ipv4)
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
user = User(email=valid_ipv6)
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
user = User(email=invalid_ip)
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# ...but it should be fine with allow_ip_domain set to True
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField(allow_ip_domain=True)
|
||||||
|
|
||||||
|
user = User(email=valid_ipv4)
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
user = User(email=valid_ipv6)
|
||||||
|
user.validate()
|
||||||
|
|
||||||
|
# invalid IP should still fail validation
|
||||||
|
user = User(email=invalid_ip)
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
def test_email_field_honors_regex(self):
|
||||||
|
class User(Document):
|
||||||
|
email = EmailField(regex=r'\w+@example.com')
|
||||||
|
|
||||||
|
# Fails regex validation
|
||||||
|
user = User(email='me@foo.com')
|
||||||
|
self.assertRaises(ValidationError, user.validate)
|
||||||
|
|
||||||
|
# Passes regex validation
|
||||||
|
user = User(email='me@example.com')
|
||||||
|
self.assertIsNone(user.validate())
|
144
tests/fields/test_map_field.py
Normal file
144
tests/fields/test_map_field.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestMapField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_mapfield(self):
|
||||||
|
"""Ensure that the MapField handles the declared type."""
|
||||||
|
class Simple(Document):
|
||||||
|
mapping = MapField(IntField())
|
||||||
|
|
||||||
|
Simple.drop_collection()
|
||||||
|
|
||||||
|
e = Simple()
|
||||||
|
e.mapping['someint'] = 1
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
e.mapping['somestring'] = "abc"
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
class NoDeclaredType(Document):
|
||||||
|
mapping = MapField()
|
||||||
|
|
||||||
|
def test_complex_mapfield(self):
|
||||||
|
"""Ensure that the MapField can handle complex declared types."""
|
||||||
|
|
||||||
|
class SettingBase(EmbeddedDocument):
|
||||||
|
meta = {"allow_inheritance": True}
|
||||||
|
|
||||||
|
class StringSetting(SettingBase):
|
||||||
|
value = StringField()
|
||||||
|
|
||||||
|
class IntegerSetting(SettingBase):
|
||||||
|
value = IntField()
|
||||||
|
|
||||||
|
class Extensible(Document):
|
||||||
|
mapping = MapField(EmbeddedDocumentField(SettingBase))
|
||||||
|
|
||||||
|
Extensible.drop_collection()
|
||||||
|
|
||||||
|
e = Extensible()
|
||||||
|
e.mapping['somestring'] = StringSetting(value='foo')
|
||||||
|
e.mapping['someint'] = IntegerSetting(value=42)
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
e2 = Extensible.objects.get(id=e.id)
|
||||||
|
self.assertIsInstance(e2.mapping['somestring'], StringSetting)
|
||||||
|
self.assertIsInstance(e2.mapping['someint'], IntegerSetting)
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
e.mapping['someint'] = 123
|
||||||
|
e.save()
|
||||||
|
|
||||||
|
def test_embedded_mapfield_db_field(self):
|
||||||
|
class Embedded(EmbeddedDocument):
|
||||||
|
number = IntField(default=0, db_field='i')
|
||||||
|
|
||||||
|
class Test(Document):
|
||||||
|
my_map = MapField(field=EmbeddedDocumentField(Embedded),
|
||||||
|
db_field='x')
|
||||||
|
|
||||||
|
Test.drop_collection()
|
||||||
|
|
||||||
|
test = Test()
|
||||||
|
test.my_map['DICTIONARY_KEY'] = Embedded(number=1)
|
||||||
|
test.save()
|
||||||
|
|
||||||
|
Test.objects.update_one(inc__my_map__DICTIONARY_KEY__number=1)
|
||||||
|
|
||||||
|
test = Test.objects.get()
|
||||||
|
self.assertEqual(test.my_map['DICTIONARY_KEY'].number, 2)
|
||||||
|
doc = self.db.test.find_one()
|
||||||
|
self.assertEqual(doc['x']['DICTIONARY_KEY']['i'], 2)
|
||||||
|
|
||||||
|
def test_mapfield_numerical_index(self):
|
||||||
|
"""Ensure that MapField accept numeric strings as indexes."""
|
||||||
|
|
||||||
|
class Embedded(EmbeddedDocument):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Test(Document):
|
||||||
|
my_map = MapField(EmbeddedDocumentField(Embedded))
|
||||||
|
|
||||||
|
Test.drop_collection()
|
||||||
|
|
||||||
|
test = Test()
|
||||||
|
test.my_map['1'] = Embedded(name='test')
|
||||||
|
test.save()
|
||||||
|
test.my_map['1'].name = 'test updated'
|
||||||
|
test.save()
|
||||||
|
|
||||||
|
def test_map_field_lookup(self):
|
||||||
|
"""Ensure MapField lookups succeed on Fields without a lookup
|
||||||
|
method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Action(EmbeddedDocument):
|
||||||
|
operation = StringField()
|
||||||
|
object = StringField()
|
||||||
|
|
||||||
|
class Log(Document):
|
||||||
|
name = StringField()
|
||||||
|
visited = MapField(DateTimeField())
|
||||||
|
actions = MapField(EmbeddedDocumentField(Action))
|
||||||
|
|
||||||
|
Log.drop_collection()
|
||||||
|
Log(name="wilson", visited={'friends': datetime.datetime.now()},
|
||||||
|
actions={'friends': Action(operation='drink', object='beer')}).save()
|
||||||
|
|
||||||
|
self.assertEqual(1, Log.objects(
|
||||||
|
visited__friends__exists=True).count())
|
||||||
|
|
||||||
|
self.assertEqual(1, Log.objects(
|
||||||
|
actions__friends__operation='drink',
|
||||||
|
actions__friends__object='beer').count())
|
||||||
|
|
||||||
|
def test_map_field_unicode(self):
|
||||||
|
class Info(EmbeddedDocument):
|
||||||
|
description = StringField()
|
||||||
|
value_list = ListField(field=StringField())
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
info_dict = MapField(field=EmbeddedDocumentField(Info))
|
||||||
|
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
tree = BlogPost(info_dict={
|
||||||
|
u"éééé": {
|
||||||
|
'description': u"VALUE: éééé"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tree.save()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
BlogPost.objects.get(id=tree.id).info_dict[u"éééé"].description,
|
||||||
|
u"VALUE: éééé"
|
||||||
|
)
|
219
tests/fields/test_reference_field.py
Normal file
219
tests/fields/test_reference_field.py
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from bson import SON, DBRef
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestReferenceField(MongoDBTestCase):
|
||||||
|
def test_reference_validation(self):
|
||||||
|
"""Ensure that invalid document objects cannot be assigned to
|
||||||
|
reference fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class User(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
content = StringField()
|
||||||
|
author = ReferenceField(User)
|
||||||
|
|
||||||
|
User.drop_collection()
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
# Make sure ReferenceField only accepts a document class or a string
|
||||||
|
# with a document class name.
|
||||||
|
self.assertRaises(ValidationError, ReferenceField, EmbeddedDocument)
|
||||||
|
|
||||||
|
user = User(name='Test User')
|
||||||
|
|
||||||
|
# Ensure that the referenced object must have been saved
|
||||||
|
post1 = BlogPost(content='Chips and gravy taste good.')
|
||||||
|
post1.author = user
|
||||||
|
self.assertRaises(ValidationError, post1.save)
|
||||||
|
|
||||||
|
# Check that an invalid object type cannot be used
|
||||||
|
post2 = BlogPost(content='Chips and chilli taste good.')
|
||||||
|
post1.author = post2
|
||||||
|
self.assertRaises(ValidationError, post1.validate)
|
||||||
|
|
||||||
|
# Ensure ObjectID's are accepted as references
|
||||||
|
user_object_id = user.pk
|
||||||
|
post3 = BlogPost(content="Chips and curry sauce taste good.")
|
||||||
|
post3.author = user_object_id
|
||||||
|
post3.save()
|
||||||
|
|
||||||
|
# Make sure referencing a saved document of the right type works
|
||||||
|
user.save()
|
||||||
|
post1.author = user
|
||||||
|
post1.save()
|
||||||
|
|
||||||
|
# Make sure referencing a saved document of the *wrong* type fails
|
||||||
|
post2.save()
|
||||||
|
post1.author = post2
|
||||||
|
self.assertRaises(ValidationError, post1.validate)
|
||||||
|
|
||||||
|
def test_objectid_reference_fields(self):
|
||||||
|
"""Make sure storing Object ID references works."""
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
name = StringField()
|
||||||
|
parent = ReferenceField('self')
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
p1 = Person(name="John").save()
|
||||||
|
Person(name="Ross", parent=p1.pk).save()
|
||||||
|
|
||||||
|
p = Person.objects.get(name="Ross")
|
||||||
|
self.assertEqual(p.parent, p1)
|
||||||
|
|
||||||
|
def test_dbref_reference_fields(self):
|
||||||
|
"""Make sure storing references as bson.dbref.DBRef works."""
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
name = StringField()
|
||||||
|
parent = ReferenceField('self', dbref=True)
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
p1 = Person(name="John").save()
|
||||||
|
Person(name="Ross", parent=p1).save()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
Person._get_collection().find_one({'name': 'Ross'})['parent'],
|
||||||
|
DBRef('person', p1.pk)
|
||||||
|
)
|
||||||
|
|
||||||
|
p = Person.objects.get(name="Ross")
|
||||||
|
self.assertEqual(p.parent, p1)
|
||||||
|
|
||||||
|
def test_dbref_to_mongo(self):
|
||||||
|
"""Make sure that calling to_mongo on a ReferenceField which
|
||||||
|
has dbref=False, but actually actually contains a DBRef returns
|
||||||
|
an ID of that DBRef.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
name = StringField()
|
||||||
|
parent = ReferenceField('self', dbref=False)
|
||||||
|
|
||||||
|
p = Person(
|
||||||
|
name='Steve',
|
||||||
|
parent=DBRef('person', 'abcdefghijklmnop')
|
||||||
|
)
|
||||||
|
self.assertEqual(p.to_mongo(), SON([
|
||||||
|
('name', u'Steve'),
|
||||||
|
('parent', 'abcdefghijklmnop')
|
||||||
|
]))
|
||||||
|
|
||||||
|
def test_objectid_reference_fields(self):
|
||||||
|
class Person(Document):
|
||||||
|
name = StringField()
|
||||||
|
parent = ReferenceField('self', dbref=False)
|
||||||
|
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
p1 = Person(name="John").save()
|
||||||
|
Person(name="Ross", parent=p1).save()
|
||||||
|
|
||||||
|
col = Person._get_collection()
|
||||||
|
data = col.find_one({'name': 'Ross'})
|
||||||
|
self.assertEqual(data['parent'], p1.pk)
|
||||||
|
|
||||||
|
p = Person.objects.get(name="Ross")
|
||||||
|
self.assertEqual(p.parent, p1)
|
||||||
|
|
||||||
|
def test_undefined_reference(self):
|
||||||
|
"""Ensure that ReferenceFields may reference undefined Documents.
|
||||||
|
"""
|
||||||
|
class Product(Document):
|
||||||
|
name = StringField()
|
||||||
|
company = ReferenceField('Company')
|
||||||
|
|
||||||
|
class Company(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
Product.drop_collection()
|
||||||
|
Company.drop_collection()
|
||||||
|
|
||||||
|
ten_gen = Company(name='10gen')
|
||||||
|
ten_gen.save()
|
||||||
|
mongodb = Product(name='MongoDB', company=ten_gen)
|
||||||
|
mongodb.save()
|
||||||
|
|
||||||
|
me = Product(name='MongoEngine')
|
||||||
|
me.save()
|
||||||
|
|
||||||
|
obj = Product.objects(company=ten_gen).first()
|
||||||
|
self.assertEqual(obj, mongodb)
|
||||||
|
self.assertEqual(obj.company, ten_gen)
|
||||||
|
|
||||||
|
obj = Product.objects(company=None).first()
|
||||||
|
self.assertEqual(obj, me)
|
||||||
|
|
||||||
|
obj = Product.objects.get(company=None)
|
||||||
|
self.assertEqual(obj, me)
|
||||||
|
|
||||||
|
def test_reference_query_conversion(self):
|
||||||
|
"""Ensure that ReferenceFields can be queried using objects and values
|
||||||
|
of the type of the primary key of the referenced object.
|
||||||
|
"""
|
||||||
|
class Member(Document):
|
||||||
|
user_num = IntField(primary_key=True)
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
title = StringField()
|
||||||
|
author = ReferenceField(Member, dbref=False)
|
||||||
|
|
||||||
|
Member.drop_collection()
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
m1 = Member(user_num=1)
|
||||||
|
m1.save()
|
||||||
|
m2 = Member(user_num=2)
|
||||||
|
m2.save()
|
||||||
|
|
||||||
|
post1 = BlogPost(title='post 1', author=m1)
|
||||||
|
post1.save()
|
||||||
|
|
||||||
|
post2 = BlogPost(title='post 2', author=m2)
|
||||||
|
post2.save()
|
||||||
|
|
||||||
|
post = BlogPost.objects(author=m1).first()
|
||||||
|
self.assertEqual(post.id, post1.id)
|
||||||
|
|
||||||
|
post = BlogPost.objects(author=m2).first()
|
||||||
|
self.assertEqual(post.id, post2.id)
|
||||||
|
|
||||||
|
def test_reference_query_conversion_dbref(self):
|
||||||
|
"""Ensure that ReferenceFields can be queried using objects and values
|
||||||
|
of the type of the primary key of the referenced object.
|
||||||
|
"""
|
||||||
|
class Member(Document):
|
||||||
|
user_num = IntField(primary_key=True)
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
title = StringField()
|
||||||
|
author = ReferenceField(Member, dbref=True)
|
||||||
|
|
||||||
|
Member.drop_collection()
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
m1 = Member(user_num=1)
|
||||||
|
m1.save()
|
||||||
|
m2 = Member(user_num=2)
|
||||||
|
m2.save()
|
||||||
|
|
||||||
|
post1 = BlogPost(title='post 1', author=m1)
|
||||||
|
post1.save()
|
||||||
|
|
||||||
|
post2 = BlogPost(title='post 2', author=m2)
|
||||||
|
post2.save()
|
||||||
|
|
||||||
|
post = BlogPost.objects(author=m1).first()
|
||||||
|
self.assertEqual(post.id, post1.id)
|
||||||
|
|
||||||
|
post = BlogPost.objects(author=m2).first()
|
||||||
|
self.assertEqual(post.id, post2.id)
|
271
tests/fields/test_sequence_field.py
Normal file
271
tests/fields/test_sequence_field.py
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestSequenceField(MongoDBTestCase):
|
||||||
|
def test_sequence_field(self):
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
ids = [i.id for i in Person.objects]
|
||||||
|
self.assertEqual(ids, range(1, 11))
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
Person.id.set_next_value(1000)
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 1000)
|
||||||
|
|
||||||
|
def test_sequence_field_get_next_value(self):
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
self.assertEqual(Person.id.get_next_value(), 11)
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
|
||||||
|
self.assertEqual(Person.id.get_next_value(), 1)
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True, value_decorator=str)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
self.assertEqual(Person.id.get_next_value(), '11')
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
|
||||||
|
self.assertEqual(Person.id.get_next_value(), '1')
|
||||||
|
|
||||||
|
def test_sequence_field_sequence_name(self):
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True, sequence_name='jelly')
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'jelly.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
ids = [i.id for i in Person.objects]
|
||||||
|
self.assertEqual(ids, range(1, 11))
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'jelly.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
Person.id.set_next_value(1000)
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'jelly.id'})
|
||||||
|
self.assertEqual(c['next'], 1000)
|
||||||
|
|
||||||
|
def test_multiple_sequence_fields(self):
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True)
|
||||||
|
counter = SequenceField()
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
ids = [i.id for i in Person.objects]
|
||||||
|
self.assertEqual(ids, range(1, 11))
|
||||||
|
|
||||||
|
counters = [i.counter for i in Person.objects]
|
||||||
|
self.assertEqual(counters, range(1, 11))
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
Person.id.set_next_value(1000)
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 1000)
|
||||||
|
|
||||||
|
Person.counter.set_next_value(999)
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.counter'})
|
||||||
|
self.assertEqual(c['next'], 999)
|
||||||
|
|
||||||
|
def test_sequence_fields_reload(self):
|
||||||
|
class Animal(Document):
|
||||||
|
counter = SequenceField()
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Animal.drop_collection()
|
||||||
|
|
||||||
|
a = Animal(name="Boi").save()
|
||||||
|
|
||||||
|
self.assertEqual(a.counter, 1)
|
||||||
|
a.reload()
|
||||||
|
self.assertEqual(a.counter, 1)
|
||||||
|
|
||||||
|
a.counter = None
|
||||||
|
self.assertEqual(a.counter, 2)
|
||||||
|
a.save()
|
||||||
|
|
||||||
|
self.assertEqual(a.counter, 2)
|
||||||
|
|
||||||
|
a = Animal.objects.first()
|
||||||
|
self.assertEqual(a.counter, 2)
|
||||||
|
a.reload()
|
||||||
|
self.assertEqual(a.counter, 2)
|
||||||
|
|
||||||
|
def test_multiple_sequence_fields_on_docs(self):
|
||||||
|
class Animal(Document):
|
||||||
|
id = SequenceField(primary_key=True)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Animal.drop_collection()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
Animal(name="Animal %s" % x).save()
|
||||||
|
Person(name="Person %s" % x).save()
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'animal.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
ids = [i.id for i in Person.objects]
|
||||||
|
self.assertEqual(ids, range(1, 11))
|
||||||
|
|
||||||
|
id = [i.id for i in Animal.objects]
|
||||||
|
self.assertEqual(id, range(1, 11))
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'animal.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
def test_sequence_field_value_decorator(self):
|
||||||
|
class Person(Document):
|
||||||
|
id = SequenceField(primary_key=True, value_decorator=str)
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
for x in range(10):
|
||||||
|
p = Person(name="Person %s" % x)
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
ids = [i.id for i in Person.objects]
|
||||||
|
self.assertEqual(ids, map(str, range(1, 11)))
|
||||||
|
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'person.id'})
|
||||||
|
self.assertEqual(c['next'], 10)
|
||||||
|
|
||||||
|
def test_embedded_sequence_field(self):
|
||||||
|
class Comment(EmbeddedDocument):
|
||||||
|
id = SequenceField()
|
||||||
|
content = StringField(required=True)
|
||||||
|
|
||||||
|
class Post(Document):
|
||||||
|
title = StringField(required=True)
|
||||||
|
comments = ListField(EmbeddedDocumentField(Comment))
|
||||||
|
|
||||||
|
self.db['mongoengine.counters'].drop()
|
||||||
|
Post.drop_collection()
|
||||||
|
|
||||||
|
Post(title="MongoEngine",
|
||||||
|
comments=[Comment(content="NoSQL Rocks"),
|
||||||
|
Comment(content="MongoEngine Rocks")]).save()
|
||||||
|
c = self.db['mongoengine.counters'].find_one({'_id': 'comment.id'})
|
||||||
|
self.assertEqual(c['next'], 2)
|
||||||
|
post = Post.objects.first()
|
||||||
|
self.assertEqual(1, post.comments[0].id)
|
||||||
|
self.assertEqual(2, post.comments[1].id)
|
||||||
|
|
||||||
|
def test_inherited_sequencefield(self):
|
||||||
|
class Base(Document):
|
||||||
|
name = StringField()
|
||||||
|
counter = SequenceField()
|
||||||
|
meta = {'abstract': True}
|
||||||
|
|
||||||
|
class Foo(Base):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Bar(Base):
|
||||||
|
pass
|
||||||
|
|
||||||
|
bar = Bar(name='Bar')
|
||||||
|
bar.save()
|
||||||
|
|
||||||
|
foo = Foo(name='Foo')
|
||||||
|
foo.save()
|
||||||
|
|
||||||
|
self.assertTrue('base.counter' in
|
||||||
|
self.db['mongoengine.counters'].find().distinct('_id'))
|
||||||
|
self.assertFalse(('foo.counter' or 'bar.counter') in
|
||||||
|
self.db['mongoengine.counters'].find().distinct('_id'))
|
||||||
|
self.assertNotEqual(foo.counter, bar.counter)
|
||||||
|
self.assertEqual(foo._fields['counter'].owner_document, Base)
|
||||||
|
self.assertEqual(bar._fields['counter'].owner_document, Base)
|
||||||
|
|
||||||
|
def test_no_inherited_sequencefield(self):
|
||||||
|
class Base(Document):
|
||||||
|
name = StringField()
|
||||||
|
meta = {'abstract': True}
|
||||||
|
|
||||||
|
class Foo(Base):
|
||||||
|
counter = SequenceField()
|
||||||
|
|
||||||
|
class Bar(Base):
|
||||||
|
counter = SequenceField()
|
||||||
|
|
||||||
|
bar = Bar(name='Bar')
|
||||||
|
bar.save()
|
||||||
|
|
||||||
|
foo = Foo(name='Foo')
|
||||||
|
foo.save()
|
||||||
|
|
||||||
|
self.assertFalse('base.counter' in
|
||||||
|
self.db['mongoengine.counters'].find().distinct('_id'))
|
||||||
|
self.assertTrue(('foo.counter' and 'bar.counter') in
|
||||||
|
self.db['mongoengine.counters'].find().distinct('_id'))
|
||||||
|
self.assertEqual(foo.counter, bar.counter)
|
||||||
|
self.assertEqual(foo._fields['counter'].owner_document, Foo)
|
||||||
|
self.assertEqual(bar._fields['counter'].owner_document, Bar)
|
@ -4,7 +4,7 @@ from mongoengine import *
|
|||||||
from tests.utils import MongoDBTestCase
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestFloatField(MongoDBTestCase):
|
class TestURLField(MongoDBTestCase):
|
||||||
|
|
||||||
def test_validation(self):
|
def test_validation(self):
|
||||||
"""Ensure that URLFields validate urls properly."""
|
"""Ensure that URLFields validate urls properly."""
|
||||||
|
65
tests/fields/test_uuid_field.py
Normal file
65
tests/fields/test_uuid_field.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase, get_as_pymongo
|
||||||
|
|
||||||
|
|
||||||
|
class Person(Document):
|
||||||
|
api_key = UUIDField(binary=False)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUUIDField(MongoDBTestCase):
|
||||||
|
def test_storage(self):
|
||||||
|
uid = uuid.uuid4()
|
||||||
|
person = Person(api_key=uid).save()
|
||||||
|
self.assertEqual(
|
||||||
|
get_as_pymongo(person),
|
||||||
|
{'_id': person.id,
|
||||||
|
'api_key': str(uid)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_field_string(self):
|
||||||
|
"""Test UUID fields storing as String
|
||||||
|
"""
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
uu = uuid.uuid4()
|
||||||
|
Person(api_key=uu).save()
|
||||||
|
self.assertEqual(1, Person.objects(api_key=uu).count())
|
||||||
|
self.assertEqual(uu, Person.objects.first().api_key)
|
||||||
|
|
||||||
|
person = Person()
|
||||||
|
valid = (uuid.uuid4(), uuid.uuid1())
|
||||||
|
for api_key in valid:
|
||||||
|
person.api_key = api_key
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
invalid = ('9d159858-549b-4975-9f98-dd2f987c113g',
|
||||||
|
'9d159858-549b-4975-9f98-dd2f987c113')
|
||||||
|
for api_key in invalid:
|
||||||
|
person.api_key = api_key
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
def test_field_binary(self):
|
||||||
|
"""Test UUID fields storing as Binary object."""
|
||||||
|
Person.drop_collection()
|
||||||
|
|
||||||
|
uu = uuid.uuid4()
|
||||||
|
Person(api_key=uu).save()
|
||||||
|
self.assertEqual(1, Person.objects(api_key=uu).count())
|
||||||
|
self.assertEqual(uu, Person.objects.first().api_key)
|
||||||
|
|
||||||
|
person = Person()
|
||||||
|
valid = (uuid.uuid4(), uuid.uuid1())
|
||||||
|
for api_key in valid:
|
||||||
|
person.api_key = api_key
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
invalid = ('9d159858-549b-4975-9f98-dd2f987c113g',
|
||||||
|
'9d159858-549b-4975-9f98-dd2f987c113')
|
||||||
|
for api_key in invalid:
|
||||||
|
person.api_key = api_key
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
@ -33,6 +33,11 @@ class MongoDBTestCase(unittest.TestCase):
|
|||||||
cls._connection.drop_database(MONGO_TEST_DB)
|
cls._connection.drop_database(MONGO_TEST_DB)
|
||||||
|
|
||||||
|
|
||||||
|
def get_as_pymongo(doc):
|
||||||
|
"""Fetch the pymongo version of a certain Document"""
|
||||||
|
return doc.__class__.objects.as_pymongo().get(id=doc.id)
|
||||||
|
|
||||||
|
|
||||||
def get_mongodb_version():
|
def get_mongodb_version():
|
||||||
"""Return the version of the connected mongoDB (first 2 digits)
|
"""Return the version of the connected mongoDB (first 2 digits)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user