refactor fields tests (float, int, lazyref, long, url) #1983
This commit is contained in:
parent
5bbe782812
commit
28606e9985
@ -2,9 +2,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import unittest
|
import unittest
|
||||||
import uuid
|
import uuid
|
||||||
import math
|
|
||||||
import itertools
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from nose.plugins.skip import SkipTest
|
from nose.plugins.skip import SkipTest
|
||||||
@ -13,15 +10,10 @@ import six
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from bson import DBRef, ObjectId, SON
|
from bson import 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,
|
from mongoengine.base import (BaseDict, BaseField, EmbeddedDocumentList,
|
||||||
_document_registry, LazyReference)
|
_document_registry)
|
||||||
|
|
||||||
from tests.utils import MongoDBTestCase
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
@ -284,30 +276,6 @@ class FieldTest(MongoDBTestCase):
|
|||||||
# attempted.
|
# attempted.
|
||||||
self.assertRaises(ValidationError, ret.validate)
|
self.assertRaises(ValidationError, ret.validate)
|
||||||
|
|
||||||
def test_int_and_float_ne_operator(self):
|
|
||||||
class TestDocument(Document):
|
|
||||||
int_fld = IntField()
|
|
||||||
float_fld = FloatField()
|
|
||||||
|
|
||||||
TestDocument.drop_collection()
|
|
||||||
|
|
||||||
TestDocument(int_fld=None, float_fld=None).save()
|
|
||||||
TestDocument(int_fld=1, float_fld=1).save()
|
|
||||||
|
|
||||||
self.assertEqual(1, TestDocument.objects(int_fld__ne=None).count())
|
|
||||||
self.assertEqual(1, TestDocument.objects(float_fld__ne=None).count())
|
|
||||||
|
|
||||||
def test_long_ne_operator(self):
|
|
||||||
class TestDocument(Document):
|
|
||||||
long_fld = LongField()
|
|
||||||
|
|
||||||
TestDocument.drop_collection()
|
|
||||||
|
|
||||||
TestDocument(long_fld=None).save()
|
|
||||||
TestDocument(long_fld=1).save()
|
|
||||||
|
|
||||||
self.assertEqual(1, TestDocument.objects(long_fld__ne=None).count())
|
|
||||||
|
|
||||||
def test_object_id_validation(self):
|
def test_object_id_validation(self):
|
||||||
"""Ensure that invalid values cannot be assigned to an
|
"""Ensure that invalid values cannot be assigned to an
|
||||||
ObjectIdField.
|
ObjectIdField.
|
||||||
@ -351,135 +319,6 @@ class FieldTest(MongoDBTestCase):
|
|||||||
person.name = 'Shorter name'
|
person.name = 'Shorter name'
|
||||||
person.validate()
|
person.validate()
|
||||||
|
|
||||||
def test_url_validation(self):
|
|
||||||
"""Ensure that URLFields validate urls properly."""
|
|
||||||
class Link(Document):
|
|
||||||
url = URLField()
|
|
||||||
|
|
||||||
link = Link()
|
|
||||||
link.url = 'google'
|
|
||||||
self.assertRaises(ValidationError, link.validate)
|
|
||||||
|
|
||||||
link.url = 'http://www.google.com:8080'
|
|
||||||
link.validate()
|
|
||||||
|
|
||||||
def test_unicode_url_validation(self):
|
|
||||||
"""Ensure unicode URLs are validated properly."""
|
|
||||||
class Link(Document):
|
|
||||||
url = URLField()
|
|
||||||
|
|
||||||
link = Link()
|
|
||||||
link.url = u'http://привет.com'
|
|
||||||
|
|
||||||
# TODO fix URL validation - this *IS* a valid URL
|
|
||||||
# For now we just want to make sure that the error message is correct
|
|
||||||
try:
|
|
||||||
link.validate()
|
|
||||||
self.assertTrue(False)
|
|
||||||
except ValidationError as e:
|
|
||||||
self.assertEqual(
|
|
||||||
unicode(e),
|
|
||||||
u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_url_scheme_validation(self):
|
|
||||||
"""Ensure that URLFields validate urls with specific schemes properly.
|
|
||||||
"""
|
|
||||||
class Link(Document):
|
|
||||||
url = URLField()
|
|
||||||
|
|
||||||
class SchemeLink(Document):
|
|
||||||
url = URLField(schemes=['ws', 'irc'])
|
|
||||||
|
|
||||||
link = Link()
|
|
||||||
link.url = 'ws://google.com'
|
|
||||||
self.assertRaises(ValidationError, link.validate)
|
|
||||||
|
|
||||||
scheme_link = SchemeLink()
|
|
||||||
scheme_link.url = 'ws://google.com'
|
|
||||||
scheme_link.validate()
|
|
||||||
|
|
||||||
def test_url_allowed_domains(self):
|
|
||||||
"""Allow underscore in domain names.
|
|
||||||
"""
|
|
||||||
class Link(Document):
|
|
||||||
url = URLField()
|
|
||||||
|
|
||||||
link = Link()
|
|
||||||
link.url = 'https://san_leandro-ca.geebo.com'
|
|
||||||
link.validate()
|
|
||||||
|
|
||||||
def test_int_validation(self):
|
|
||||||
"""Ensure that invalid values cannot be assigned to int fields.
|
|
||||||
"""
|
|
||||||
class Person(Document):
|
|
||||||
age = IntField(min_value=0, max_value=110)
|
|
||||||
|
|
||||||
person = Person()
|
|
||||||
person.age = 50
|
|
||||||
person.validate()
|
|
||||||
|
|
||||||
person.age = -1
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
person.age = 120
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
person.age = 'ten'
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
|
|
||||||
def test_long_validation(self):
|
|
||||||
"""Ensure that invalid values cannot be assigned to long fields.
|
|
||||||
"""
|
|
||||||
class TestDocument(Document):
|
|
||||||
value = LongField(min_value=0, max_value=110)
|
|
||||||
|
|
||||||
doc = TestDocument()
|
|
||||||
doc.value = 50
|
|
||||||
doc.validate()
|
|
||||||
|
|
||||||
doc.value = -1
|
|
||||||
self.assertRaises(ValidationError, doc.validate)
|
|
||||||
doc.age = 120
|
|
||||||
self.assertRaises(ValidationError, doc.validate)
|
|
||||||
doc.age = 'ten'
|
|
||||||
self.assertRaises(ValidationError, doc.validate)
|
|
||||||
|
|
||||||
def test_float_validation(self):
|
|
||||||
"""Ensure that invalid values cannot be assigned to float fields.
|
|
||||||
"""
|
|
||||||
class Person(Document):
|
|
||||||
height = FloatField(min_value=0.1, max_value=3.5)
|
|
||||||
|
|
||||||
class BigPerson(Document):
|
|
||||||
height = FloatField()
|
|
||||||
|
|
||||||
person = Person()
|
|
||||||
person.height = 1.89
|
|
||||||
person.validate()
|
|
||||||
|
|
||||||
person.height = '2.0'
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
|
|
||||||
person.height = 0.01
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
|
|
||||||
person.height = 4.0
|
|
||||||
self.assertRaises(ValidationError, person.validate)
|
|
||||||
|
|
||||||
person_2 = Person(height='something invalid')
|
|
||||||
self.assertRaises(ValidationError, person_2.validate)
|
|
||||||
|
|
||||||
big_person = BigPerson()
|
|
||||||
|
|
||||||
for value, value_type in enumerate(six.integer_types):
|
|
||||||
big_person.height = value_type(value)
|
|
||||||
big_person.validate()
|
|
||||||
|
|
||||||
big_person.height = 2 ** 500
|
|
||||||
big_person.validate()
|
|
||||||
|
|
||||||
big_person.height = 2 ** 100000 # Too big for a float value
|
|
||||||
self.assertRaises(ValidationError, big_person.validate)
|
|
||||||
|
|
||||||
def test_decimal_validation(self):
|
def test_decimal_validation(self):
|
||||||
"""Ensure that invalid values cannot be assigned to decimal fields.
|
"""Ensure that invalid values cannot be assigned to decimal fields.
|
||||||
"""
|
"""
|
||||||
@ -3534,19 +3373,6 @@ class FieldTest(MongoDBTestCase):
|
|||||||
with self.assertRaises(FieldDoesNotExist):
|
with self.assertRaises(FieldDoesNotExist):
|
||||||
Doc(bar='test')
|
Doc(bar='test')
|
||||||
|
|
||||||
def test_long_field_is_considered_as_int64(self):
|
|
||||||
"""
|
|
||||||
Tests that long fields are stored as long in mongo, even if long
|
|
||||||
value is small enough to be an int.
|
|
||||||
"""
|
|
||||||
class TestLongFieldConsideredAsInt64(Document):
|
|
||||||
some_long = LongField()
|
|
||||||
|
|
||||||
doc = TestLongFieldConsideredAsInt64(some_long=42).save()
|
|
||||||
db = get_db()
|
|
||||||
self.assertIsInstance(db.test_long_field_considered_as_int64.find()[0]['some_long'], Int64)
|
|
||||||
self.assertIsInstance(doc.some_long, six.integer_types)
|
|
||||||
|
|
||||||
|
|
||||||
class EmbeddedDocumentListFieldTestCase(MongoDBTestCase):
|
class EmbeddedDocumentListFieldTestCase(MongoDBTestCase):
|
||||||
|
|
||||||
@ -4493,522 +4319,5 @@ class CachedReferenceFieldTest(MongoDBTestCase):
|
|||||||
self.assertIsInstance(ocorrence.animal, Animal)
|
self.assertIsInstance(ocorrence.animal, Animal)
|
||||||
|
|
||||||
|
|
||||||
class LazyReferenceFieldTest(MongoDBTestCase):
|
|
||||||
def test_lazy_reference_config(self):
|
|
||||||
# Make sure ReferenceField only accepts a document class or a string
|
|
||||||
# with a document class name.
|
|
||||||
self.assertRaises(ValidationError, LazyReferenceField, EmbeddedDocument)
|
|
||||||
|
|
||||||
def test_lazy_reference_simple(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
Ocurrence(person="test", animal=animal).save()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIsInstance(p.animal, LazyReference)
|
|
||||||
fetched_animal = p.animal.fetch()
|
|
||||||
self.assertEqual(fetched_animal, animal)
|
|
||||||
# `fetch` keep cache on referenced document by default...
|
|
||||||
animal.tag = "not so heavy"
|
|
||||||
animal.save()
|
|
||||||
double_fetch = p.animal.fetch()
|
|
||||||
self.assertIs(fetched_animal, double_fetch)
|
|
||||||
self.assertEqual(double_fetch.tag, "heavy")
|
|
||||||
# ...unless specified otherwise
|
|
||||||
fetch_force = p.animal.fetch(force=True)
|
|
||||||
self.assertIsNot(fetch_force, fetched_animal)
|
|
||||||
self.assertEqual(fetch_force.tag, "not so heavy")
|
|
||||||
|
|
||||||
def test_lazy_reference_fetch_invalid_ref(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
Ocurrence(person="test", animal=animal).save()
|
|
||||||
animal.delete()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIsInstance(p.animal, LazyReference)
|
|
||||||
with self.assertRaises(DoesNotExist):
|
|
||||||
p.animal.fetch()
|
|
||||||
|
|
||||||
def test_lazy_reference_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
meta = {'allow_inheritance': True}
|
|
||||||
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
class SubAnimal(Animal):
|
|
||||||
nick = StringField()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
sub_animal = SubAnimal(nick='doggo', name='dog').save()
|
|
||||||
for ref in (
|
|
||||||
animal,
|
|
||||||
animal.pk,
|
|
||||||
DBRef(animal._get_collection_name(), animal.pk),
|
|
||||||
LazyReference(Animal, animal.pk),
|
|
||||||
|
|
||||||
sub_animal,
|
|
||||||
sub_animal.pk,
|
|
||||||
DBRef(sub_animal._get_collection_name(), sub_animal.pk),
|
|
||||||
LazyReference(SubAnimal, sub_animal.pk),
|
|
||||||
):
|
|
||||||
p = Ocurrence(person="test", animal=ref).save()
|
|
||||||
p.reload()
|
|
||||||
self.assertIsInstance(p.animal, LazyReference)
|
|
||||||
p.animal.fetch()
|
|
||||||
|
|
||||||
def test_lazy_reference_bad_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
class BadDoc(Document):
|
|
||||||
pass
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
baddoc = BadDoc().save()
|
|
||||||
for bad in (
|
|
||||||
42,
|
|
||||||
'foo',
|
|
||||||
baddoc,
|
|
||||||
DBRef(baddoc._get_collection_name(), animal.pk),
|
|
||||||
LazyReference(BadDoc, animal.pk)
|
|
||||||
):
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
p = Ocurrence(person="test", animal=bad).save()
|
|
||||||
|
|
||||||
def test_lazy_reference_query_conversion(self):
|
|
||||||
"""Ensure that LazyReferenceFields 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 = LazyReferenceField(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)
|
|
||||||
|
|
||||||
# Same thing by passing a LazyReference instance
|
|
||||||
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
|
||||||
self.assertEqual(post.id, post2.id)
|
|
||||||
|
|
||||||
def test_lazy_reference_query_conversion_dbref(self):
|
|
||||||
"""Ensure that LazyReferenceFields 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 = LazyReferenceField(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)
|
|
||||||
|
|
||||||
# Same thing by passing a LazyReference instance
|
|
||||||
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
|
||||||
self.assertEqual(post.id, post2.id)
|
|
||||||
|
|
||||||
def test_lazy_reference_passthrough(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
animal = LazyReferenceField(Animal, passthrough=False)
|
|
||||||
animal_passthrough = LazyReferenceField(Animal, passthrough=True)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
Ocurrence(animal=animal, animal_passthrough=animal).save()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIsInstance(p.animal, LazyReference)
|
|
||||||
with self.assertRaises(KeyError):
|
|
||||||
p.animal['name']
|
|
||||||
with self.assertRaises(AttributeError):
|
|
||||||
p.animal.name
|
|
||||||
self.assertEqual(p.animal.pk, animal.pk)
|
|
||||||
|
|
||||||
self.assertEqual(p.animal_passthrough.name, "Leopard")
|
|
||||||
self.assertEqual(p.animal_passthrough['name'], "Leopard")
|
|
||||||
|
|
||||||
# Should not be able to access referenced document's methods
|
|
||||||
with self.assertRaises(AttributeError):
|
|
||||||
p.animal.save
|
|
||||||
with self.assertRaises(KeyError):
|
|
||||||
p.animal['save']
|
|
||||||
|
|
||||||
def test_lazy_reference_not_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
Ocurrence(person='foo').save()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIs(p.animal, None)
|
|
||||||
|
|
||||||
def test_lazy_reference_equality(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
animalref = LazyReference(Animal, animal.pk)
|
|
||||||
self.assertEqual(animal, animalref)
|
|
||||||
self.assertEqual(animalref, animal)
|
|
||||||
|
|
||||||
other_animalref = LazyReference(Animal, ObjectId("54495ad94c934721ede76f90"))
|
|
||||||
self.assertNotEqual(animal, other_animalref)
|
|
||||||
self.assertNotEqual(other_animalref, animal)
|
|
||||||
|
|
||||||
def test_lazy_reference_embedded(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class EmbeddedOcurrence(EmbeddedDocument):
|
|
||||||
in_list = ListField(LazyReferenceField(Animal))
|
|
||||||
direct = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
in_list = ListField(LazyReferenceField(Animal))
|
|
||||||
in_embedded = EmbeddedDocumentField(EmbeddedOcurrence)
|
|
||||||
direct = LazyReferenceField(Animal)
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal1 = Animal('doggo').save()
|
|
||||||
animal2 = Animal('cheeta').save()
|
|
||||||
|
|
||||||
def check_fields_type(occ):
|
|
||||||
self.assertIsInstance(occ.direct, LazyReference)
|
|
||||||
for elem in occ.in_list:
|
|
||||||
self.assertIsInstance(elem, LazyReference)
|
|
||||||
self.assertIsInstance(occ.in_embedded.direct, LazyReference)
|
|
||||||
for elem in occ.in_embedded.in_list:
|
|
||||||
self.assertIsInstance(elem, LazyReference)
|
|
||||||
|
|
||||||
occ = Ocurrence(
|
|
||||||
in_list=[animal1, animal2],
|
|
||||||
in_embedded={'in_list': [animal1, animal2], 'direct': animal1},
|
|
||||||
direct=animal1
|
|
||||||
).save()
|
|
||||||
check_fields_type(occ)
|
|
||||||
occ.reload()
|
|
||||||
check_fields_type(occ)
|
|
||||||
occ.direct = animal1.id
|
|
||||||
occ.in_list = [animal1.id, animal2.id]
|
|
||||||
occ.in_embedded.direct = animal1.id
|
|
||||||
occ.in_embedded.in_list = [animal1.id, animal2.id]
|
|
||||||
check_fields_type(occ)
|
|
||||||
|
|
||||||
|
|
||||||
class GenericLazyReferenceFieldTest(MongoDBTestCase):
|
|
||||||
def test_generic_lazy_reference_simple(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
Ocurrence(person="test", animal=animal).save()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIsInstance(p.animal, LazyReference)
|
|
||||||
fetched_animal = p.animal.fetch()
|
|
||||||
self.assertEqual(fetched_animal, animal)
|
|
||||||
# `fetch` keep cache on referenced document by default...
|
|
||||||
animal.tag = "not so heavy"
|
|
||||||
animal.save()
|
|
||||||
double_fetch = p.animal.fetch()
|
|
||||||
self.assertIs(fetched_animal, double_fetch)
|
|
||||||
self.assertEqual(double_fetch.tag, "heavy")
|
|
||||||
# ...unless specified otherwise
|
|
||||||
fetch_force = p.animal.fetch(force=True)
|
|
||||||
self.assertIsNot(fetch_force, fetched_animal)
|
|
||||||
self.assertEqual(fetch_force.tag, "not so heavy")
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_choices(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
|
|
||||||
class Vegetal(Document):
|
|
||||||
name = StringField()
|
|
||||||
|
|
||||||
class Mineral(Document):
|
|
||||||
name = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
living_thing = GenericLazyReferenceField(choices=[Animal, Vegetal])
|
|
||||||
thing = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Vegetal.drop_collection()
|
|
||||||
Mineral.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard").save()
|
|
||||||
vegetal = Vegetal(name="Oak").save()
|
|
||||||
mineral = Mineral(name="Granite").save()
|
|
||||||
|
|
||||||
occ_animal = Ocurrence(living_thing=animal, thing=animal).save()
|
|
||||||
occ_vegetal = Ocurrence(living_thing=vegetal, thing=vegetal).save()
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
Ocurrence(living_thing=mineral).save()
|
|
||||||
|
|
||||||
occ = Ocurrence.objects.get(living_thing=animal)
|
|
||||||
self.assertEqual(occ, occ_animal)
|
|
||||||
self.assertIsInstance(occ.thing, LazyReference)
|
|
||||||
self.assertIsInstance(occ.living_thing, LazyReference)
|
|
||||||
|
|
||||||
occ.thing = vegetal
|
|
||||||
occ.living_thing = vegetal
|
|
||||||
occ.save()
|
|
||||||
|
|
||||||
occ.thing = mineral
|
|
||||||
occ.living_thing = mineral
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
occ.save()
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
meta = {'allow_inheritance': True}
|
|
||||||
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
class SubAnimal(Animal):
|
|
||||||
nick = StringField()
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
sub_animal = SubAnimal(nick='doggo', name='dog').save()
|
|
||||||
for ref in (
|
|
||||||
animal,
|
|
||||||
LazyReference(Animal, animal.pk),
|
|
||||||
{'_cls': 'Animal', '_ref': DBRef(animal._get_collection_name(), animal.pk)},
|
|
||||||
|
|
||||||
sub_animal,
|
|
||||||
LazyReference(SubAnimal, sub_animal.pk),
|
|
||||||
{'_cls': 'SubAnimal', '_ref': DBRef(sub_animal._get_collection_name(), sub_animal.pk)},
|
|
||||||
):
|
|
||||||
p = Ocurrence(person="test", animal=ref).save()
|
|
||||||
p.reload()
|
|
||||||
self.assertIsInstance(p.animal, (LazyReference, Document))
|
|
||||||
p.animal.fetch()
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_bad_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = GenericLazyReferenceField(choices=['Animal'])
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
class BadDoc(Document):
|
|
||||||
pass
|
|
||||||
|
|
||||||
animal = Animal(name="Leopard", tag="heavy").save()
|
|
||||||
baddoc = BadDoc().save()
|
|
||||||
for bad in (
|
|
||||||
42,
|
|
||||||
'foo',
|
|
||||||
baddoc,
|
|
||||||
LazyReference(BadDoc, animal.pk)
|
|
||||||
):
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
p = Ocurrence(person="test", animal=bad).save()
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_query_conversion(self):
|
|
||||||
class Member(Document):
|
|
||||||
user_num = IntField(primary_key=True)
|
|
||||||
|
|
||||||
class BlogPost(Document):
|
|
||||||
title = StringField()
|
|
||||||
author = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# Same thing by passing a LazyReference instance
|
|
||||||
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
|
||||||
self.assertEqual(post.id, post2.id)
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_not_set(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
person = StringField()
|
|
||||||
animal = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
Ocurrence(person='foo').save()
|
|
||||||
p = Ocurrence.objects.get()
|
|
||||||
self.assertIs(p.animal, None)
|
|
||||||
|
|
||||||
def test_generic_lazy_reference_embedded(self):
|
|
||||||
class Animal(Document):
|
|
||||||
name = StringField()
|
|
||||||
tag = StringField()
|
|
||||||
|
|
||||||
class EmbeddedOcurrence(EmbeddedDocument):
|
|
||||||
in_list = ListField(GenericLazyReferenceField())
|
|
||||||
direct = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
class Ocurrence(Document):
|
|
||||||
in_list = ListField(GenericLazyReferenceField())
|
|
||||||
in_embedded = EmbeddedDocumentField(EmbeddedOcurrence)
|
|
||||||
direct = GenericLazyReferenceField()
|
|
||||||
|
|
||||||
Animal.drop_collection()
|
|
||||||
Ocurrence.drop_collection()
|
|
||||||
|
|
||||||
animal1 = Animal('doggo').save()
|
|
||||||
animal2 = Animal('cheeta').save()
|
|
||||||
|
|
||||||
def check_fields_type(occ):
|
|
||||||
self.assertIsInstance(occ.direct, LazyReference)
|
|
||||||
for elem in occ.in_list:
|
|
||||||
self.assertIsInstance(elem, LazyReference)
|
|
||||||
self.assertIsInstance(occ.in_embedded.direct, LazyReference)
|
|
||||||
for elem in occ.in_embedded.in_list:
|
|
||||||
self.assertIsInstance(elem, LazyReference)
|
|
||||||
|
|
||||||
occ = Ocurrence(
|
|
||||||
in_list=[animal1, animal2],
|
|
||||||
in_embedded={'in_list': [animal1, animal2], 'direct': animal1},
|
|
||||||
direct=animal1
|
|
||||||
).save()
|
|
||||||
check_fields_type(occ)
|
|
||||||
occ.reload()
|
|
||||||
check_fields_type(occ)
|
|
||||||
animal1_ref = {'_cls': 'Animal', '_ref': DBRef(animal1._get_collection_name(), animal1.pk)}
|
|
||||||
animal2_ref = {'_cls': 'Animal', '_ref': DBRef(animal2._get_collection_name(), animal2.pk)}
|
|
||||||
occ.direct = animal1_ref
|
|
||||||
occ.in_list = [animal1_ref, animal2_ref]
|
|
||||||
occ.in_embedded.direct = animal1_ref
|
|
||||||
occ.in_embedded.in_list = [animal1_ref, animal2_ref]
|
|
||||||
check_fields_type(occ)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
58
tests/fields/test_float_field.py
Normal file
58
tests/fields/test_float_field.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import six
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloatField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_float_ne_operator(self):
|
||||||
|
class TestDocument(Document):
|
||||||
|
float_fld = FloatField()
|
||||||
|
|
||||||
|
TestDocument.drop_collection()
|
||||||
|
|
||||||
|
TestDocument(float_fld=None).save()
|
||||||
|
TestDocument(float_fld=1).save()
|
||||||
|
|
||||||
|
self.assertEqual(1, TestDocument.objects(float_fld__ne=None).count())
|
||||||
|
self.assertEqual(1, TestDocument.objects(float_fld__ne=1).count())
|
||||||
|
|
||||||
|
def test_validation(self):
|
||||||
|
"""Ensure that invalid values cannot be assigned to float fields.
|
||||||
|
"""
|
||||||
|
class Person(Document):
|
||||||
|
height = FloatField(min_value=0.1, max_value=3.5)
|
||||||
|
|
||||||
|
class BigPerson(Document):
|
||||||
|
height = FloatField()
|
||||||
|
|
||||||
|
person = Person()
|
||||||
|
person.height = 1.89
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
person.height = '2.0'
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
person.height = 0.01
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
person.height = 4.0
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
person_2 = Person(height='something invalid')
|
||||||
|
self.assertRaises(ValidationError, person_2.validate)
|
||||||
|
|
||||||
|
big_person = BigPerson()
|
||||||
|
|
||||||
|
for value, value_type in enumerate(six.integer_types):
|
||||||
|
big_person.height = value_type(value)
|
||||||
|
big_person.validate()
|
||||||
|
|
||||||
|
big_person.height = 2 ** 500
|
||||||
|
big_person.validate()
|
||||||
|
|
||||||
|
big_person.height = 2 ** 100000 # Too big for a float value
|
||||||
|
self.assertRaises(ValidationError, big_person.validate)
|
42
tests/fields/test_int_field.py
Normal file
42
tests/fields/test_int_field.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestIntField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_int_validation(self):
|
||||||
|
"""Ensure that invalid values cannot be assigned to int fields.
|
||||||
|
"""
|
||||||
|
class Person(Document):
|
||||||
|
age = IntField(min_value=0, max_value=110)
|
||||||
|
|
||||||
|
person = Person()
|
||||||
|
person.age = 0
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
person.age = 50
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
person.age = 110
|
||||||
|
person.validate()
|
||||||
|
|
||||||
|
person.age = -1
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.age = 120
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
person.age = 'ten'
|
||||||
|
self.assertRaises(ValidationError, person.validate)
|
||||||
|
|
||||||
|
def test_ne_operator(self):
|
||||||
|
class TestDocument(Document):
|
||||||
|
int_fld = IntField()
|
||||||
|
|
||||||
|
TestDocument.drop_collection()
|
||||||
|
|
||||||
|
TestDocument(int_fld=None).save()
|
||||||
|
TestDocument(int_fld=1).save()
|
||||||
|
|
||||||
|
self.assertEqual(1, TestDocument.objects(int_fld__ne=None).count())
|
||||||
|
self.assertEqual(1, TestDocument.objects(int_fld__ne=1).count())
|
524
tests/fields/test_lazy_reference_field.py
Normal file
524
tests/fields/test_lazy_reference_field.py
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from bson import DBRef, ObjectId
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
from mongoengine.base import LazyReference
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestLazyReferenceField(MongoDBTestCase):
|
||||||
|
def test_lazy_reference_config(self):
|
||||||
|
# Make sure ReferenceField only accepts a document class or a string
|
||||||
|
# with a document class name.
|
||||||
|
self.assertRaises(ValidationError, LazyReferenceField, EmbeddedDocument)
|
||||||
|
|
||||||
|
def test_lazy_reference_simple(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
Ocurrence(person="test", animal=animal).save()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIsInstance(p.animal, LazyReference)
|
||||||
|
fetched_animal = p.animal.fetch()
|
||||||
|
self.assertEqual(fetched_animal, animal)
|
||||||
|
# `fetch` keep cache on referenced document by default...
|
||||||
|
animal.tag = "not so heavy"
|
||||||
|
animal.save()
|
||||||
|
double_fetch = p.animal.fetch()
|
||||||
|
self.assertIs(fetched_animal, double_fetch)
|
||||||
|
self.assertEqual(double_fetch.tag, "heavy")
|
||||||
|
# ...unless specified otherwise
|
||||||
|
fetch_force = p.animal.fetch(force=True)
|
||||||
|
self.assertIsNot(fetch_force, fetched_animal)
|
||||||
|
self.assertEqual(fetch_force.tag, "not so heavy")
|
||||||
|
|
||||||
|
def test_lazy_reference_fetch_invalid_ref(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
Ocurrence(person="test", animal=animal).save()
|
||||||
|
animal.delete()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIsInstance(p.animal, LazyReference)
|
||||||
|
with self.assertRaises(DoesNotExist):
|
||||||
|
p.animal.fetch()
|
||||||
|
|
||||||
|
def test_lazy_reference_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
meta = {'allow_inheritance': True}
|
||||||
|
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
class SubAnimal(Animal):
|
||||||
|
nick = StringField()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
sub_animal = SubAnimal(nick='doggo', name='dog').save()
|
||||||
|
for ref in (
|
||||||
|
animal,
|
||||||
|
animal.pk,
|
||||||
|
DBRef(animal._get_collection_name(), animal.pk),
|
||||||
|
LazyReference(Animal, animal.pk),
|
||||||
|
|
||||||
|
sub_animal,
|
||||||
|
sub_animal.pk,
|
||||||
|
DBRef(sub_animal._get_collection_name(), sub_animal.pk),
|
||||||
|
LazyReference(SubAnimal, sub_animal.pk),
|
||||||
|
):
|
||||||
|
p = Ocurrence(person="test", animal=ref).save()
|
||||||
|
p.reload()
|
||||||
|
self.assertIsInstance(p.animal, LazyReference)
|
||||||
|
p.animal.fetch()
|
||||||
|
|
||||||
|
def test_lazy_reference_bad_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
class BadDoc(Document):
|
||||||
|
pass
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
baddoc = BadDoc().save()
|
||||||
|
for bad in (
|
||||||
|
42,
|
||||||
|
'foo',
|
||||||
|
baddoc,
|
||||||
|
DBRef(baddoc._get_collection_name(), animal.pk),
|
||||||
|
LazyReference(BadDoc, animal.pk)
|
||||||
|
):
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
p = Ocurrence(person="test", animal=bad).save()
|
||||||
|
|
||||||
|
def test_lazy_reference_query_conversion(self):
|
||||||
|
"""Ensure that LazyReferenceFields 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 = LazyReferenceField(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)
|
||||||
|
|
||||||
|
# Same thing by passing a LazyReference instance
|
||||||
|
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
||||||
|
self.assertEqual(post.id, post2.id)
|
||||||
|
|
||||||
|
def test_lazy_reference_query_conversion_dbref(self):
|
||||||
|
"""Ensure that LazyReferenceFields 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 = LazyReferenceField(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)
|
||||||
|
|
||||||
|
# Same thing by passing a LazyReference instance
|
||||||
|
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
||||||
|
self.assertEqual(post.id, post2.id)
|
||||||
|
|
||||||
|
def test_lazy_reference_passthrough(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
animal = LazyReferenceField(Animal, passthrough=False)
|
||||||
|
animal_passthrough = LazyReferenceField(Animal, passthrough=True)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
Ocurrence(animal=animal, animal_passthrough=animal).save()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIsInstance(p.animal, LazyReference)
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
p.animal['name']
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
p.animal.name
|
||||||
|
self.assertEqual(p.animal.pk, animal.pk)
|
||||||
|
|
||||||
|
self.assertEqual(p.animal_passthrough.name, "Leopard")
|
||||||
|
self.assertEqual(p.animal_passthrough['name'], "Leopard")
|
||||||
|
|
||||||
|
# Should not be able to access referenced document's methods
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
p.animal.save
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
p.animal['save']
|
||||||
|
|
||||||
|
def test_lazy_reference_not_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
Ocurrence(person='foo').save()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIs(p.animal, None)
|
||||||
|
|
||||||
|
def test_lazy_reference_equality(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
animalref = LazyReference(Animal, animal.pk)
|
||||||
|
self.assertEqual(animal, animalref)
|
||||||
|
self.assertEqual(animalref, animal)
|
||||||
|
|
||||||
|
other_animalref = LazyReference(Animal, ObjectId("54495ad94c934721ede76f90"))
|
||||||
|
self.assertNotEqual(animal, other_animalref)
|
||||||
|
self.assertNotEqual(other_animalref, animal)
|
||||||
|
|
||||||
|
def test_lazy_reference_embedded(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class EmbeddedOcurrence(EmbeddedDocument):
|
||||||
|
in_list = ListField(LazyReferenceField(Animal))
|
||||||
|
direct = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
in_list = ListField(LazyReferenceField(Animal))
|
||||||
|
in_embedded = EmbeddedDocumentField(EmbeddedOcurrence)
|
||||||
|
direct = LazyReferenceField(Animal)
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal1 = Animal('doggo').save()
|
||||||
|
animal2 = Animal('cheeta').save()
|
||||||
|
|
||||||
|
def check_fields_type(occ):
|
||||||
|
self.assertIsInstance(occ.direct, LazyReference)
|
||||||
|
for elem in occ.in_list:
|
||||||
|
self.assertIsInstance(elem, LazyReference)
|
||||||
|
self.assertIsInstance(occ.in_embedded.direct, LazyReference)
|
||||||
|
for elem in occ.in_embedded.in_list:
|
||||||
|
self.assertIsInstance(elem, LazyReference)
|
||||||
|
|
||||||
|
occ = Ocurrence(
|
||||||
|
in_list=[animal1, animal2],
|
||||||
|
in_embedded={'in_list': [animal1, animal2], 'direct': animal1},
|
||||||
|
direct=animal1
|
||||||
|
).save()
|
||||||
|
check_fields_type(occ)
|
||||||
|
occ.reload()
|
||||||
|
check_fields_type(occ)
|
||||||
|
occ.direct = animal1.id
|
||||||
|
occ.in_list = [animal1.id, animal2.id]
|
||||||
|
occ.in_embedded.direct = animal1.id
|
||||||
|
occ.in_embedded.in_list = [animal1.id, animal2.id]
|
||||||
|
check_fields_type(occ)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGenericLazyReferenceField(MongoDBTestCase):
|
||||||
|
def test_generic_lazy_reference_simple(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
Ocurrence(person="test", animal=animal).save()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIsInstance(p.animal, LazyReference)
|
||||||
|
fetched_animal = p.animal.fetch()
|
||||||
|
self.assertEqual(fetched_animal, animal)
|
||||||
|
# `fetch` keep cache on referenced document by default...
|
||||||
|
animal.tag = "not so heavy"
|
||||||
|
animal.save()
|
||||||
|
double_fetch = p.animal.fetch()
|
||||||
|
self.assertIs(fetched_animal, double_fetch)
|
||||||
|
self.assertEqual(double_fetch.tag, "heavy")
|
||||||
|
# ...unless specified otherwise
|
||||||
|
fetch_force = p.animal.fetch(force=True)
|
||||||
|
self.assertIsNot(fetch_force, fetched_animal)
|
||||||
|
self.assertEqual(fetch_force.tag, "not so heavy")
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_choices(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Vegetal(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Mineral(Document):
|
||||||
|
name = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
living_thing = GenericLazyReferenceField(choices=[Animal, Vegetal])
|
||||||
|
thing = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Vegetal.drop_collection()
|
||||||
|
Mineral.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard").save()
|
||||||
|
vegetal = Vegetal(name="Oak").save()
|
||||||
|
mineral = Mineral(name="Granite").save()
|
||||||
|
|
||||||
|
occ_animal = Ocurrence(living_thing=animal, thing=animal).save()
|
||||||
|
occ_vegetal = Ocurrence(living_thing=vegetal, thing=vegetal).save()
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
Ocurrence(living_thing=mineral).save()
|
||||||
|
|
||||||
|
occ = Ocurrence.objects.get(living_thing=animal)
|
||||||
|
self.assertEqual(occ, occ_animal)
|
||||||
|
self.assertIsInstance(occ.thing, LazyReference)
|
||||||
|
self.assertIsInstance(occ.living_thing, LazyReference)
|
||||||
|
|
||||||
|
occ.thing = vegetal
|
||||||
|
occ.living_thing = vegetal
|
||||||
|
occ.save()
|
||||||
|
|
||||||
|
occ.thing = mineral
|
||||||
|
occ.living_thing = mineral
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
occ.save()
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
meta = {'allow_inheritance': True}
|
||||||
|
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
class SubAnimal(Animal):
|
||||||
|
nick = StringField()
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
sub_animal = SubAnimal(nick='doggo', name='dog').save()
|
||||||
|
for ref in (
|
||||||
|
animal,
|
||||||
|
LazyReference(Animal, animal.pk),
|
||||||
|
{'_cls': 'Animal', '_ref': DBRef(animal._get_collection_name(), animal.pk)},
|
||||||
|
|
||||||
|
sub_animal,
|
||||||
|
LazyReference(SubAnimal, sub_animal.pk),
|
||||||
|
{'_cls': 'SubAnimal', '_ref': DBRef(sub_animal._get_collection_name(), sub_animal.pk)},
|
||||||
|
):
|
||||||
|
p = Ocurrence(person="test", animal=ref).save()
|
||||||
|
p.reload()
|
||||||
|
self.assertIsInstance(p.animal, (LazyReference, Document))
|
||||||
|
p.animal.fetch()
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_bad_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = GenericLazyReferenceField(choices=['Animal'])
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
class BadDoc(Document):
|
||||||
|
pass
|
||||||
|
|
||||||
|
animal = Animal(name="Leopard", tag="heavy").save()
|
||||||
|
baddoc = BadDoc().save()
|
||||||
|
for bad in (
|
||||||
|
42,
|
||||||
|
'foo',
|
||||||
|
baddoc,
|
||||||
|
LazyReference(BadDoc, animal.pk)
|
||||||
|
):
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
p = Ocurrence(person="test", animal=bad).save()
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_query_conversion(self):
|
||||||
|
class Member(Document):
|
||||||
|
user_num = IntField(primary_key=True)
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
title = StringField()
|
||||||
|
author = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Same thing by passing a LazyReference instance
|
||||||
|
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first()
|
||||||
|
self.assertEqual(post.id, post2.id)
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_not_set(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
person = StringField()
|
||||||
|
animal = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
Ocurrence(person='foo').save()
|
||||||
|
p = Ocurrence.objects.get()
|
||||||
|
self.assertIs(p.animal, None)
|
||||||
|
|
||||||
|
def test_generic_lazy_reference_embedded(self):
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
tag = StringField()
|
||||||
|
|
||||||
|
class EmbeddedOcurrence(EmbeddedDocument):
|
||||||
|
in_list = ListField(GenericLazyReferenceField())
|
||||||
|
direct = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
class Ocurrence(Document):
|
||||||
|
in_list = ListField(GenericLazyReferenceField())
|
||||||
|
in_embedded = EmbeddedDocumentField(EmbeddedOcurrence)
|
||||||
|
direct = GenericLazyReferenceField()
|
||||||
|
|
||||||
|
Animal.drop_collection()
|
||||||
|
Ocurrence.drop_collection()
|
||||||
|
|
||||||
|
animal1 = Animal('doggo').save()
|
||||||
|
animal2 = Animal('cheeta').save()
|
||||||
|
|
||||||
|
def check_fields_type(occ):
|
||||||
|
self.assertIsInstance(occ.direct, LazyReference)
|
||||||
|
for elem in occ.in_list:
|
||||||
|
self.assertIsInstance(elem, LazyReference)
|
||||||
|
self.assertIsInstance(occ.in_embedded.direct, LazyReference)
|
||||||
|
for elem in occ.in_embedded.in_list:
|
||||||
|
self.assertIsInstance(elem, LazyReference)
|
||||||
|
|
||||||
|
occ = Ocurrence(
|
||||||
|
in_list=[animal1, animal2],
|
||||||
|
in_embedded={'in_list': [animal1, animal2], 'direct': animal1},
|
||||||
|
direct=animal1
|
||||||
|
).save()
|
||||||
|
check_fields_type(occ)
|
||||||
|
occ.reload()
|
||||||
|
check_fields_type(occ)
|
||||||
|
animal1_ref = {'_cls': 'Animal', '_ref': DBRef(animal1._get_collection_name(), animal1.pk)}
|
||||||
|
animal2_ref = {'_cls': 'Animal', '_ref': DBRef(animal2._get_collection_name(), animal2.pk)}
|
||||||
|
occ.direct = animal1_ref
|
||||||
|
occ.in_list = [animal1_ref, animal2_ref]
|
||||||
|
occ.in_embedded.direct = animal1_ref
|
||||||
|
occ.in_embedded.in_list = [animal1_ref, animal2_ref]
|
||||||
|
check_fields_type(occ)
|
56
tests/fields/test_long_field.py
Normal file
56
tests/fields/test_long_field.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import six
|
||||||
|
|
||||||
|
try:
|
||||||
|
from bson.int64 import Int64
|
||||||
|
except ImportError:
|
||||||
|
Int64 = long
|
||||||
|
|
||||||
|
from mongoengine import *
|
||||||
|
from mongoengine.connection import get_db
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestLongField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_long_field_is_considered_as_int64(self):
|
||||||
|
"""
|
||||||
|
Tests that long fields are stored as long in mongo, even if long
|
||||||
|
value is small enough to be an int.
|
||||||
|
"""
|
||||||
|
class TestLongFieldConsideredAsInt64(Document):
|
||||||
|
some_long = LongField()
|
||||||
|
|
||||||
|
doc = TestLongFieldConsideredAsInt64(some_long=42).save()
|
||||||
|
db = get_db()
|
||||||
|
self.assertIsInstance(db.test_long_field_considered_as_int64.find()[0]['some_long'], Int64)
|
||||||
|
self.assertIsInstance(doc.some_long, six.integer_types)
|
||||||
|
|
||||||
|
def test_long_validation(self):
|
||||||
|
"""Ensure that invalid values cannot be assigned to long fields.
|
||||||
|
"""
|
||||||
|
class TestDocument(Document):
|
||||||
|
value = LongField(min_value=0, max_value=110)
|
||||||
|
|
||||||
|
doc = TestDocument()
|
||||||
|
doc.value = 50
|
||||||
|
doc.validate()
|
||||||
|
|
||||||
|
doc.value = -1
|
||||||
|
self.assertRaises(ValidationError, doc.validate)
|
||||||
|
doc.age = 120
|
||||||
|
self.assertRaises(ValidationError, doc.validate)
|
||||||
|
doc.age = 'ten'
|
||||||
|
self.assertRaises(ValidationError, doc.validate)
|
||||||
|
|
||||||
|
def test_long_ne_operator(self):
|
||||||
|
class TestDocument(Document):
|
||||||
|
long_fld = LongField()
|
||||||
|
|
||||||
|
TestDocument.drop_collection()
|
||||||
|
|
||||||
|
TestDocument(long_fld=None).save()
|
||||||
|
TestDocument(long_fld=1).save()
|
||||||
|
|
||||||
|
self.assertEqual(1, TestDocument.objects(long_fld__ne=None).count())
|
59
tests/fields/test_url_field.py
Normal file
59
tests/fields/test_url_field.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from mongoengine import *
|
||||||
|
|
||||||
|
from tests.utils import MongoDBTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloatField(MongoDBTestCase):
|
||||||
|
|
||||||
|
def test_validation(self):
|
||||||
|
"""Ensure that URLFields validate urls properly."""
|
||||||
|
class Link(Document):
|
||||||
|
url = URLField()
|
||||||
|
|
||||||
|
link = Link()
|
||||||
|
link.url = 'google'
|
||||||
|
self.assertRaises(ValidationError, link.validate)
|
||||||
|
|
||||||
|
link.url = 'http://www.google.com:8080'
|
||||||
|
link.validate()
|
||||||
|
|
||||||
|
def test_unicode_url_validation(self):
|
||||||
|
"""Ensure unicode URLs are validated properly."""
|
||||||
|
class Link(Document):
|
||||||
|
url = URLField()
|
||||||
|
|
||||||
|
link = Link()
|
||||||
|
link.url = u'http://привет.com'
|
||||||
|
|
||||||
|
# TODO fix URL validation - this *IS* a valid URL
|
||||||
|
# For now we just want to make sure that the error message is correct
|
||||||
|
with self.assertRaises(ValidationError) as ctx_err:
|
||||||
|
link.validate()
|
||||||
|
self.assertEqual(unicode(ctx_err.exception),
|
||||||
|
u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])")
|
||||||
|
|
||||||
|
def test_url_scheme_validation(self):
|
||||||
|
"""Ensure that URLFields validate urls with specific schemes properly.
|
||||||
|
"""
|
||||||
|
class Link(Document):
|
||||||
|
url = URLField()
|
||||||
|
|
||||||
|
class SchemeLink(Document):
|
||||||
|
url = URLField(schemes=['ws', 'irc'])
|
||||||
|
|
||||||
|
link = Link()
|
||||||
|
link.url = 'ws://google.com'
|
||||||
|
self.assertRaises(ValidationError, link.validate)
|
||||||
|
|
||||||
|
scheme_link = SchemeLink()
|
||||||
|
scheme_link.url = 'ws://google.com'
|
||||||
|
scheme_link.validate()
|
||||||
|
|
||||||
|
def test_underscore_allowed_in_domains_names(self):
|
||||||
|
class Link(Document):
|
||||||
|
url = URLField()
|
||||||
|
|
||||||
|
link = Link()
|
||||||
|
link.url = 'https://san_leandro-ca.geebo.com'
|
||||||
|
link.validate()
|
Loading…
x
Reference in New Issue
Block a user