Merge branch 'master' of github.com:MongoEngine/mongoengine into fix_baselist_marked_changed_bug
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from all_warnings import AllWarnings
|
||||
from document import *
|
||||
from queryset import *
|
||||
from fields import *
|
||||
from .all_warnings import AllWarnings
|
||||
from .document import *
|
||||
from .queryset import *
|
||||
from .fields import *
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import unittest
|
||||
|
||||
from class_methods import *
|
||||
from delta import *
|
||||
from dynamic import *
|
||||
from indexes import *
|
||||
from inheritance import *
|
||||
from instance import *
|
||||
from json_serialisation import *
|
||||
from validation import *
|
||||
from .class_methods import *
|
||||
from .delta import *
|
||||
from .dynamic import *
|
||||
from .indexes import *
|
||||
from .inheritance import *
|
||||
from .instance import *
|
||||
from .json_serialisation import *
|
||||
from .validation import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -5,7 +5,7 @@ from mongoengine import *
|
||||
|
||||
from mongoengine.queryset import NULLIFY, PULL
|
||||
from mongoengine.connection import get_db
|
||||
from tests.utils import needs_mongodb_v26
|
||||
from tests.utils import requires_mongodb_gte_26
|
||||
|
||||
__all__ = ("ClassMethodsTest", )
|
||||
|
||||
@@ -66,10 +66,10 @@ class ClassMethodsTest(unittest.TestCase):
|
||||
"""
|
||||
collection_name = 'person'
|
||||
self.Person(name='Test').save()
|
||||
self.assertTrue(collection_name in self.db.collection_names())
|
||||
self.assertIn(collection_name, self.db.collection_names())
|
||||
|
||||
self.Person.drop_collection()
|
||||
self.assertFalse(collection_name in self.db.collection_names())
|
||||
self.assertNotIn(collection_name, self.db.collection_names())
|
||||
|
||||
def test_register_delete_rule(self):
|
||||
"""Ensure that register delete rule adds a delete rule to the document
|
||||
@@ -188,7 +188,7 @@ class ClassMethodsTest(unittest.TestCase):
|
||||
self.assertEqual(BlogPostWithTags.compare_indexes(), { 'missing': [], 'extra': [] })
|
||||
self.assertEqual(BlogPostWithCustomField.compare_indexes(), { 'missing': [], 'extra': [] })
|
||||
|
||||
@needs_mongodb_v26
|
||||
@requires_mongodb_gte_26
|
||||
def test_compare_indexes_for_text_indexes(self):
|
||||
""" Ensure that compare_indexes behaves correctly for text indexes """
|
||||
|
||||
@@ -340,7 +340,7 @@ class ClassMethodsTest(unittest.TestCase):
|
||||
meta = {'collection': collection_name}
|
||||
|
||||
Person(name="Test User").save()
|
||||
self.assertTrue(collection_name in self.db.collection_names())
|
||||
self.assertIn(collection_name, self.db.collection_names())
|
||||
|
||||
user_obj = self.db[collection_name].find_one()
|
||||
self.assertEqual(user_obj['name'], "Test User")
|
||||
@@ -349,7 +349,7 @@ class ClassMethodsTest(unittest.TestCase):
|
||||
self.assertEqual(user_obj.name, "Test User")
|
||||
|
||||
Person.drop_collection()
|
||||
self.assertFalse(collection_name in self.db.collection_names())
|
||||
self.assertNotIn(collection_name, self.db.collection_names())
|
||||
|
||||
def test_collection_name_and_primary(self):
|
||||
"""Ensure that a collection with a specified name may be used.
|
||||
|
||||
@@ -694,7 +694,7 @@ class DeltaTest(unittest.TestCase):
|
||||
organization.employees.append(person)
|
||||
updates, removals = organization._delta()
|
||||
self.assertEqual({}, removals)
|
||||
self.assertTrue('employees' in updates)
|
||||
self.assertIn('employees', updates)
|
||||
|
||||
def test_delta_with_dbref_false(self):
|
||||
person, organization, employee = self.circular_reference_deltas_2(Document, Document, False)
|
||||
@@ -709,7 +709,7 @@ class DeltaTest(unittest.TestCase):
|
||||
organization.employees.append(person)
|
||||
updates, removals = organization._delta()
|
||||
self.assertEqual({}, removals)
|
||||
self.assertTrue('employees' in updates)
|
||||
self.assertIn('employees', updates)
|
||||
|
||||
def test_nested_nested_fields_mark_as_changed(self):
|
||||
class EmbeddedDoc(EmbeddedDocument):
|
||||
|
||||
@@ -174,8 +174,8 @@ class DynamicTest(unittest.TestCase):
|
||||
|
||||
Employee.drop_collection()
|
||||
|
||||
self.assertTrue('name' in Employee._fields)
|
||||
self.assertTrue('salary' in Employee._fields)
|
||||
self.assertIn('name', Employee._fields)
|
||||
self.assertIn('salary', Employee._fields)
|
||||
self.assertEqual(Employee._get_collection_name(),
|
||||
self.Person._get_collection_name())
|
||||
|
||||
@@ -189,7 +189,7 @@ class DynamicTest(unittest.TestCase):
|
||||
self.assertEqual(1, Employee.objects(age=20).count())
|
||||
|
||||
joe_bloggs = self.Person.objects.first()
|
||||
self.assertTrue(isinstance(joe_bloggs, Employee))
|
||||
self.assertIsInstance(joe_bloggs, Employee)
|
||||
|
||||
def test_embedded_dynamic_document(self):
|
||||
"""Test dynamic embedded documents"""
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import unittest
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from nose.plugins.skip import SkipTest
|
||||
from datetime import datetime
|
||||
from pymongo.errors import OperationFailure
|
||||
import pymongo
|
||||
|
||||
from mongoengine import *
|
||||
from mongoengine.connection import get_db
|
||||
|
||||
from tests.utils import get_mongodb_version, needs_mongodb_v26
|
||||
from tests.utils import get_mongodb_version, requires_mongodb_gte_26, MONGODB_32, MONGODB_3
|
||||
|
||||
__all__ = ("IndexesTest", )
|
||||
|
||||
@@ -19,6 +18,7 @@ class IndexesTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.connection = connect(db='mongoenginetest')
|
||||
self.db = get_db()
|
||||
self.mongodb_version = get_mongodb_version()
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
@@ -70,7 +70,7 @@ class IndexesTest(unittest.TestCase):
|
||||
self.assertEqual(len(info), 4)
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
for expected in expected_specs:
|
||||
self.assertTrue(expected['fields'] in info)
|
||||
self.assertIn(expected['fields'], info)
|
||||
|
||||
def _index_test_inheritance(self, InheritFrom):
|
||||
|
||||
@@ -102,7 +102,7 @@ class IndexesTest(unittest.TestCase):
|
||||
self.assertEqual(len(info), 4)
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
for expected in expected_specs:
|
||||
self.assertTrue(expected['fields'] in info)
|
||||
self.assertIn(expected['fields'], info)
|
||||
|
||||
class ExtendedBlogPost(BlogPost):
|
||||
title = StringField()
|
||||
@@ -117,7 +117,7 @@ class IndexesTest(unittest.TestCase):
|
||||
info = ExtendedBlogPost.objects._collection.index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
for expected in expected_specs:
|
||||
self.assertTrue(expected['fields'] in info)
|
||||
self.assertIn(expected['fields'], info)
|
||||
|
||||
def test_indexes_document_inheritance(self):
|
||||
"""Ensure that indexes are used when meta[indexes] is specified for
|
||||
@@ -226,7 +226,7 @@ class IndexesTest(unittest.TestCase):
|
||||
list(Person.objects)
|
||||
info = Person.objects._collection.index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('rank.title', 1)] in info)
|
||||
self.assertIn([('rank.title', 1)], info)
|
||||
|
||||
def test_explicit_geo2d_index(self):
|
||||
"""Ensure that geo2d indexes work when created via meta[indexes]
|
||||
@@ -246,7 +246,7 @@ class IndexesTest(unittest.TestCase):
|
||||
Place.ensure_indexes()
|
||||
info = Place._get_collection().index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('location.point', '2d')] in info)
|
||||
self.assertIn([('location.point', '2d')], info)
|
||||
|
||||
def test_explicit_geo2d_index_embedded(self):
|
||||
"""Ensure that geo2d indexes work when created via meta[indexes]
|
||||
@@ -269,7 +269,7 @@ class IndexesTest(unittest.TestCase):
|
||||
Place.ensure_indexes()
|
||||
info = Place._get_collection().index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('current.location.point', '2d')] in info)
|
||||
self.assertIn([('current.location.point', '2d')], info)
|
||||
|
||||
def test_explicit_geosphere_index(self):
|
||||
"""Ensure that geosphere indexes work when created via meta[indexes]
|
||||
@@ -289,7 +289,7 @@ class IndexesTest(unittest.TestCase):
|
||||
Place.ensure_indexes()
|
||||
info = Place._get_collection().index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('location.point', '2dsphere')] in info)
|
||||
self.assertIn([('location.point', '2dsphere')], info)
|
||||
|
||||
def test_explicit_geohaystack_index(self):
|
||||
"""Ensure that geohaystack indexes work when created via meta[indexes]
|
||||
@@ -311,7 +311,7 @@ class IndexesTest(unittest.TestCase):
|
||||
Place.ensure_indexes()
|
||||
info = Place._get_collection().index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('location.point', 'geoHaystack')] in info)
|
||||
self.assertIn([('location.point', 'geoHaystack')], info)
|
||||
|
||||
def test_create_geohaystack_index(self):
|
||||
"""Ensure that geohaystack indexes can be created
|
||||
@@ -323,7 +323,7 @@ class IndexesTest(unittest.TestCase):
|
||||
Place.create_index({'fields': (')location.point', 'name')}, bucketSize=10)
|
||||
info = Place._get_collection().index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('location.point', 'geoHaystack'), ('name', 1)] in info)
|
||||
self.assertIn([('location.point', 'geoHaystack'), ('name', 1)], info)
|
||||
|
||||
def test_dictionary_indexes(self):
|
||||
"""Ensure that indexes are used when meta[indexes] contains
|
||||
@@ -356,7 +356,7 @@ class IndexesTest(unittest.TestCase):
|
||||
value.get('unique', False),
|
||||
value.get('sparse', False))
|
||||
for key, value in info.iteritems()]
|
||||
self.assertTrue(([('addDate', -1)], True, True) in info)
|
||||
self.assertIn(([('addDate', -1)], True, True), info)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
@@ -491,7 +491,7 @@ class IndexesTest(unittest.TestCase):
|
||||
obj = Test(a=1)
|
||||
obj.save()
|
||||
|
||||
IS_MONGODB_3 = get_mongodb_version()[0] >= 3
|
||||
IS_MONGODB_3 = get_mongodb_version() >= MONGODB_3
|
||||
|
||||
# Need to be explicit about covered indexes as mongoDB doesn't know if
|
||||
# the documents returned might have more keys in that here.
|
||||
@@ -541,19 +541,24 @@ class IndexesTest(unittest.TestCase):
|
||||
[('categories', 1), ('_id', 1)])
|
||||
|
||||
def test_hint(self):
|
||||
MONGO_VER = self.mongodb_version
|
||||
|
||||
TAGS_INDEX_NAME = 'tags_1'
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
meta = {
|
||||
'indexes': [
|
||||
'tags',
|
||||
{
|
||||
'fields': ['tags'],
|
||||
'name': TAGS_INDEX_NAME
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
BlogPost.drop_collection()
|
||||
|
||||
for i in range(0, 10):
|
||||
tags = [("tag %i" % n) for n in range(0, i % 2)]
|
||||
for i in range(10):
|
||||
tags = [("tag %i" % n) for n in range(i % 2)]
|
||||
BlogPost(tags=tags).save()
|
||||
|
||||
self.assertEqual(BlogPost.objects.count(), 10)
|
||||
@@ -563,18 +568,18 @@ class IndexesTest(unittest.TestCase):
|
||||
if pymongo.version != '3.0':
|
||||
self.assertEqual(BlogPost.objects.hint([('tags', 1)]).count(), 10)
|
||||
|
||||
if MONGO_VER == MONGODB_32:
|
||||
# Mongo32 throws an error if an index exists (i.e `tags` in our case)
|
||||
# and you use hint on an index name that does not exist
|
||||
with self.assertRaises(OperationFailure):
|
||||
BlogPost.objects.hint([('ZZ', 1)]).count()
|
||||
else:
|
||||
self.assertEqual(BlogPost.objects.hint([('ZZ', 1)]).count(), 10)
|
||||
|
||||
if pymongo.version >= '2.8':
|
||||
self.assertEqual(BlogPost.objects.hint('tags').count(), 10)
|
||||
else:
|
||||
def invalid_index():
|
||||
BlogPost.objects.hint('tags').next()
|
||||
self.assertRaises(TypeError, invalid_index)
|
||||
self.assertEqual(BlogPost.objects.hint(TAGS_INDEX_NAME ).count(), 10)
|
||||
|
||||
def invalid_index_2():
|
||||
return BlogPost.objects.hint(('tags', 1)).next()
|
||||
self.assertRaises(Exception, invalid_index_2)
|
||||
with self.assertRaises(Exception):
|
||||
BlogPost.objects.hint(('tags', 1)).next()
|
||||
|
||||
def test_unique(self):
|
||||
"""Ensure that uniqueness constraints are applied to fields.
|
||||
@@ -749,7 +754,7 @@ class IndexesTest(unittest.TestCase):
|
||||
except NotUniqueError:
|
||||
pass
|
||||
|
||||
def test_unique_and_primary(self):
|
||||
def test_primary_save_duplicate_update_existing_object(self):
|
||||
"""If you set a field as primary, then unexpected behaviour can occur.
|
||||
You won't create a duplicate but you will update an existing document.
|
||||
"""
|
||||
@@ -803,7 +808,7 @@ class IndexesTest(unittest.TestCase):
|
||||
info = BlogPost.objects._collection.index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
index_item = [('_id', 1), ('comments.comment_id', 1)]
|
||||
self.assertTrue(index_item in info)
|
||||
self.assertIn(index_item, info)
|
||||
|
||||
def test_compound_key_embedded(self):
|
||||
|
||||
@@ -850,8 +855,8 @@ class IndexesTest(unittest.TestCase):
|
||||
|
||||
info = MyDoc.objects._collection.index_information()
|
||||
info = [value['key'] for key, value in info.iteritems()]
|
||||
self.assertTrue([('provider_ids.foo', 1)] in info)
|
||||
self.assertTrue([('provider_ids.bar', 1)] in info)
|
||||
self.assertIn([('provider_ids.foo', 1)], info)
|
||||
self.assertIn([('provider_ids.bar', 1)], info)
|
||||
|
||||
def test_sparse_compound_indexes(self):
|
||||
|
||||
@@ -867,7 +872,7 @@ class IndexesTest(unittest.TestCase):
|
||||
info['provider_ids.foo_1_provider_ids.bar_1']['key'])
|
||||
self.assertTrue(info['provider_ids.foo_1_provider_ids.bar_1']['sparse'])
|
||||
|
||||
@needs_mongodb_v26
|
||||
@requires_mongodb_gte_26
|
||||
def test_text_indexes(self):
|
||||
class Book(Document):
|
||||
title = DictField()
|
||||
@@ -876,9 +881,9 @@ class IndexesTest(unittest.TestCase):
|
||||
}
|
||||
|
||||
indexes = Book.objects._collection.index_information()
|
||||
self.assertTrue("title_text" in indexes)
|
||||
self.assertIn("title_text", indexes)
|
||||
key = indexes["title_text"]["key"]
|
||||
self.assertTrue(('_fts', 'text') in key)
|
||||
self.assertIn(('_fts', 'text'), key)
|
||||
|
||||
def test_hashed_indexes(self):
|
||||
|
||||
@@ -889,8 +894,8 @@ class IndexesTest(unittest.TestCase):
|
||||
}
|
||||
|
||||
indexes = Book.objects._collection.index_information()
|
||||
self.assertTrue("ref_id_hashed" in indexes)
|
||||
self.assertTrue(('ref_id', 'hashed') in indexes["ref_id_hashed"]["key"])
|
||||
self.assertIn("ref_id_hashed", indexes)
|
||||
self.assertIn(('ref_id', 'hashed'), indexes["ref_id_hashed"]["key"])
|
||||
|
||||
def test_indexes_after_database_drop(self):
|
||||
"""
|
||||
@@ -1013,7 +1018,7 @@ class IndexesTest(unittest.TestCase):
|
||||
TestDoc.ensure_indexes()
|
||||
|
||||
index_info = TestDoc._get_collection().index_information()
|
||||
self.assertTrue('shard_1_1__cls_1_txt_1_1' in index_info)
|
||||
self.assertIn('shard_1_1__cls_1_txt_1_1', index_info)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from tests.fixtures import Base
|
||||
|
||||
from mongoengine import Document, EmbeddedDocument, connect
|
||||
from mongoengine import (BooleanField, Document, EmbeddedDocument,
|
||||
EmbeddedDocumentField, GenericReferenceField,
|
||||
IntField, ReferenceField, StringField, connect)
|
||||
from mongoengine.connection import get_db
|
||||
from mongoengine.fields import (BooleanField, GenericReferenceField,
|
||||
IntField, StringField)
|
||||
from tests.fixtures import Base
|
||||
|
||||
__all__ = ('InheritanceTest', )
|
||||
|
||||
@@ -26,6 +23,27 @@ class InheritanceTest(unittest.TestCase):
|
||||
continue
|
||||
self.db.drop_collection(collection)
|
||||
|
||||
def test_constructor_cls(self):
|
||||
# Ensures _cls is properly set during construction
|
||||
# and when object gets reloaded (prevent regression of #1950)
|
||||
class EmbedData(EmbeddedDocument):
|
||||
data = StringField()
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
class DataDoc(Document):
|
||||
name = StringField()
|
||||
embed = EmbeddedDocumentField(EmbedData)
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
test_doc = DataDoc(name='test', embed=EmbedData(data='data'))
|
||||
assert test_doc._cls == 'DataDoc'
|
||||
assert test_doc.embed._cls == 'EmbedData'
|
||||
test_doc.save()
|
||||
saved_doc = DataDoc.objects.with_id(test_doc.id)
|
||||
assert test_doc._cls == saved_doc._cls
|
||||
assert test_doc.embed._cls == saved_doc.embed._cls
|
||||
test_doc.delete()
|
||||
|
||||
def test_superclasses(self):
|
||||
"""Ensure that the correct list of superclasses is assembled.
|
||||
"""
|
||||
@@ -258,9 +276,10 @@ class InheritanceTest(unittest.TestCase):
|
||||
name = StringField()
|
||||
|
||||
# can't inherit because Animal didn't explicitly allow inheritance
|
||||
with self.assertRaises(ValueError):
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
class Dog(Animal):
|
||||
pass
|
||||
self.assertIn("Document Animal may not be subclassed", str(cm.exception))
|
||||
|
||||
# Check that _cls etc aren't present on simple documents
|
||||
dog = Animal(name='dog').save()
|
||||
@@ -268,7 +287,7 @@ class InheritanceTest(unittest.TestCase):
|
||||
|
||||
collection = self.db[Animal._get_collection_name()]
|
||||
obj = collection.find_one()
|
||||
self.assertFalse('_cls' in obj)
|
||||
self.assertNotIn('_cls', obj)
|
||||
|
||||
def test_cant_turn_off_inheritance_on_subclass(self):
|
||||
"""Ensure if inheritance is on in a subclass you cant turn it off.
|
||||
@@ -277,9 +296,10 @@ class InheritanceTest(unittest.TestCase):
|
||||
name = StringField()
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
class Mammal(Animal):
|
||||
meta = {'allow_inheritance': False}
|
||||
self.assertEqual(str(cm.exception), 'Only direct subclasses of Document may set "allow_inheritance" to False')
|
||||
|
||||
def test_allow_inheritance_abstract_document(self):
|
||||
"""Ensure that abstract documents can set inheritance rules and that
|
||||
@@ -292,13 +312,48 @@ class InheritanceTest(unittest.TestCase):
|
||||
class Animal(FinalDocument):
|
||||
name = StringField()
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
class Mammal(Animal):
|
||||
pass
|
||||
|
||||
# Check that _cls isn't present in simple documents
|
||||
doc = Animal(name='dog')
|
||||
self.assertFalse('_cls' in doc.to_mongo())
|
||||
self.assertNotIn('_cls', doc.to_mongo())
|
||||
|
||||
def test_using_abstract_class_in_reference_field(self):
|
||||
# Ensures no regression of #1920
|
||||
class AbstractHuman(Document):
|
||||
meta = {'abstract': True}
|
||||
|
||||
class Dad(AbstractHuman):
|
||||
name = StringField()
|
||||
|
||||
class Home(Document):
|
||||
dad = ReferenceField(AbstractHuman) # Referencing the abstract class
|
||||
address = StringField()
|
||||
|
||||
dad = Dad(name='5').save()
|
||||
Home(dad=dad, address='street').save()
|
||||
|
||||
home = Home.objects.first()
|
||||
home.address = 'garbage'
|
||||
home.save() # Was failing with ValidationError
|
||||
|
||||
def test_abstract_class_referencing_self(self):
|
||||
# Ensures no regression of #1920
|
||||
class Human(Document):
|
||||
meta = {'abstract': True}
|
||||
creator = ReferenceField('self', dbref=True)
|
||||
|
||||
class User(Human):
|
||||
name = StringField()
|
||||
|
||||
user = User(name='John').save()
|
||||
user2 = User(name='Foo', creator=user).save()
|
||||
|
||||
user2 = User.objects.with_id(user2.id)
|
||||
user2.name = 'Bar'
|
||||
user2.save() # Was failing with ValidationError
|
||||
|
||||
def test_abstract_handle_ids_in_metaclass_properly(self):
|
||||
|
||||
@@ -358,11 +413,11 @@ class InheritanceTest(unittest.TestCase):
|
||||
meta = {'abstract': True,
|
||||
'allow_inheritance': False}
|
||||
|
||||
bkk = City(continent='asia')
|
||||
self.assertEqual(None, bkk.pk)
|
||||
city = City(continent='asia')
|
||||
self.assertEqual(None, city.pk)
|
||||
# TODO: expected error? Shouldn't we create a new error type?
|
||||
with self.assertRaises(KeyError):
|
||||
setattr(bkk, 'pk', 1)
|
||||
setattr(city, 'pk', 1)
|
||||
|
||||
def test_allow_inheritance_embedded_document(self):
|
||||
"""Ensure embedded documents respect inheritance."""
|
||||
@@ -374,14 +429,14 @@ class InheritanceTest(unittest.TestCase):
|
||||
pass
|
||||
|
||||
doc = Comment(content='test')
|
||||
self.assertFalse('_cls' in doc.to_mongo())
|
||||
self.assertNotIn('_cls', doc.to_mongo())
|
||||
|
||||
class Comment(EmbeddedDocument):
|
||||
content = StringField()
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
doc = Comment(content='test')
|
||||
self.assertTrue('_cls' in doc.to_mongo())
|
||||
self.assertIn('_cls', doc.to_mongo())
|
||||
|
||||
def test_document_inheritance(self):
|
||||
"""Ensure mutliple inheritance of abstract documents
|
||||
@@ -434,8 +489,8 @@ class InheritanceTest(unittest.TestCase):
|
||||
for cls in [Animal, Fish, Guppy]:
|
||||
self.assertEqual(cls._meta[k], v)
|
||||
|
||||
self.assertFalse('collection' in Animal._meta)
|
||||
self.assertFalse('collection' in Mammal._meta)
|
||||
self.assertNotIn('collection', Animal._meta)
|
||||
self.assertNotIn('collection', Mammal._meta)
|
||||
|
||||
self.assertEqual(Animal._get_collection_name(), None)
|
||||
self.assertEqual(Mammal._get_collection_name(), None)
|
||||
|
||||
@@ -8,9 +8,12 @@ import weakref
|
||||
|
||||
from datetime import datetime
|
||||
from bson import DBRef, ObjectId
|
||||
from pymongo.errors import DuplicateKeyError
|
||||
|
||||
from tests import fixtures
|
||||
from tests.fixtures import (PickleEmbedded, PickleTest, PickleSignalsTest,
|
||||
PickleDynamicEmbedded, PickleDynamicTest)
|
||||
from tests.utils import MongoDBTestCase
|
||||
|
||||
from mongoengine import *
|
||||
from mongoengine.base import get_document, _document_registry
|
||||
@@ -22,7 +25,7 @@ from mongoengine.queryset import NULLIFY, Q
|
||||
from mongoengine.context_managers import switch_db, query_counter
|
||||
from mongoengine import signals
|
||||
|
||||
from tests.utils import needs_mongodb_v26
|
||||
from tests.utils import requires_mongodb_gte_26
|
||||
|
||||
TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__),
|
||||
'../fields/mongoengine.png')
|
||||
@@ -30,12 +33,9 @@ TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__),
|
||||
__all__ = ("InstanceTest",)
|
||||
|
||||
|
||||
class InstanceTest(unittest.TestCase):
|
||||
class InstanceTest(MongoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db='mongoenginetest')
|
||||
self.db = get_db()
|
||||
|
||||
class Job(EmbeddedDocument):
|
||||
name = StringField()
|
||||
years = IntField()
|
||||
@@ -357,7 +357,7 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
user_son = User.objects._collection.find_one()
|
||||
self.assertEqual(user_son['_id'], 'test')
|
||||
self.assertTrue('username' not in user_son['_id'])
|
||||
self.assertNotIn('username', user_son['_id'])
|
||||
|
||||
User.drop_collection()
|
||||
|
||||
@@ -370,7 +370,7 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
user_son = User.objects._collection.find_one()
|
||||
self.assertEqual(user_son['_id'], 'mongo')
|
||||
self.assertTrue('username' not in user_son['_id'])
|
||||
self.assertNotIn('username', user_son['_id'])
|
||||
|
||||
def test_document_not_registered(self):
|
||||
class Place(Document):
|
||||
@@ -550,21 +550,14 @@ class InstanceTest(unittest.TestCase):
|
||||
pass
|
||||
|
||||
f = Foo()
|
||||
try:
|
||||
with self.assertRaises(Foo.DoesNotExist):
|
||||
f.reload()
|
||||
except Foo.DoesNotExist:
|
||||
pass
|
||||
except Exception:
|
||||
self.assertFalse("Threw wrong exception")
|
||||
|
||||
f.save()
|
||||
f.delete()
|
||||
try:
|
||||
|
||||
with self.assertRaises(Foo.DoesNotExist):
|
||||
f.reload()
|
||||
except Foo.DoesNotExist:
|
||||
pass
|
||||
except Exception:
|
||||
self.assertFalse("Threw wrong exception")
|
||||
|
||||
def test_reload_of_non_strict_with_special_field_name(self):
|
||||
"""Ensures reloading works for documents with meta strict == False."""
|
||||
@@ -601,10 +594,10 @@ class InstanceTest(unittest.TestCase):
|
||||
# Length = length(assigned fields + id)
|
||||
self.assertEqual(len(person), 5)
|
||||
|
||||
self.assertTrue('age' in person)
|
||||
self.assertIn('age', person)
|
||||
person.age = None
|
||||
self.assertFalse('age' in person)
|
||||
self.assertFalse('nationality' in person)
|
||||
self.assertNotIn('age', person)
|
||||
self.assertNotIn('nationality', person)
|
||||
|
||||
def test_embedded_document_to_mongo(self):
|
||||
class Person(EmbeddedDocument):
|
||||
@@ -634,8 +627,8 @@ class InstanceTest(unittest.TestCase):
|
||||
class Comment(EmbeddedDocument):
|
||||
content = StringField()
|
||||
|
||||
self.assertTrue('content' in Comment._fields)
|
||||
self.assertFalse('id' in Comment._fields)
|
||||
self.assertIn('content', Comment._fields)
|
||||
self.assertNotIn('id', Comment._fields)
|
||||
|
||||
def test_embedded_document_instance(self):
|
||||
"""Ensure that embedded documents can reference parent instance."""
|
||||
@@ -734,12 +727,12 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
t = TestDocument(status="draft", pub_date=datetime.now())
|
||||
|
||||
try:
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
t.save()
|
||||
except ValidationError as e:
|
||||
expect_msg = "Draft entries may not have a publication date."
|
||||
self.assertTrue(expect_msg in e.message)
|
||||
self.assertEqual(e.to_dict(), {'__all__': expect_msg})
|
||||
|
||||
expected_msg = "Draft entries may not have a publication date."
|
||||
self.assertIn(expected_msg, cm.exception.message)
|
||||
self.assertEqual(cm.exception.to_dict(), {'__all__': expected_msg})
|
||||
|
||||
t = TestDocument(status="published")
|
||||
t.save(clean=False)
|
||||
@@ -773,12 +766,13 @@ class InstanceTest(unittest.TestCase):
|
||||
TestDocument.drop_collection()
|
||||
|
||||
t = TestDocument(doc=TestEmbeddedDocument(x=10, y=25, z=15))
|
||||
try:
|
||||
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
t.save()
|
||||
except ValidationError as e:
|
||||
expect_msg = "Value of z != x + y"
|
||||
self.assertTrue(expect_msg in e.message)
|
||||
self.assertEqual(e.to_dict(), {'doc': {'__all__': expect_msg}})
|
||||
|
||||
expected_msg = "Value of z != x + y"
|
||||
self.assertIn(expected_msg, cm.exception.message)
|
||||
self.assertEqual(cm.exception.to_dict(), {'doc': {'__all__': expected_msg}})
|
||||
|
||||
t = TestDocument(doc=TestEmbeddedDocument(x=10, y=25)).save()
|
||||
self.assertEqual(t.doc.z, 35)
|
||||
@@ -846,12 +840,18 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
self.assertDbEqual([dict(other_doc.to_mongo()), dict(doc.to_mongo())])
|
||||
|
||||
@needs_mongodb_v26
|
||||
@requires_mongodb_gte_26
|
||||
def test_modify_with_positional_push(self):
|
||||
class Content(EmbeddedDocument):
|
||||
keywords = ListField(StringField())
|
||||
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
content = EmbeddedDocumentField(Content)
|
||||
|
||||
post = BlogPost.objects.create(
|
||||
tags=['python'], content=Content(keywords=['ipsum']))
|
||||
|
||||
post = BlogPost.objects.create(tags=['python'])
|
||||
self.assertEqual(post.tags, ['python'])
|
||||
post.modify(push__tags__0=['code', 'mongo'])
|
||||
self.assertEqual(post.tags, ['code', 'mongo', 'python'])
|
||||
@@ -862,6 +862,16 @@ class InstanceTest(unittest.TestCase):
|
||||
['code', 'mongo', 'python']
|
||||
)
|
||||
|
||||
self.assertEqual(post.content.keywords, ['ipsum'])
|
||||
post.modify(push__content__keywords__0=['lorem'])
|
||||
self.assertEqual(post.content.keywords, ['lorem', 'ipsum'])
|
||||
|
||||
# Assert same order of the list items is maintained in the db
|
||||
self.assertEqual(
|
||||
BlogPost._get_collection().find_one({'_id': post.pk})['content']['keywords'],
|
||||
['lorem', 'ipsum']
|
||||
)
|
||||
|
||||
def test_save(self):
|
||||
"""Ensure that a document may be saved in the database."""
|
||||
|
||||
@@ -1428,6 +1438,60 @@ class InstanceTest(unittest.TestCase):
|
||||
self.assertEqual(person.age, 21)
|
||||
self.assertEqual(person.active, False)
|
||||
|
||||
def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop(self):
|
||||
# Refers to Issue #1685
|
||||
class EmbeddedChildModel(EmbeddedDocument):
|
||||
id = DictField(primary_key=True)
|
||||
|
||||
class ParentModel(Document):
|
||||
child = EmbeddedDocumentField(
|
||||
EmbeddedChildModel)
|
||||
|
||||
emb = EmbeddedChildModel(id={'1': [1]})
|
||||
ParentModel(children=emb)._get_changed_fields()
|
||||
|
||||
def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop(self):
|
||||
class User(Document):
|
||||
id = IntField(primary_key=True)
|
||||
name = StringField()
|
||||
|
||||
class Message(Document):
|
||||
id = IntField(primary_key=True)
|
||||
author = ReferenceField(User)
|
||||
|
||||
Message.drop_collection()
|
||||
|
||||
# All objects share the same id, but each in a different collection
|
||||
user = User(id=1, name='user-name').save()
|
||||
message = Message(id=1, author=user).save()
|
||||
|
||||
message.author.name = 'tutu'
|
||||
self.assertEqual(message._get_changed_fields(), [])
|
||||
self.assertEqual(user._get_changed_fields(), ['name'])
|
||||
|
||||
def test__get_changed_fields_same_ids_embedded(self):
|
||||
# Refers to Issue #1768
|
||||
class User(EmbeddedDocument):
|
||||
id = IntField()
|
||||
name = StringField()
|
||||
|
||||
class Message(Document):
|
||||
id = IntField(primary_key=True)
|
||||
author = EmbeddedDocumentField(User)
|
||||
|
||||
Message.drop_collection()
|
||||
|
||||
# All objects share the same id, but each in a different collection
|
||||
user = User(id=1, name='user-name')#.save()
|
||||
message = Message(id=1, author=user).save()
|
||||
|
||||
message.author.name = 'tutu'
|
||||
self.assertEqual(message._get_changed_fields(), ['author.name'])
|
||||
message.save()
|
||||
|
||||
message_fetched = Message.objects.with_id(message.id)
|
||||
self.assertEqual(message_fetched.author.name, 'tutu')
|
||||
|
||||
def test_query_count_when_saving(self):
|
||||
"""Ensure references don't cause extra fetches when saving"""
|
||||
class Organization(Document):
|
||||
@@ -1461,9 +1525,9 @@ class InstanceTest(unittest.TestCase):
|
||||
user = User.objects.first()
|
||||
# Even if stored as ObjectId's internally mongoengine uses DBRefs
|
||||
# As ObjectId's aren't automatically derefenced
|
||||
self.assertTrue(isinstance(user._data['orgs'][0], DBRef))
|
||||
self.assertTrue(isinstance(user.orgs[0], Organization))
|
||||
self.assertTrue(isinstance(user._data['orgs'][0], Organization))
|
||||
self.assertIsInstance(user._data['orgs'][0], DBRef)
|
||||
self.assertIsInstance(user.orgs[0], Organization)
|
||||
self.assertIsInstance(user._data['orgs'][0], Organization)
|
||||
|
||||
# Changing a value
|
||||
with query_counter() as q:
|
||||
@@ -1843,9 +1907,8 @@ class InstanceTest(unittest.TestCase):
|
||||
post_obj = BlogPost.objects.first()
|
||||
|
||||
# Test laziness
|
||||
self.assertTrue(isinstance(post_obj._data['author'],
|
||||
bson.DBRef))
|
||||
self.assertTrue(isinstance(post_obj.author, self.Person))
|
||||
self.assertIsInstance(post_obj._data['author'], bson.DBRef)
|
||||
self.assertIsInstance(post_obj.author, self.Person)
|
||||
self.assertEqual(post_obj.author.name, 'Test User')
|
||||
|
||||
# Ensure that the dereferenced object may be changed and saved
|
||||
@@ -2251,12 +2314,12 @@ class InstanceTest(unittest.TestCase):
|
||||
# Make sure docs are properly identified in a list (__eq__ is used
|
||||
# for the comparison).
|
||||
all_user_list = list(User.objects.all())
|
||||
self.assertTrue(u1 in all_user_list)
|
||||
self.assertTrue(u2 in all_user_list)
|
||||
self.assertTrue(u3 in all_user_list)
|
||||
self.assertTrue(u4 not in all_user_list) # New object
|
||||
self.assertTrue(b1 not in all_user_list) # Other object
|
||||
self.assertTrue(b2 not in all_user_list) # Other object
|
||||
self.assertIn(u1, all_user_list)
|
||||
self.assertIn(u2, all_user_list)
|
||||
self.assertIn(u3, all_user_list)
|
||||
self.assertNotIn(u4, all_user_list) # New object
|
||||
self.assertNotIn(b1, all_user_list) # Other object
|
||||
self.assertNotIn(b2, all_user_list) # Other object
|
||||
|
||||
# Make sure docs can be used as keys in a dict (__hash__ is used
|
||||
# for hashing the docs).
|
||||
@@ -2274,10 +2337,10 @@ class InstanceTest(unittest.TestCase):
|
||||
# Make sure docs are properly identified in a set (__hash__ is used
|
||||
# for hashing the docs).
|
||||
all_user_set = set(User.objects.all())
|
||||
self.assertTrue(u1 in all_user_set)
|
||||
self.assertTrue(u4 not in all_user_set)
|
||||
self.assertTrue(b1 not in all_user_list)
|
||||
self.assertTrue(b2 not in all_user_list)
|
||||
self.assertIn(u1, all_user_set)
|
||||
self.assertNotIn(u4, all_user_set)
|
||||
self.assertNotIn(b1, all_user_list)
|
||||
self.assertNotIn(b2, all_user_list)
|
||||
|
||||
# Make sure duplicate docs aren't accepted in the set
|
||||
self.assertEqual(len(all_user_set), 3)
|
||||
@@ -2978,7 +3041,7 @@ class InstanceTest(unittest.TestCase):
|
||||
Person(name="Harry Potter").save()
|
||||
|
||||
person = Person.objects.first()
|
||||
self.assertTrue('id' in person._data.keys())
|
||||
self.assertIn('id', person._data.keys())
|
||||
self.assertEqual(person._data.get('id'), person.id)
|
||||
|
||||
def test_complex_nesting_document_and_embedded_document(self):
|
||||
@@ -3070,36 +3133,36 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
dbref2 = f._data['test2']
|
||||
obj2 = f.test2
|
||||
self.assertTrue(isinstance(dbref2, DBRef))
|
||||
self.assertTrue(isinstance(obj2, Test2))
|
||||
self.assertTrue(obj2.id == dbref2.id)
|
||||
self.assertTrue(obj2 == dbref2)
|
||||
self.assertTrue(dbref2 == obj2)
|
||||
self.assertIsInstance(dbref2, DBRef)
|
||||
self.assertIsInstance(obj2, Test2)
|
||||
self.assertEqual(obj2.id, dbref2.id)
|
||||
self.assertEqual(obj2, dbref2)
|
||||
self.assertEqual(dbref2, obj2)
|
||||
|
||||
dbref3 = f._data['test3']
|
||||
obj3 = f.test3
|
||||
self.assertTrue(isinstance(dbref3, DBRef))
|
||||
self.assertTrue(isinstance(obj3, Test3))
|
||||
self.assertTrue(obj3.id == dbref3.id)
|
||||
self.assertTrue(obj3 == dbref3)
|
||||
self.assertTrue(dbref3 == obj3)
|
||||
self.assertIsInstance(dbref3, DBRef)
|
||||
self.assertIsInstance(obj3, Test3)
|
||||
self.assertEqual(obj3.id, dbref3.id)
|
||||
self.assertEqual(obj3, dbref3)
|
||||
self.assertEqual(dbref3, obj3)
|
||||
|
||||
self.assertTrue(obj2.id == obj3.id)
|
||||
self.assertTrue(dbref2.id == dbref3.id)
|
||||
self.assertFalse(dbref2 == dbref3)
|
||||
self.assertFalse(dbref3 == dbref2)
|
||||
self.assertTrue(dbref2 != dbref3)
|
||||
self.assertTrue(dbref3 != dbref2)
|
||||
self.assertEqual(obj2.id, obj3.id)
|
||||
self.assertEqual(dbref2.id, dbref3.id)
|
||||
self.assertNotEqual(dbref2, dbref3)
|
||||
self.assertNotEqual(dbref3, dbref2)
|
||||
self.assertNotEqual(dbref2, dbref3)
|
||||
self.assertNotEqual(dbref3, dbref2)
|
||||
|
||||
self.assertFalse(obj2 == dbref3)
|
||||
self.assertFalse(dbref3 == obj2)
|
||||
self.assertTrue(obj2 != dbref3)
|
||||
self.assertTrue(dbref3 != obj2)
|
||||
self.assertNotEqual(obj2, dbref3)
|
||||
self.assertNotEqual(dbref3, obj2)
|
||||
self.assertNotEqual(obj2, dbref3)
|
||||
self.assertNotEqual(dbref3, obj2)
|
||||
|
||||
self.assertFalse(obj3 == dbref2)
|
||||
self.assertFalse(dbref2 == obj3)
|
||||
self.assertTrue(obj3 != dbref2)
|
||||
self.assertTrue(dbref2 != obj3)
|
||||
self.assertNotEqual(obj3, dbref2)
|
||||
self.assertNotEqual(dbref2, obj3)
|
||||
self.assertNotEqual(obj3, dbref2)
|
||||
self.assertNotEqual(dbref2, obj3)
|
||||
|
||||
def test_default_values(self):
|
||||
class Person(Document):
|
||||
@@ -3148,6 +3211,64 @@ class InstanceTest(unittest.TestCase):
|
||||
self.assertEquals(p.id, None)
|
||||
p.id = "12345" # in case it is not working: "OperationError: Shard Keys are immutable..." will be raised here
|
||||
|
||||
def test_from_son_created_False_without_id(self):
|
||||
class MyPerson(Document):
|
||||
name = StringField()
|
||||
|
||||
MyPerson.objects.delete()
|
||||
|
||||
p = MyPerson.from_json('{"name": "a_fancy_name"}', created=False)
|
||||
self.assertFalse(p._created)
|
||||
self.assertIsNone(p.id)
|
||||
p.save()
|
||||
self.assertIsNotNone(p.id)
|
||||
saved_p = MyPerson.objects.get(id=p.id)
|
||||
self.assertEqual(saved_p.name, 'a_fancy_name')
|
||||
|
||||
def test_from_son_created_False_with_id(self):
|
||||
# 1854
|
||||
class MyPerson(Document):
|
||||
name = StringField()
|
||||
|
||||
MyPerson.objects.delete()
|
||||
|
||||
p = MyPerson.from_json('{"_id": "5b85a8b04ec5dc2da388296e", "name": "a_fancy_name"}', created=False)
|
||||
self.assertFalse(p._created)
|
||||
self.assertEqual(p._changed_fields, [])
|
||||
self.assertEqual(p.name, 'a_fancy_name')
|
||||
self.assertEqual(p.id, ObjectId('5b85a8b04ec5dc2da388296e'))
|
||||
p.save()
|
||||
|
||||
with self.assertRaises(DoesNotExist):
|
||||
# Since created=False and we gave an id in the json and _changed_fields is empty
|
||||
# mongoengine assumes that the document exits with that structure already
|
||||
# and calling .save() didn't save anything
|
||||
MyPerson.objects.get(id=p.id)
|
||||
|
||||
self.assertFalse(p._created)
|
||||
p.name = 'a new fancy name'
|
||||
self.assertEqual(p._changed_fields, ['name'])
|
||||
p.save()
|
||||
saved_p = MyPerson.objects.get(id=p.id)
|
||||
self.assertEqual(saved_p.name, p.name)
|
||||
|
||||
def test_from_son_created_True_with_an_id(self):
|
||||
class MyPerson(Document):
|
||||
name = StringField()
|
||||
|
||||
MyPerson.objects.delete()
|
||||
|
||||
p = MyPerson.from_json('{"_id": "5b85a8b04ec5dc2da388296e", "name": "a_fancy_name"}', created=True)
|
||||
self.assertTrue(p._created)
|
||||
self.assertEqual(p._changed_fields, [])
|
||||
self.assertEqual(p.name, 'a_fancy_name')
|
||||
self.assertEqual(p.id, ObjectId('5b85a8b04ec5dc2da388296e'))
|
||||
p.save()
|
||||
|
||||
saved_p = MyPerson.objects.get(id=p.id)
|
||||
self.assertEqual(saved_p, p)
|
||||
self.assertEqual(p.name, 'a_fancy_name')
|
||||
|
||||
def test_null_field(self):
|
||||
# 734
|
||||
class User(Document):
|
||||
@@ -3221,7 +3342,7 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
person.update(set__height=2.0)
|
||||
|
||||
@needs_mongodb_v26
|
||||
@requires_mongodb_gte_26
|
||||
def test_push_with_position(self):
|
||||
"""Ensure that push with position works properly for an instance."""
|
||||
class BlogPost(Document):
|
||||
@@ -3248,6 +3369,23 @@ class InstanceTest(unittest.TestCase):
|
||||
blog.reload()
|
||||
self.assertEqual(blog.tags, [["value1", 123]])
|
||||
|
||||
def test_accessing_objects_with_indexes_error(self):
|
||||
insert_result = self.db.company.insert_many([{'name': 'Foo'},
|
||||
{'name': 'Foo'}]) # Force 2 doc with same name
|
||||
REF_OID = insert_result.inserted_ids[0]
|
||||
self.db.user.insert_one({'company': REF_OID}) # Force 2 doc with same name
|
||||
|
||||
class Company(Document):
|
||||
name = StringField(unique=True)
|
||||
|
||||
class User(Document):
|
||||
company = ReferenceField(Company)
|
||||
|
||||
|
||||
# Ensure index creation exception aren't swallowed (#1688)
|
||||
with self.assertRaises(DuplicateKeyError):
|
||||
User.objects().select_related()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -20,16 +20,16 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
|
||||
# 1st level error schema
|
||||
error.errors = {'1st': ValidationError('bad 1st'), }
|
||||
self.assertTrue('1st' in error.to_dict())
|
||||
self.assertIn('1st', error.to_dict())
|
||||
self.assertEqual(error.to_dict()['1st'], 'bad 1st')
|
||||
|
||||
# 2nd level error schema
|
||||
error.errors = {'1st': ValidationError('bad 1st', errors={
|
||||
'2nd': ValidationError('bad 2nd'),
|
||||
})}
|
||||
self.assertTrue('1st' in error.to_dict())
|
||||
self.assertTrue(isinstance(error.to_dict()['1st'], dict))
|
||||
self.assertTrue('2nd' in error.to_dict()['1st'])
|
||||
self.assertIn('1st', error.to_dict())
|
||||
self.assertIsInstance(error.to_dict()['1st'], dict)
|
||||
self.assertIn('2nd', error.to_dict()['1st'])
|
||||
self.assertEqual(error.to_dict()['1st']['2nd'], 'bad 2nd')
|
||||
|
||||
# moar levels
|
||||
@@ -40,10 +40,10 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
}),
|
||||
}),
|
||||
})}
|
||||
self.assertTrue('1st' in error.to_dict())
|
||||
self.assertTrue('2nd' in error.to_dict()['1st'])
|
||||
self.assertTrue('3rd' in error.to_dict()['1st']['2nd'])
|
||||
self.assertTrue('4th' in error.to_dict()['1st']['2nd']['3rd'])
|
||||
self.assertIn('1st', error.to_dict())
|
||||
self.assertIn('2nd', error.to_dict()['1st'])
|
||||
self.assertIn('3rd', error.to_dict()['1st']['2nd'])
|
||||
self.assertIn('4th', error.to_dict()['1st']['2nd']['3rd'])
|
||||
self.assertEqual(error.to_dict()['1st']['2nd']['3rd']['4th'],
|
||||
'Inception')
|
||||
|
||||
@@ -58,7 +58,7 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
try:
|
||||
User().validate()
|
||||
except ValidationError as e:
|
||||
self.assertTrue("User:None" in e.message)
|
||||
self.assertIn("User:None", e.message)
|
||||
self.assertEqual(e.to_dict(), {
|
||||
'username': 'Field is required',
|
||||
'name': 'Field is required'})
|
||||
@@ -68,7 +68,7 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
try:
|
||||
user.save()
|
||||
except ValidationError as e:
|
||||
self.assertTrue("User:RossC0" in e.message)
|
||||
self.assertIn("User:RossC0", e.message)
|
||||
self.assertEqual(e.to_dict(), {
|
||||
'name': 'Field is required'})
|
||||
|
||||
@@ -116,7 +116,7 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
try:
|
||||
Doc(id="bad").validate()
|
||||
except ValidationError as e:
|
||||
self.assertTrue("SubDoc:None" in e.message)
|
||||
self.assertIn("SubDoc:None", e.message)
|
||||
self.assertEqual(e.to_dict(), {
|
||||
"e": {'val': 'OK could not be converted to int'}})
|
||||
|
||||
@@ -127,14 +127,14 @@ class ValidatorErrorTest(unittest.TestCase):
|
||||
doc = Doc.objects.first()
|
||||
keys = doc._data.keys()
|
||||
self.assertEqual(2, len(keys))
|
||||
self.assertTrue('e' in keys)
|
||||
self.assertTrue('id' in keys)
|
||||
self.assertIn('e', keys)
|
||||
self.assertIn('id', keys)
|
||||
|
||||
doc.e.val = "OK"
|
||||
try:
|
||||
doc.save()
|
||||
except ValidationError as e:
|
||||
self.assertTrue("Doc:test" in e.message)
|
||||
self.assertIn("Doc:test", e.message)
|
||||
self.assertEqual(e.to_dict(), {
|
||||
"e": {'val': 'OK could not be converted to int'}})
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from fields import *
|
||||
from file_tests import *
|
||||
from geo import *
|
||||
from .fields import *
|
||||
from .file_tests import *
|
||||
from .geo import *
|
||||
|
||||
@@ -175,7 +175,7 @@ class FieldTest(MongoDBTestCase):
|
||||
self.assertEqual(person.name, None)
|
||||
self.assertEqual(person.age, 30)
|
||||
self.assertEqual(person.userid, 'test')
|
||||
self.assertTrue(isinstance(person.created, datetime.datetime))
|
||||
self.assertIsInstance(person.created, datetime.datetime)
|
||||
|
||||
self.assertEqual(person._data['name'], person.name)
|
||||
self.assertEqual(person._data['age'], person.age)
|
||||
@@ -186,6 +186,31 @@ class FieldTest(MongoDBTestCase):
|
||||
data_to_be_saved = sorted(person.to_mongo().keys())
|
||||
self.assertEqual(data_to_be_saved, ['age', 'created', 'userid'])
|
||||
|
||||
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_strict_doc(self):
|
||||
"""List field with default can be set to the empty list (strict)"""
|
||||
# Issue #1733
|
||||
class Doc(Document):
|
||||
x = ListField(IntField(), default=lambda: [42])
|
||||
|
||||
doc = Doc(x=[1]).save()
|
||||
doc.x = []
|
||||
doc.save()
|
||||
reloaded = Doc.objects.get(id=doc.id)
|
||||
self.assertEqual(reloaded.x, [])
|
||||
|
||||
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_dyn_doc(self):
|
||||
"""List field with default can be set to the empty list (dynamic)"""
|
||||
# Issue #1733
|
||||
class Doc(DynamicDocument):
|
||||
x = ListField(IntField(), default=lambda: [42])
|
||||
|
||||
doc = Doc(x=[1]).save()
|
||||
doc.x = []
|
||||
doc.y = 2 # Was triggering the bug
|
||||
doc.save()
|
||||
reloaded = Doc.objects.get(id=doc.id)
|
||||
self.assertEqual(reloaded.x, [])
|
||||
|
||||
def test_default_values_when_deleting_value(self):
|
||||
"""Ensure that default field values are used after non-default
|
||||
values are explicitly deleted.
|
||||
@@ -211,7 +236,7 @@ class FieldTest(MongoDBTestCase):
|
||||
self.assertEqual(person.name, None)
|
||||
self.assertEqual(person.age, 30)
|
||||
self.assertEqual(person.userid, 'test')
|
||||
self.assertTrue(isinstance(person.created, datetime.datetime))
|
||||
self.assertIsInstance(person.created, datetime.datetime)
|
||||
self.assertNotEqual(person.created, datetime.datetime(2014, 6, 12))
|
||||
|
||||
self.assertEqual(person._data['name'], person.name)
|
||||
@@ -264,12 +289,11 @@ class FieldTest(MongoDBTestCase):
|
||||
|
||||
# Retrive data from db and verify it.
|
||||
ret = HandleNoneFields.objects.all()[0]
|
||||
self.assertEqual(ret.str_fld, None)
|
||||
self.assertEqual(ret.int_fld, None)
|
||||
self.assertEqual(ret.flt_fld, None)
|
||||
self.assertIsNone(ret.str_fld)
|
||||
self.assertIsNone(ret.int_fld)
|
||||
self.assertIsNone(ret.flt_fld)
|
||||
|
||||
# Return current time if retrived value is None.
|
||||
self.assertTrue(isinstance(ret.comp_dt_fld, datetime.datetime))
|
||||
self.assertIsNone(ret.comp_dt_fld)
|
||||
|
||||
def test_not_required_handles_none_from_database(self):
|
||||
"""Ensure that every field can handle null values from the
|
||||
@@ -287,7 +311,7 @@ class FieldTest(MongoDBTestCase):
|
||||
doc.str_fld = u'spam ham egg'
|
||||
doc.int_fld = 42
|
||||
doc.flt_fld = 4.2
|
||||
doc.com_dt_fld = datetime.datetime.utcnow()
|
||||
doc.comp_dt_fld = datetime.datetime.utcnow()
|
||||
doc.save()
|
||||
|
||||
# Unset all the fields
|
||||
@@ -302,12 +326,10 @@ class FieldTest(MongoDBTestCase):
|
||||
|
||||
# Retrive data from db and verify it.
|
||||
ret = HandleNoneFields.objects.first()
|
||||
self.assertEqual(ret.str_fld, None)
|
||||
self.assertEqual(ret.int_fld, None)
|
||||
self.assertEqual(ret.flt_fld, None)
|
||||
|
||||
# ComplexDateTimeField returns current time if retrived value is None.
|
||||
self.assertTrue(isinstance(ret.comp_dt_fld, datetime.datetime))
|
||||
self.assertIsNone(ret.str_fld)
|
||||
self.assertIsNone(ret.int_fld)
|
||||
self.assertIsNone(ret.flt_fld)
|
||||
self.assertIsNone(ret.comp_dt_fld)
|
||||
|
||||
# Retrieved object shouldn't pass validation when a re-save is
|
||||
# attempted.
|
||||
@@ -428,6 +450,16 @@ class FieldTest(MongoDBTestCase):
|
||||
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.
|
||||
"""
|
||||
@@ -611,6 +643,8 @@ class FieldTest(MongoDBTestCase):
|
||||
self.assertRaises(ValidationError, person.validate)
|
||||
person.admin = 'Yes'
|
||||
self.assertRaises(ValidationError, person.validate)
|
||||
person.admin = 'False'
|
||||
self.assertRaises(ValidationError, person.validate)
|
||||
|
||||
def test_uuid_field_string(self):
|
||||
"""Test UUID fields storing as String
|
||||
@@ -928,137 +962,6 @@ class FieldTest(MongoDBTestCase):
|
||||
logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1))
|
||||
self.assertEqual(logs.count(), 10)
|
||||
|
||||
def test_complexdatetime_storage(self):
|
||||
"""Tests for complex datetime fields - which can handle
|
||||
microseconds without rounding.
|
||||
"""
|
||||
class LogEntry(Document):
|
||||
date = ComplexDateTimeField()
|
||||
date_with_dots = ComplexDateTimeField(separator='.')
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
# Post UTC - microseconds are rounded (down) nearest millisecond and
|
||||
# dropped - with default datetimefields
|
||||
d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999)
|
||||
log = LogEntry()
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Post UTC - microseconds are rounded (down) nearest millisecond - with
|
||||
# default datetimefields
|
||||
d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Pre UTC dates microseconds below 1000 are dropped - with default
|
||||
# datetimefields
|
||||
d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Pre UTC microseconds above 1000 is wonky - with default datetimefields
|
||||
# log.date has an invalid microsecond value so I can't construct
|
||||
# a date to compare.
|
||||
for i in range(1001, 3113, 33):
|
||||
d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, i)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
log1 = LogEntry.objects.get(date=d1)
|
||||
self.assertEqual(log, log1)
|
||||
|
||||
# Test string padding
|
||||
microsecond = map(int, [math.pow(10, x) for x in range(6)])
|
||||
mm = dd = hh = ii = ss = [1, 10]
|
||||
|
||||
for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond):
|
||||
stored = LogEntry(date=datetime.datetime(*values)).to_mongo()['date']
|
||||
self.assertTrue(re.match('^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$', stored) is not None)
|
||||
|
||||
# Test separator
|
||||
stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()['date_with_dots']
|
||||
self.assertTrue(re.match('^\d{4}.\d{2}.\d{2}.\d{2}.\d{2}.\d{2}.\d{6}$', stored) is not None)
|
||||
|
||||
def test_complexdatetime_usage(self):
|
||||
"""Tests for complex datetime fields - which can handle
|
||||
microseconds without rounding.
|
||||
"""
|
||||
class LogEntry(Document):
|
||||
date = ComplexDateTimeField()
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
d1 = datetime.datetime(1950, 1, 1, 0, 0, 1, 999)
|
||||
log = LogEntry()
|
||||
log.date = d1
|
||||
log.save()
|
||||
|
||||
log1 = LogEntry.objects.get(date=d1)
|
||||
self.assertEqual(log, log1)
|
||||
|
||||
# create extra 59 log entries for a total of 60
|
||||
for i in range(1951, 2010):
|
||||
d = datetime.datetime(i, 1, 1, 0, 0, 1, 999)
|
||||
LogEntry(date=d).save()
|
||||
|
||||
self.assertEqual(LogEntry.objects.count(), 60)
|
||||
|
||||
# Test ordering
|
||||
logs = LogEntry.objects.order_by("date")
|
||||
i = 0
|
||||
while i < 59:
|
||||
self.assertTrue(logs[i].date <= logs[i + 1].date)
|
||||
i += 1
|
||||
|
||||
logs = LogEntry.objects.order_by("-date")
|
||||
i = 0
|
||||
while i < 59:
|
||||
self.assertTrue(logs[i].date >= logs[i + 1].date)
|
||||
i += 1
|
||||
|
||||
# Test searching
|
||||
logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1))
|
||||
self.assertEqual(logs.count(), 30)
|
||||
|
||||
logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1))
|
||||
self.assertEqual(logs.count(), 30)
|
||||
|
||||
logs = LogEntry.objects.filter(
|
||||
date__lte=datetime.datetime(2011, 1, 1),
|
||||
date__gte=datetime.datetime(2000, 1, 1),
|
||||
)
|
||||
self.assertEqual(logs.count(), 10)
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
# Test microsecond-level ordering/filtering
|
||||
for microsecond in (99, 999, 9999, 10000):
|
||||
LogEntry(
|
||||
date=datetime.datetime(2015, 1, 1, 0, 0, 0, microsecond)
|
||||
).save()
|
||||
|
||||
logs = list(LogEntry.objects.order_by('date'))
|
||||
for next_idx, log in enumerate(logs[:-1], start=1):
|
||||
next_log = logs[next_idx]
|
||||
self.assertTrue(log.date < next_log.date)
|
||||
|
||||
logs = list(LogEntry.objects.order_by('-date'))
|
||||
for next_idx, log in enumerate(logs[:-1], start=1):
|
||||
next_log = logs[next_idx]
|
||||
self.assertTrue(log.date > next_log.date)
|
||||
|
||||
logs = LogEntry.objects.filter(
|
||||
date__lte=datetime.datetime(2015, 1, 1, 0, 0, 0, 10000))
|
||||
self.assertEqual(logs.count(), 4)
|
||||
|
||||
def test_list_validation(self):
|
||||
"""Ensure that a list field only accepts lists with valid elements."""
|
||||
AccessLevelChoices = (
|
||||
@@ -1311,7 +1214,7 @@ class FieldTest(MongoDBTestCase):
|
||||
# aka 'del list[index]'
|
||||
# aka 'operator.delitem(list, index)'
|
||||
reset_post()
|
||||
del post.info[2] # del from middle ('2')
|
||||
del post.info[2] # del from middle ('2')
|
||||
self.assertEqual(post.info, ['0', '1', '3', '4', '5'])
|
||||
post.save()
|
||||
post.reload()
|
||||
@@ -1321,7 +1224,7 @@ class FieldTest(MongoDBTestCase):
|
||||
# aka 'del list[i:j]'
|
||||
# aka 'operator.delitem(list, slice(i,j))'
|
||||
reset_post()
|
||||
del post.info[1:3] # removes '1', '2'
|
||||
del post.info[1:3] # removes '1', '2'
|
||||
self.assertEqual(post.info, ['0', '3', '4', '5'])
|
||||
post.save()
|
||||
post.reload()
|
||||
@@ -1736,8 +1639,8 @@ class FieldTest(MongoDBTestCase):
|
||||
e.save()
|
||||
|
||||
e2 = Simple.objects.get(id=e.id)
|
||||
self.assertTrue(isinstance(e2.mapping[0], StringSetting))
|
||||
self.assertTrue(isinstance(e2.mapping[1], IntegerSetting))
|
||||
self.assertIsInstance(e2.mapping[0], StringSetting)
|
||||
self.assertIsInstance(e2.mapping[1], IntegerSetting)
|
||||
|
||||
# Test querying
|
||||
self.assertEqual(
|
||||
@@ -1906,8 +1809,8 @@ class FieldTest(MongoDBTestCase):
|
||||
e.save()
|
||||
|
||||
e2 = Simple.objects.get(id=e.id)
|
||||
self.assertTrue(isinstance(e2.mapping['somestring'], StringSetting))
|
||||
self.assertTrue(isinstance(e2.mapping['someint'], IntegerSetting))
|
||||
self.assertIsInstance(e2.mapping['somestring'], StringSetting)
|
||||
self.assertIsInstance(e2.mapping['someint'], IntegerSetting)
|
||||
|
||||
# Test querying
|
||||
self.assertEqual(
|
||||
@@ -1950,6 +1853,48 @@ class FieldTest(MongoDBTestCase):
|
||||
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)
|
||||
|
||||
def test_mapfield(self):
|
||||
"""Ensure that the MapField handles the declared type."""
|
||||
class Simple(Document):
|
||||
@@ -1991,8 +1936,8 @@ class FieldTest(MongoDBTestCase):
|
||||
e.save()
|
||||
|
||||
e2 = Extensible.objects.get(id=e.id)
|
||||
self.assertTrue(isinstance(e2.mapping['somestring'], StringSetting))
|
||||
self.assertTrue(isinstance(e2.mapping['someint'], IntegerSetting))
|
||||
self.assertIsInstance(e2.mapping['somestring'], StringSetting)
|
||||
self.assertIsInstance(e2.mapping['someint'], IntegerSetting)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
e.mapping['someint'] = 123
|
||||
@@ -2147,6 +2092,15 @@ class FieldTest(MongoDBTestCase):
|
||||
]))
|
||||
self.assertEqual(a.b.c.txt, 'hi')
|
||||
|
||||
def test_embedded_document_field_cant_reference_using_a_str_if_it_does_not_exist_yet(self):
|
||||
raise SkipTest("Using a string reference in an EmbeddedDocumentField does not work if the class isnt registerd yet")
|
||||
|
||||
class MyDoc2(Document):
|
||||
emb = EmbeddedDocumentField('MyDoc')
|
||||
|
||||
class MyDoc(EmbeddedDocument):
|
||||
name = StringField()
|
||||
|
||||
def test_embedded_document_validation(self):
|
||||
"""Ensure that invalid embedded documents cannot be assigned to
|
||||
embedded document fields.
|
||||
@@ -2688,7 +2642,7 @@ class FieldTest(MongoDBTestCase):
|
||||
bm = Bookmark.objects(bookmark_object=post_1).first()
|
||||
|
||||
self.assertEqual(bm.bookmark_object, post_1)
|
||||
self.assertTrue(isinstance(bm.bookmark_object, Post))
|
||||
self.assertIsInstance(bm.bookmark_object, Post)
|
||||
|
||||
bm.bookmark_object = link_1
|
||||
bm.save()
|
||||
@@ -2696,7 +2650,7 @@ class FieldTest(MongoDBTestCase):
|
||||
bm = Bookmark.objects(bookmark_object=link_1).first()
|
||||
|
||||
self.assertEqual(bm.bookmark_object, link_1)
|
||||
self.assertTrue(isinstance(bm.bookmark_object, Link))
|
||||
self.assertIsInstance(bm.bookmark_object, Link)
|
||||
|
||||
def test_generic_reference_list(self):
|
||||
"""Ensure that a ListField properly dereferences generic references.
|
||||
@@ -2931,7 +2885,32 @@ class FieldTest(MongoDBTestCase):
|
||||
doc = Doc.objects.get(ref=DBRef('doc', doc1.pk))
|
||||
self.assertEqual(doc, doc2)
|
||||
|
||||
def test_generic_reference_filter_by_objectid(self):
|
||||
def test_generic_reference_is_not_tracked_in_parent_doc(self):
|
||||
"""Ensure that modifications of related documents (through generic reference) don't influence
|
||||
the owner changed fields (#1934)
|
||||
"""
|
||||
class Doc1(Document):
|
||||
name = StringField()
|
||||
|
||||
class Doc2(Document):
|
||||
ref = GenericReferenceField()
|
||||
refs = ListField(GenericReferenceField())
|
||||
|
||||
Doc1.drop_collection()
|
||||
Doc2.drop_collection()
|
||||
|
||||
doc1 = Doc1(name='garbage1').save()
|
||||
doc11 = Doc1(name='garbage11').save()
|
||||
doc2 = Doc2(ref=doc1, refs=[doc11]).save()
|
||||
|
||||
doc2.ref.name = 'garbage2'
|
||||
self.assertEqual(doc2._get_changed_fields(), [])
|
||||
|
||||
doc2.refs[0].name = 'garbage3'
|
||||
self.assertEqual(doc2._get_changed_fields(), [])
|
||||
self.assertEqual(doc2._delta(), ({}, {}))
|
||||
|
||||
def test_generic_reference_field(self):
|
||||
"""Ensure we can search for a specific generic reference by
|
||||
providing its DBRef.
|
||||
"""
|
||||
@@ -2943,7 +2922,7 @@ class FieldTest(MongoDBTestCase):
|
||||
doc1 = Doc.objects.create()
|
||||
doc2 = Doc.objects.create(ref=doc1)
|
||||
|
||||
self.assertTrue(isinstance(doc1.pk, ObjectId))
|
||||
self.assertIsInstance(doc1.pk, ObjectId)
|
||||
|
||||
doc = Doc.objects.get(ref=doc1.pk)
|
||||
self.assertEqual(doc, doc2)
|
||||
@@ -2967,37 +2946,33 @@ class FieldTest(MongoDBTestCase):
|
||||
self.assertEqual(MIME_TYPE, attachment_1.content_type)
|
||||
self.assertEqual(BLOB, six.binary_type(attachment_1.blob))
|
||||
|
||||
def test_binary_validation(self):
|
||||
"""Ensure that invalid values cannot be assigned to binary fields.
|
||||
def test_binary_validation_succeeds(self):
|
||||
"""Ensure that valid values can be assigned to binary fields.
|
||||
"""
|
||||
class Attachment(Document):
|
||||
blob = BinaryField()
|
||||
|
||||
class AttachmentRequired(Document):
|
||||
blob = BinaryField(required=True)
|
||||
|
||||
class AttachmentSizeLimit(Document):
|
||||
blob = BinaryField(max_bytes=4)
|
||||
|
||||
Attachment.drop_collection()
|
||||
AttachmentRequired.drop_collection()
|
||||
AttachmentSizeLimit.drop_collection()
|
||||
|
||||
attachment = Attachment()
|
||||
attachment.validate()
|
||||
attachment.blob = 2
|
||||
self.assertRaises(ValidationError, attachment.validate)
|
||||
|
||||
attachment_required = AttachmentRequired()
|
||||
self.assertRaises(ValidationError, attachment_required.validate)
|
||||
attachment_required.blob = Binary(six.b('\xe6\x00\xc4\xff\x07'))
|
||||
attachment_required.validate()
|
||||
|
||||
attachment_size_limit = AttachmentSizeLimit(
|
||||
blob=six.b('\xe6\x00\xc4\xff\x07'))
|
||||
self.assertRaises(ValidationError, attachment_size_limit.validate)
|
||||
attachment_size_limit.blob = six.b('\xe6\x00\xc4\xff')
|
||||
attachment_size_limit.validate()
|
||||
_5_BYTES = six.b('\xe6\x00\xc4\xff\x07')
|
||||
_4_BYTES = six.b('\xe6\x00\xc4\xff')
|
||||
self.assertRaises(ValidationError, AttachmentSizeLimit(blob=_5_BYTES).validate)
|
||||
AttachmentSizeLimit(blob=_4_BYTES).validate()
|
||||
|
||||
def test_binary_validation_fails(self):
|
||||
"""Ensure that invalid values cannot be assigned to binary fields."""
|
||||
|
||||
class Attachment(Document):
|
||||
blob = BinaryField()
|
||||
|
||||
for invalid_data in (2, u'Im_a_unicode', ['some_str']):
|
||||
self.assertRaises(ValidationError, Attachment(blob=invalid_data).validate)
|
||||
|
||||
def test_binary_field_primary(self):
|
||||
class Attachment(Document):
|
||||
@@ -3546,13 +3521,13 @@ class FieldTest(MongoDBTestCase):
|
||||
person.save()
|
||||
|
||||
person = Person.objects.first()
|
||||
self.assertTrue(isinstance(person.like, Car))
|
||||
self.assertIsInstance(person.like, Car)
|
||||
|
||||
person.like = Dish(food="arroz", number=15)
|
||||
person.save()
|
||||
|
||||
person = Person.objects.first()
|
||||
self.assertTrue(isinstance(person.like, Dish))
|
||||
self.assertIsInstance(person.like, Dish)
|
||||
|
||||
def test_generic_embedded_document_choices(self):
|
||||
"""Ensure you can limit GenericEmbeddedDocument choices."""
|
||||
@@ -3577,7 +3552,7 @@ class FieldTest(MongoDBTestCase):
|
||||
person.save()
|
||||
|
||||
person = Person.objects.first()
|
||||
self.assertTrue(isinstance(person.like, Dish))
|
||||
self.assertIsInstance(person.like, Dish)
|
||||
|
||||
def test_generic_list_embedded_document_choices(self):
|
||||
"""Ensure you can limit GenericEmbeddedDocument choices inside
|
||||
@@ -3604,7 +3579,7 @@ class FieldTest(MongoDBTestCase):
|
||||
person.save()
|
||||
|
||||
person = Person.objects.first()
|
||||
self.assertTrue(isinstance(person.likes[0], Dish))
|
||||
self.assertIsInstance(person.likes[0], Dish)
|
||||
|
||||
def test_recursive_validation(self):
|
||||
"""Ensure that a validation result to_dict is available."""
|
||||
@@ -3630,18 +3605,17 @@ class FieldTest(MongoDBTestCase):
|
||||
except ValidationError as error:
|
||||
# ValidationError.errors property
|
||||
self.assertTrue(hasattr(error, 'errors'))
|
||||
self.assertTrue(isinstance(error.errors, dict))
|
||||
self.assertTrue('comments' in error.errors)
|
||||
self.assertTrue(1 in error.errors['comments'])
|
||||
self.assertTrue(isinstance(error.errors['comments'][1]['content'],
|
||||
ValidationError))
|
||||
self.assertIsInstance(error.errors, dict)
|
||||
self.assertIn('comments', error.errors)
|
||||
self.assertIn(1, error.errors['comments'])
|
||||
self.assertIsInstance(error.errors['comments'][1]['content'], ValidationError)
|
||||
|
||||
# ValidationError.schema property
|
||||
error_dict = error.to_dict()
|
||||
self.assertTrue(isinstance(error_dict, dict))
|
||||
self.assertTrue('comments' in error_dict)
|
||||
self.assertTrue(1 in error_dict['comments'])
|
||||
self.assertTrue('content' in error_dict['comments'][1])
|
||||
self.assertIsInstance(error_dict, dict)
|
||||
self.assertIn('comments', error_dict)
|
||||
self.assertIn(1, error_dict['comments'])
|
||||
self.assertIn('content', error_dict['comments'][1])
|
||||
self.assertEqual(error_dict['comments'][1]['content'],
|
||||
u'Field is required')
|
||||
|
||||
@@ -3757,7 +3731,7 @@ class FieldTest(MongoDBTestCase):
|
||||
|
||||
# Passes regex validation
|
||||
user = User(email='me@example.com')
|
||||
self.assertTrue(user.validate() is None)
|
||||
self.assertIsNone(user.validate())
|
||||
|
||||
def test_tuples_as_tuples(self):
|
||||
"""Ensure that tuples remain tuples when they are inside
|
||||
@@ -3784,10 +3758,10 @@ class FieldTest(MongoDBTestCase):
|
||||
doc.items = tuples
|
||||
doc.save()
|
||||
x = TestDoc.objects().get()
|
||||
self.assertTrue(x is not None)
|
||||
self.assertTrue(len(x.items) == 1)
|
||||
self.assertTrue(tuple(x.items[0]) in tuples)
|
||||
self.assertTrue(x.items[0] in tuples)
|
||||
self.assertIsNotNone(x)
|
||||
self.assertEqual(len(x.items), 1)
|
||||
self.assertIn(tuple(x.items[0]), tuples)
|
||||
self.assertIn(x.items[0], tuples)
|
||||
|
||||
def test_dynamic_fields_class(self):
|
||||
class Doc2(Document):
|
||||
@@ -3859,7 +3833,7 @@ class FieldTest(MongoDBTestCase):
|
||||
assert isinstance(doc.field, ToEmbedChild)
|
||||
assert doc.field == to_embed_child
|
||||
|
||||
def test_invalid_dict_value(self):
|
||||
def test_dict_field_invalid_dict_value(self):
|
||||
class DictFieldTest(Document):
|
||||
dictionary = DictField(required=True)
|
||||
|
||||
@@ -3873,6 +3847,22 @@ class FieldTest(MongoDBTestCase):
|
||||
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_cls_field(self):
|
||||
class Animal(Document):
|
||||
meta = {'allow_inheritance': True}
|
||||
@@ -3937,8 +3927,8 @@ class FieldTest(MongoDBTestCase):
|
||||
|
||||
doc = TestLongFieldConsideredAsInt64(some_long=42).save()
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db.test_long_field_considered_as_int64.find()[0]['some_long'], Int64))
|
||||
self.assertTrue(isinstance(doc.some_long, six.integer_types))
|
||||
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):
|
||||
@@ -3971,6 +3961,28 @@ class EmbeddedDocumentListFieldTestCase(MongoDBTestCase):
|
||||
self.Comments(author='user3', message='message1')
|
||||
]).save()
|
||||
|
||||
def test_fails_upon_validate_if_provide_a_doc_instead_of_a_list_of_doc(self):
|
||||
# Relates to Issue #1464
|
||||
comment = self.Comments(author='John')
|
||||
|
||||
class Title(Document):
|
||||
content = StringField()
|
||||
|
||||
# Test with an embeddedDocument instead of a list(embeddedDocument)
|
||||
# It's an edge case but it used to fail with a vague error, making it difficult to troubleshoot it
|
||||
post = self.BlogPost(comments=comment)
|
||||
with self.assertRaises(ValidationError) as ctx_err:
|
||||
post.validate()
|
||||
self.assertIn("'comments'", str(ctx_err.exception))
|
||||
self.assertIn('Only lists and tuples may be used in a list field', str(ctx_err.exception))
|
||||
|
||||
# Test with a Document
|
||||
post = self.BlogPost(comments=Title(content='garbage'))
|
||||
with self.assertRaises(ValidationError) as e:
|
||||
post.validate()
|
||||
self.assertIn("'comments'", str(ctx_err.exception))
|
||||
self.assertIn('Only lists and tuples may be used in a list field', str(ctx_err.exception))
|
||||
|
||||
def test_no_keyword_filter(self):
|
||||
"""
|
||||
Tests the filter method of a List of Embedded Documents
|
||||
@@ -4388,6 +4400,45 @@ class EmbeddedDocumentListFieldTestCase(MongoDBTestCase):
|
||||
self.assertEqual(custom_data['a'], CustomData.c_field.custom_data['a'])
|
||||
|
||||
|
||||
class TestEmbeddedDocumentField(MongoDBTestCase):
|
||||
def test___init___(self):
|
||||
class MyDoc(EmbeddedDocument):
|
||||
name = StringField()
|
||||
|
||||
field = EmbeddedDocumentField(MyDoc)
|
||||
self.assertEqual(field.document_type_obj, MyDoc)
|
||||
|
||||
field2 = EmbeddedDocumentField('MyDoc')
|
||||
self.assertEqual(field2.document_type_obj, 'MyDoc')
|
||||
|
||||
def test___init___throw_error_if_document_type_is_not_EmbeddedDocument(self):
|
||||
with self.assertRaises(ValidationError):
|
||||
EmbeddedDocumentField(dict)
|
||||
|
||||
def test_document_type_throw_error_if_not_EmbeddedDocument_subclass(self):
|
||||
|
||||
class MyDoc(Document):
|
||||
name = StringField()
|
||||
|
||||
emb = EmbeddedDocumentField('MyDoc')
|
||||
with self.assertRaises(ValidationError) as ctx:
|
||||
emb.document_type
|
||||
self.assertIn('Invalid embedded document class provided to an EmbeddedDocumentField', str(ctx.exception))
|
||||
|
||||
def test_embedded_document_field_only_allow_subclasses_of_embedded_document(self):
|
||||
# Relates to #1661
|
||||
class MyDoc(Document):
|
||||
name = StringField()
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
class MyFailingDoc(Document):
|
||||
emb = EmbeddedDocumentField(MyDoc)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
class MyFailingdoc2(Document):
|
||||
emb = EmbeddedDocumentField('MyDoc')
|
||||
|
||||
|
||||
class CachedReferenceFieldTest(MongoDBTestCase):
|
||||
|
||||
def test_cached_reference_field_get_and_save(self):
|
||||
@@ -4451,7 +4502,7 @@ class CachedReferenceFieldTest(MongoDBTestCase):
|
||||
|
||||
ocorrence = Ocorrence.objects(animal__tag='heavy').first()
|
||||
self.assertEqual(ocorrence.person, "teste")
|
||||
self.assertTrue(isinstance(ocorrence.animal, Animal))
|
||||
self.assertIsInstance(ocorrence.animal, Animal)
|
||||
|
||||
def test_cached_reference_field_decimal(self):
|
||||
class PersonAuto(Document):
|
||||
@@ -4768,7 +4819,7 @@ class CachedReferenceFieldTest(MongoDBTestCase):
|
||||
animal__tag='heavy',
|
||||
animal__owner__tp='u').first()
|
||||
self.assertEqual(ocorrence.person, "teste")
|
||||
self.assertTrue(isinstance(ocorrence.animal, Animal))
|
||||
self.assertIsInstance(ocorrence.animal, Animal)
|
||||
|
||||
def test_cached_reference_embedded_list_fields(self):
|
||||
class Owner(EmbeddedDocument):
|
||||
@@ -4822,7 +4873,7 @@ class CachedReferenceFieldTest(MongoDBTestCase):
|
||||
animal__tag='heavy',
|
||||
animal__owner__tags='cool').first()
|
||||
self.assertEqual(ocorrence.person, "teste 2")
|
||||
self.assertTrue(isinstance(ocorrence.animal, Animal))
|
||||
self.assertIsInstance(ocorrence.animal, Animal)
|
||||
|
||||
|
||||
class LazyReferenceFieldTest(MongoDBTestCase):
|
||||
@@ -5342,5 +5393,180 @@ class GenericLazyReferenceFieldTest(MongoDBTestCase):
|
||||
check_fields_type(occ)
|
||||
|
||||
|
||||
class ComplexDateTimeFieldTest(MongoDBTestCase):
|
||||
def test_complexdatetime_storage(self):
|
||||
"""Tests for complex datetime fields - which can handle
|
||||
microseconds without rounding.
|
||||
"""
|
||||
class LogEntry(Document):
|
||||
date = ComplexDateTimeField()
|
||||
date_with_dots = ComplexDateTimeField(separator='.')
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
# Post UTC - microseconds are rounded (down) nearest millisecond and
|
||||
# dropped - with default datetimefields
|
||||
d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999)
|
||||
log = LogEntry()
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Post UTC - microseconds are rounded (down) nearest millisecond - with
|
||||
# default datetimefields
|
||||
d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Pre UTC dates microseconds below 1000 are dropped - with default
|
||||
# datetimefields
|
||||
d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
|
||||
# Pre UTC microseconds above 1000 is wonky - with default datetimefields
|
||||
# log.date has an invalid microsecond value so I can't construct
|
||||
# a date to compare.
|
||||
for i in range(1001, 3113, 33):
|
||||
d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, i)
|
||||
log.date = d1
|
||||
log.save()
|
||||
log.reload()
|
||||
self.assertEqual(log.date, d1)
|
||||
log1 = LogEntry.objects.get(date=d1)
|
||||
self.assertEqual(log, log1)
|
||||
|
||||
# Test string padding
|
||||
microsecond = map(int, [math.pow(10, x) for x in range(6)])
|
||||
mm = dd = hh = ii = ss = [1, 10]
|
||||
|
||||
for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond):
|
||||
stored = LogEntry(date=datetime.datetime(*values)).to_mongo()['date']
|
||||
self.assertTrue(re.match('^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$', stored) is not None)
|
||||
|
||||
# Test separator
|
||||
stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()['date_with_dots']
|
||||
self.assertTrue(re.match('^\d{4}.\d{2}.\d{2}.\d{2}.\d{2}.\d{2}.\d{6}$', stored) is not None)
|
||||
|
||||
def test_complexdatetime_usage(self):
|
||||
"""Tests for complex datetime fields - which can handle
|
||||
microseconds without rounding.
|
||||
"""
|
||||
class LogEntry(Document):
|
||||
date = ComplexDateTimeField()
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
d1 = datetime.datetime(1950, 1, 1, 0, 0, 1, 999)
|
||||
log = LogEntry()
|
||||
log.date = d1
|
||||
log.save()
|
||||
|
||||
log1 = LogEntry.objects.get(date=d1)
|
||||
self.assertEqual(log, log1)
|
||||
|
||||
# create extra 59 log entries for a total of 60
|
||||
for i in range(1951, 2010):
|
||||
d = datetime.datetime(i, 1, 1, 0, 0, 1, 999)
|
||||
LogEntry(date=d).save()
|
||||
|
||||
self.assertEqual(LogEntry.objects.count(), 60)
|
||||
|
||||
# Test ordering
|
||||
logs = LogEntry.objects.order_by("date")
|
||||
i = 0
|
||||
while i < 59:
|
||||
self.assertTrue(logs[i].date <= logs[i + 1].date)
|
||||
i += 1
|
||||
|
||||
logs = LogEntry.objects.order_by("-date")
|
||||
i = 0
|
||||
while i < 59:
|
||||
self.assertTrue(logs[i].date >= logs[i + 1].date)
|
||||
i += 1
|
||||
|
||||
# Test searching
|
||||
logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1))
|
||||
self.assertEqual(logs.count(), 30)
|
||||
|
||||
logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1))
|
||||
self.assertEqual(logs.count(), 30)
|
||||
|
||||
logs = LogEntry.objects.filter(
|
||||
date__lte=datetime.datetime(2011, 1, 1),
|
||||
date__gte=datetime.datetime(2000, 1, 1),
|
||||
)
|
||||
self.assertEqual(logs.count(), 10)
|
||||
|
||||
LogEntry.drop_collection()
|
||||
|
||||
# Test microsecond-level ordering/filtering
|
||||
for microsecond in (99, 999, 9999, 10000):
|
||||
LogEntry(
|
||||
date=datetime.datetime(2015, 1, 1, 0, 0, 0, microsecond)
|
||||
).save()
|
||||
|
||||
logs = list(LogEntry.objects.order_by('date'))
|
||||
for next_idx, log in enumerate(logs[:-1], start=1):
|
||||
next_log = logs[next_idx]
|
||||
self.assertTrue(log.date < next_log.date)
|
||||
|
||||
logs = list(LogEntry.objects.order_by('-date'))
|
||||
for next_idx, log in enumerate(logs[:-1], start=1):
|
||||
next_log = logs[next_idx]
|
||||
self.assertTrue(log.date > next_log.date)
|
||||
|
||||
logs = LogEntry.objects.filter(
|
||||
date__lte=datetime.datetime(2015, 1, 1, 0, 0, 0, 10000))
|
||||
self.assertEqual(logs.count(), 4)
|
||||
|
||||
def test_no_default_value(self):
|
||||
class Log(Document):
|
||||
timestamp = ComplexDateTimeField()
|
||||
|
||||
Log.drop_collection()
|
||||
|
||||
log = Log()
|
||||
self.assertIsNone(log.timestamp)
|
||||
log.save()
|
||||
|
||||
fetched_log = Log.objects.with_id(log.id)
|
||||
self.assertIsNone(fetched_log.timestamp)
|
||||
|
||||
def test_default_static_value(self):
|
||||
NOW = datetime.datetime.utcnow()
|
||||
class Log(Document):
|
||||
timestamp = ComplexDateTimeField(default=NOW)
|
||||
|
||||
Log.drop_collection()
|
||||
|
||||
log = Log()
|
||||
self.assertEqual(log.timestamp, NOW)
|
||||
log.save()
|
||||
|
||||
fetched_log = Log.objects.with_id(log.id)
|
||||
self.assertEqual(fetched_log.timestamp, NOW)
|
||||
|
||||
def test_default_callable(self):
|
||||
NOW = datetime.datetime.utcnow()
|
||||
|
||||
class Log(Document):
|
||||
timestamp = ComplexDateTimeField(default=datetime.datetime.utcnow)
|
||||
|
||||
Log.drop_collection()
|
||||
|
||||
log = Log()
|
||||
self.assertGreaterEqual(log.timestamp, NOW)
|
||||
log.save()
|
||||
|
||||
fetched_log = Log.objects.with_id(log.id)
|
||||
self.assertGreaterEqual(fetched_log.timestamp, NOW)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -53,7 +53,7 @@ class FileTest(MongoDBTestCase):
|
||||
putfile.save()
|
||||
|
||||
result = PutFile.objects.first()
|
||||
self.assertTrue(putfile == result)
|
||||
self.assertEqual(putfile, result)
|
||||
self.assertEqual("%s" % result.the_file, "<GridFSProxy: hello (%s)>" % result.the_file.grid_id)
|
||||
self.assertEqual(result.the_file.read(), text)
|
||||
self.assertEqual(result.the_file.content_type, content_type)
|
||||
@@ -71,7 +71,7 @@ class FileTest(MongoDBTestCase):
|
||||
putfile.save()
|
||||
|
||||
result = PutFile.objects.first()
|
||||
self.assertTrue(putfile == result)
|
||||
self.assertEqual(putfile, result)
|
||||
self.assertEqual(result.the_file.read(), text)
|
||||
self.assertEqual(result.the_file.content_type, content_type)
|
||||
result.the_file.delete()
|
||||
@@ -96,7 +96,7 @@ class FileTest(MongoDBTestCase):
|
||||
streamfile.save()
|
||||
|
||||
result = StreamFile.objects.first()
|
||||
self.assertTrue(streamfile == result)
|
||||
self.assertEqual(streamfile, result)
|
||||
self.assertEqual(result.the_file.read(), text + more_text)
|
||||
self.assertEqual(result.the_file.content_type, content_type)
|
||||
result.the_file.seek(0)
|
||||
@@ -132,7 +132,7 @@ class FileTest(MongoDBTestCase):
|
||||
streamfile.save()
|
||||
|
||||
result = StreamFile.objects.first()
|
||||
self.assertTrue(streamfile == result)
|
||||
self.assertEqual(streamfile, result)
|
||||
self.assertEqual(result.the_file.read(), text + more_text)
|
||||
# self.assertEqual(result.the_file.content_type, content_type)
|
||||
result.the_file.seek(0)
|
||||
@@ -161,7 +161,7 @@ class FileTest(MongoDBTestCase):
|
||||
setfile.save()
|
||||
|
||||
result = SetFile.objects.first()
|
||||
self.assertTrue(setfile == result)
|
||||
self.assertEqual(setfile, result)
|
||||
self.assertEqual(result.the_file.read(), text)
|
||||
|
||||
# Try replacing file with new one
|
||||
@@ -169,7 +169,7 @@ class FileTest(MongoDBTestCase):
|
||||
result.save()
|
||||
|
||||
result = SetFile.objects.first()
|
||||
self.assertTrue(setfile == result)
|
||||
self.assertEqual(setfile, result)
|
||||
self.assertEqual(result.the_file.read(), more_text)
|
||||
result.the_file.delete()
|
||||
|
||||
@@ -231,8 +231,8 @@ class FileTest(MongoDBTestCase):
|
||||
test_file_dupe = TestFile()
|
||||
data = test_file_dupe.the_file.read() # Should be None
|
||||
|
||||
self.assertTrue(test_file.name != test_file_dupe.name)
|
||||
self.assertTrue(test_file.the_file.read() != data)
|
||||
self.assertNotEqual(test_file.name, test_file_dupe.name)
|
||||
self.assertNotEqual(test_file.the_file.read(), data)
|
||||
|
||||
TestFile.drop_collection()
|
||||
|
||||
@@ -291,7 +291,7 @@ class FileTest(MongoDBTestCase):
|
||||
the_file = FileField()
|
||||
|
||||
test_file = TestFile()
|
||||
self.assertFalse(test_file.the_file in [{"test": 1}])
|
||||
self.assertNotIn(test_file.the_file, [{"test": 1}])
|
||||
|
||||
def test_file_disk_space(self):
|
||||
""" Test disk space usage when we delete/replace a file """
|
||||
|
||||
@@ -298,9 +298,9 @@ class GeoFieldTest(unittest.TestCase):
|
||||
polygon = PolygonField()
|
||||
|
||||
geo_indicies = Event._geo_indices()
|
||||
self.assertTrue({'fields': [('line', '2dsphere')]} in geo_indicies)
|
||||
self.assertTrue({'fields': [('polygon', '2dsphere')]} in geo_indicies)
|
||||
self.assertTrue({'fields': [('point', '2dsphere')]} in geo_indicies)
|
||||
self.assertIn({'fields': [('line', '2dsphere')]}, geo_indicies)
|
||||
self.assertIn({'fields': [('polygon', '2dsphere')]}, geo_indicies)
|
||||
self.assertIn({'fields': [('point', '2dsphere')]}, geo_indicies)
|
||||
|
||||
def test_indexes_2dsphere_embedded(self):
|
||||
"""Ensure that indexes are created automatically for GeoPointFields.
|
||||
@@ -316,9 +316,9 @@ class GeoFieldTest(unittest.TestCase):
|
||||
venue = EmbeddedDocumentField(Venue)
|
||||
|
||||
geo_indicies = Event._geo_indices()
|
||||
self.assertTrue({'fields': [('venue.line', '2dsphere')]} in geo_indicies)
|
||||
self.assertTrue({'fields': [('venue.polygon', '2dsphere')]} in geo_indicies)
|
||||
self.assertTrue({'fields': [('venue.point', '2dsphere')]} in geo_indicies)
|
||||
self.assertIn({'fields': [('venue.line', '2dsphere')]}, geo_indicies)
|
||||
self.assertIn({'fields': [('venue.polygon', '2dsphere')]}, geo_indicies)
|
||||
self.assertIn({'fields': [('venue.point', '2dsphere')]}, geo_indicies)
|
||||
|
||||
def test_geo_indexes_recursion(self):
|
||||
|
||||
@@ -335,9 +335,9 @@ class GeoFieldTest(unittest.TestCase):
|
||||
|
||||
Parent(name='Berlin').save()
|
||||
info = Parent._get_collection().index_information()
|
||||
self.assertFalse('location_2d' in info)
|
||||
self.assertNotIn('location_2d', info)
|
||||
info = Location._get_collection().index_information()
|
||||
self.assertTrue('location_2d' in info)
|
||||
self.assertIn('location_2d', info)
|
||||
|
||||
self.assertEqual(len(Parent._geo_indices()), 0)
|
||||
self.assertEqual(len(Location._geo_indices()), 1)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from transform import *
|
||||
from field_list import *
|
||||
from queryset import *
|
||||
from visitor import *
|
||||
from geo import *
|
||||
from modify import *
|
||||
from .transform import *
|
||||
from .field_list import *
|
||||
from .queryset import *
|
||||
from .visitor import *
|
||||
from .geo import *
|
||||
from .modify import *
|
||||
|
||||
@@ -181,7 +181,7 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
||||
employee.save()
|
||||
|
||||
obj = self.Person.objects(id=employee.id).only('age').get()
|
||||
self.assertTrue(isinstance(obj, Employee))
|
||||
self.assertIsInstance(obj, Employee)
|
||||
|
||||
# Check field names are looked up properly
|
||||
obj = Employee.objects(id=employee.id).only('salary').get()
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
|
||||
from mongoengine import *
|
||||
|
||||
from tests.utils import MongoDBTestCase, needs_mongodb_v3
|
||||
from tests.utils import MongoDBTestCase, requires_mongodb_gte_3
|
||||
|
||||
|
||||
__all__ = ("GeoQueriesTest",)
|
||||
@@ -72,7 +72,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# $minDistance was added in MongoDB v2.6, but continued being buggy
|
||||
# until v3.0; skip for older versions
|
||||
@needs_mongodb_v3
|
||||
@requires_mongodb_gte_3
|
||||
def test_near_and_min_distance(self):
|
||||
"""Ensure the "min_distance" operator works alongside the "near"
|
||||
operator.
|
||||
@@ -95,9 +95,9 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
location__within_distance=point_and_distance)
|
||||
self.assertEqual(events.count(), 2)
|
||||
events = list(events)
|
||||
self.assertTrue(event2 not in events)
|
||||
self.assertTrue(event1 in events)
|
||||
self.assertTrue(event3 in events)
|
||||
self.assertNotIn(event2, events)
|
||||
self.assertIn(event1, events)
|
||||
self.assertIn(event3, events)
|
||||
|
||||
# find events within 10 degrees of san francisco
|
||||
point_and_distance = [[-122.415579, 37.7566023], 10]
|
||||
@@ -245,7 +245,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
|
||||
# $minDistance was added in MongoDB v2.6, but continued being buggy
|
||||
# until v3.0; skip for older versions
|
||||
@needs_mongodb_v3
|
||||
@requires_mongodb_gte_3
|
||||
def test_2dsphere_near_and_min_max_distance(self):
|
||||
"""Ensure "min_distace" and "max_distance" operators work well
|
||||
together with the "near" operator in a 2dsphere index.
|
||||
@@ -285,9 +285,9 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
location__geo_within_center=point_and_distance)
|
||||
self.assertEqual(events.count(), 2)
|
||||
events = list(events)
|
||||
self.assertTrue(event2 not in events)
|
||||
self.assertTrue(event1 in events)
|
||||
self.assertTrue(event3 in events)
|
||||
self.assertNotIn(event2, events)
|
||||
self.assertIn(event1, events)
|
||||
self.assertIn(event3, events)
|
||||
|
||||
def _test_embedded(self, point_field_class):
|
||||
"""Helper test method ensuring given point field class works
|
||||
@@ -329,7 +329,7 @@ class GeoQueriesTest(MongoDBTestCase):
|
||||
self._test_embedded(point_field_class=PointField)
|
||||
|
||||
# Needs MongoDB > 2.6.4 https://jira.mongodb.org/browse/SERVER-14039
|
||||
@needs_mongodb_v3
|
||||
@requires_mongodb_gte_3
|
||||
def test_spherical_geospatial_operators(self):
|
||||
"""Ensure that spherical geospatial queries are working."""
|
||||
class Point(Document):
|
||||
|
||||
@@ -2,7 +2,7 @@ import unittest
|
||||
|
||||
from mongoengine import connect, Document, IntField, StringField, ListField
|
||||
|
||||
from tests.utils import needs_mongodb_v26
|
||||
from tests.utils import requires_mongodb_gte_26
|
||||
|
||||
__all__ = ("FindAndModifyTest",)
|
||||
|
||||
@@ -96,7 +96,7 @@ class FindAndModifyTest(unittest.TestCase):
|
||||
self.assertEqual(old_doc.to_mongo(), {"_id": 1})
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
|
||||
|
||||
@needs_mongodb_v26
|
||||
@requires_mongodb_gte_26
|
||||
def test_modify_with_push(self):
|
||||
class BlogPost(Document):
|
||||
tags = ListField(StringField())
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,15 +48,15 @@ class TransformTest(unittest.TestCase):
|
||||
|
||||
for k, v in (("set", "$set"), ("set_on_insert", "$setOnInsert"), ("push", "$push")):
|
||||
update = transform.update(DicDoc, **{"%s__dictField__test" % k: doc})
|
||||
self.assertTrue(isinstance(update[v]["dictField.test"], dict))
|
||||
self.assertIsInstance(update[v]["dictField.test"], dict)
|
||||
|
||||
# Update special cases
|
||||
update = transform.update(DicDoc, unset__dictField__test=doc)
|
||||
self.assertEqual(update["$unset"]["dictField.test"], 1)
|
||||
|
||||
update = transform.update(DicDoc, pull__dictField__test=doc)
|
||||
self.assertTrue(isinstance(update["$pull"]["dictField"]["test"], dict))
|
||||
|
||||
self.assertIsInstance(update["$pull"]["dictField"]["test"], dict)
|
||||
|
||||
update = transform.update(LisDoc, pull__foo__in=['a'])
|
||||
self.assertEqual(update, {'$pull': {'foo': {'$in': ['a']}}})
|
||||
|
||||
@@ -88,17 +88,15 @@ class TransformTest(unittest.TestCase):
|
||||
post = BlogPost(**data)
|
||||
post.save()
|
||||
|
||||
self.assertTrue('postTitle' in
|
||||
BlogPost.objects(title=data['title'])._query)
|
||||
self.assertIn('postTitle', BlogPost.objects(title=data['title'])._query)
|
||||
self.assertFalse('title' in
|
||||
BlogPost.objects(title=data['title'])._query)
|
||||
self.assertEqual(BlogPost.objects(title=data['title']).count(), 1)
|
||||
|
||||
self.assertTrue('_id' in BlogPost.objects(pk=post.id)._query)
|
||||
self.assertIn('_id', BlogPost.objects(pk=post.id)._query)
|
||||
self.assertEqual(BlogPost.objects(pk=post.id).count(), 1)
|
||||
|
||||
self.assertTrue('postComments.commentContent' in
|
||||
BlogPost.objects(comments__content='test')._query)
|
||||
self.assertIn('postComments.commentContent', BlogPost.objects(comments__content='test')._query)
|
||||
self.assertEqual(BlogPost.objects(comments__content='test').count(), 1)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
@@ -116,8 +114,8 @@ class TransformTest(unittest.TestCase):
|
||||
post = BlogPost(**data)
|
||||
post.save()
|
||||
|
||||
self.assertTrue('_id' in BlogPost.objects(pk=data['title'])._query)
|
||||
self.assertTrue('_id' in BlogPost.objects(title=data['title'])._query)
|
||||
self.assertIn('_id', BlogPost.objects(pk=data['title'])._query)
|
||||
self.assertIn('_id', BlogPost.objects(title=data['title'])._query)
|
||||
self.assertEqual(BlogPost.objects(pk=data['title']).count(), 1)
|
||||
|
||||
BlogPost.drop_collection()
|
||||
@@ -260,31 +258,31 @@ class TransformTest(unittest.TestCase):
|
||||
events = Event.objects(location__within=box)
|
||||
with self.assertRaises(InvalidQueryError):
|
||||
events.count()
|
||||
|
||||
|
||||
def test_update_pull_for_list_fields(self):
|
||||
"""
|
||||
Test added to check pull operation in update for
|
||||
"""
|
||||
Test added to check pull operation in update for
|
||||
EmbeddedDocumentListField which is inside a EmbeddedDocumentField
|
||||
"""
|
||||
class Word(EmbeddedDocument):
|
||||
word = StringField()
|
||||
index = IntField()
|
||||
|
||||
|
||||
class SubDoc(EmbeddedDocument):
|
||||
heading = ListField(StringField())
|
||||
text = EmbeddedDocumentListField(Word)
|
||||
|
||||
|
||||
class MainDoc(Document):
|
||||
title = StringField()
|
||||
content = EmbeddedDocumentField(SubDoc)
|
||||
|
||||
|
||||
word = Word(word='abc', index=1)
|
||||
update = transform.update(MainDoc, pull__content__text=word)
|
||||
self.assertEqual(update, {'$pull': {'content.text': SON([('word', u'abc'), ('index', 1)])}})
|
||||
|
||||
update = transform.update(MainDoc, pull__content__heading='xyz')
|
||||
self.assertEqual(update, {'$pull': {'content.heading': 'xyz'}})
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -196,7 +196,7 @@ class QTest(unittest.TestCase):
|
||||
|
||||
test2 = test.clone()
|
||||
self.assertEqual(test2.count(), 3)
|
||||
self.assertFalse(test2 == test)
|
||||
self.assertNotEqual(test2, test)
|
||||
|
||||
test3 = test2.filter(x=6)
|
||||
self.assertEqual(test3.count(), 1)
|
||||
@@ -296,6 +296,18 @@ class QTest(unittest.TestCase):
|
||||
obj = self.Person.objects(Q(name__not=re.compile('^Gui'))).first()
|
||||
self.assertEqual(obj, None)
|
||||
|
||||
def test_q_repr(self):
|
||||
self.assertEqual(repr(Q()), 'Q(**{})')
|
||||
self.assertEqual(repr(Q(name='test')), "Q(**{'name': 'test'})")
|
||||
|
||||
self.assertEqual(
|
||||
repr(Q(name='test') & Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))")
|
||||
|
||||
self.assertEqual(
|
||||
repr(Q(name='test') | Q(age__gte=18)),
|
||||
"(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))")
|
||||
|
||||
def test_q_lists(self):
|
||||
"""Ensure that Q objects query ListFields correctly.
|
||||
"""
|
||||
|
||||
@@ -39,15 +39,15 @@ class ConnectionTest(unittest.TestCase):
|
||||
connect('mongoenginetest')
|
||||
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'mongoenginetest')
|
||||
|
||||
connect('mongoenginetest2', alias='testdb')
|
||||
conn = get_connection('testdb')
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
def test_connect_in_mocking(self):
|
||||
"""Ensure that the connect() method works properly in mocking.
|
||||
@@ -59,31 +59,31 @@ class ConnectionTest(unittest.TestCase):
|
||||
|
||||
connect('mongoenginetest', host='mongomock://localhost')
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect('mongoenginetest2', host='mongomock://localhost', alias='testdb2')
|
||||
conn = get_connection('testdb2')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect('mongoenginetest3', host='mongodb://localhost', is_mock=True, alias='testdb3')
|
||||
conn = get_connection('testdb3')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect('mongoenginetest4', is_mock=True, alias='testdb4')
|
||||
conn = get_connection('testdb4')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host='mongodb://localhost:27017/mongoenginetest5', is_mock=True, alias='testdb5')
|
||||
conn = get_connection('testdb5')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host='mongomock://localhost:27017/mongoenginetest6', alias='testdb6')
|
||||
conn = get_connection('testdb6')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host='mongomock://localhost:27017/mongoenginetest7', is_mock=True, alias='testdb7')
|
||||
conn = get_connection('testdb7')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
def test_connect_with_host_list(self):
|
||||
"""Ensure that the connect() method works when host is a list
|
||||
@@ -97,27 +97,27 @@ class ConnectionTest(unittest.TestCase):
|
||||
|
||||
connect(host=['mongomock://localhost'])
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host=['mongodb://localhost'], is_mock=True, alias='testdb2')
|
||||
conn = get_connection('testdb2')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host=['localhost'], is_mock=True, alias='testdb3')
|
||||
conn = get_connection('testdb3')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host=['mongomock://localhost:27017', 'mongomock://localhost:27018'], alias='testdb4')
|
||||
conn = get_connection('testdb4')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host=['mongodb://localhost:27017', 'mongodb://localhost:27018'], is_mock=True, alias='testdb5')
|
||||
conn = get_connection('testdb5')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
connect(host=['localhost:27017', 'localhost:27018'], is_mock=True, alias='testdb6')
|
||||
conn = get_connection('testdb6')
|
||||
self.assertTrue(isinstance(conn, mongomock.MongoClient))
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
def test_disconnect(self):
|
||||
"""Ensure that the disconnect() method works properly
|
||||
@@ -163,10 +163,10 @@ class ConnectionTest(unittest.TestCase):
|
||||
connect("testdb_uri", host='mongodb://username:password@localhost/mongoenginetest')
|
||||
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'mongoenginetest')
|
||||
|
||||
c.admin.system.users.remove({})
|
||||
@@ -179,10 +179,10 @@ class ConnectionTest(unittest.TestCase):
|
||||
connect("mongoenginetest", host='mongodb://localhost/')
|
||||
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'mongoenginetest')
|
||||
|
||||
def test_connect_uri_default_db(self):
|
||||
@@ -192,10 +192,10 @@ class ConnectionTest(unittest.TestCase):
|
||||
connect(host='mongodb://localhost/')
|
||||
|
||||
conn = get_connection()
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'test')
|
||||
|
||||
def test_uri_without_credentials_doesnt_override_conn_settings(self):
|
||||
@@ -242,7 +242,7 @@ class ConnectionTest(unittest.TestCase):
|
||||
'mongoenginetest?authSource=admin')
|
||||
)
|
||||
db = get_db('test2')
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'mongoenginetest')
|
||||
|
||||
# Clear all users
|
||||
@@ -255,10 +255,10 @@ class ConnectionTest(unittest.TestCase):
|
||||
|
||||
self.assertRaises(MongoEngineConnectionError, get_connection)
|
||||
conn = get_connection('testdb')
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
db = get_db('testdb')
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'mongoenginetest2')
|
||||
|
||||
def test_register_connection_defaults(self):
|
||||
@@ -267,7 +267,7 @@ class ConnectionTest(unittest.TestCase):
|
||||
register_connection('testdb', 'mongoenginetest', host=None, port=None)
|
||||
|
||||
conn = get_connection('testdb')
|
||||
self.assertTrue(isinstance(conn, pymongo.mongo_client.MongoClient))
|
||||
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient)
|
||||
|
||||
def test_connection_kwargs(self):
|
||||
"""Ensure that connection kwargs get passed to pymongo."""
|
||||
@@ -326,7 +326,7 @@ class ConnectionTest(unittest.TestCase):
|
||||
if IS_PYMONGO_3:
|
||||
c = connect(host='mongodb://localhost/test?replicaSet=local-rs')
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'test')
|
||||
else:
|
||||
# PyMongo < v3.x raises an exception:
|
||||
@@ -343,7 +343,7 @@ class ConnectionTest(unittest.TestCase):
|
||||
self.assertEqual(c._MongoClient__options.replica_set_name,
|
||||
'local-rs')
|
||||
db = get_db()
|
||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||
self.assertIsInstance(db, pymongo.database.Database)
|
||||
self.assertEqual(db.name, 'test')
|
||||
else:
|
||||
# PyMongo < v3.x raises an exception:
|
||||
@@ -364,6 +364,12 @@ class ConnectionTest(unittest.TestCase):
|
||||
date_doc = DateDoc.objects.first()
|
||||
self.assertEqual(d, date_doc.the_date)
|
||||
|
||||
def test_read_preference_from_parse(self):
|
||||
if IS_PYMONGO_3:
|
||||
from pymongo import ReadPreference
|
||||
conn = connect(host="mongodb://a1.vpc,a2.vpc,a3.vpc/prod?readPreference=secondaryPreferred")
|
||||
self.assertEqual(conn.read_preference, ReadPreference.SECONDARY_PREFERRED)
|
||||
|
||||
def test_multiple_connection_settings(self):
|
||||
connect('mongoenginetest', alias='t1', host="localhost")
|
||||
|
||||
@@ -371,8 +377,8 @@ class ConnectionTest(unittest.TestCase):
|
||||
|
||||
mongo_connections = mongoengine.connection._connections
|
||||
self.assertEqual(len(mongo_connections.items()), 2)
|
||||
self.assertTrue('t1' in mongo_connections.keys())
|
||||
self.assertTrue('t2' in mongo_connections.keys())
|
||||
self.assertIn('t1', mongo_connections.keys())
|
||||
self.assertIn('t2', mongo_connections.keys())
|
||||
if not IS_PYMONGO_3:
|
||||
self.assertEqual(mongo_connections['t1'].host, 'localhost')
|
||||
self.assertEqual(mongo_connections['t2'].host, '127.0.0.1')
|
||||
|
||||
@@ -89,15 +89,15 @@ class ContextManagersTest(unittest.TestCase):
|
||||
|
||||
with no_dereference(Group) as Group:
|
||||
group = Group.objects.first()
|
||||
self.assertTrue(all([not isinstance(m, User)
|
||||
for m in group.members]))
|
||||
self.assertFalse(isinstance(group.ref, User))
|
||||
self.assertFalse(isinstance(group.generic, User))
|
||||
for m in group.members:
|
||||
self.assertNotIsInstance(m, User)
|
||||
self.assertNotIsInstance(group.ref, User)
|
||||
self.assertNotIsInstance(group.generic, User)
|
||||
|
||||
self.assertTrue(all([isinstance(m, User)
|
||||
for m in group.members]))
|
||||
self.assertTrue(isinstance(group.ref, User))
|
||||
self.assertTrue(isinstance(group.generic, User))
|
||||
for m in group.members:
|
||||
self.assertIsInstance(m, User)
|
||||
self.assertIsInstance(group.ref, User)
|
||||
self.assertIsInstance(group.generic, User)
|
||||
|
||||
def test_no_dereference_context_manager_dbref(self):
|
||||
"""Ensure that DBRef items in ListFields aren't dereferenced.
|
||||
@@ -129,19 +129,17 @@ class ContextManagersTest(unittest.TestCase):
|
||||
group = Group.objects.first()
|
||||
self.assertTrue(all([not isinstance(m, User)
|
||||
for m in group.members]))
|
||||
self.assertFalse(isinstance(group.ref, User))
|
||||
self.assertFalse(isinstance(group.generic, User))
|
||||
self.assertNotIsInstance(group.ref, User)
|
||||
self.assertNotIsInstance(group.generic, User)
|
||||
|
||||
self.assertTrue(all([isinstance(m, User)
|
||||
for m in group.members]))
|
||||
self.assertTrue(isinstance(group.ref, User))
|
||||
self.assertTrue(isinstance(group.generic, User))
|
||||
self.assertIsInstance(group.ref, User)
|
||||
self.assertIsInstance(group.generic, User)
|
||||
|
||||
def test_no_sub_classes(self):
|
||||
class A(Document):
|
||||
x = IntField()
|
||||
y = IntField()
|
||||
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
class B(A):
|
||||
@@ -152,29 +150,29 @@ class ContextManagersTest(unittest.TestCase):
|
||||
|
||||
A.drop_collection()
|
||||
|
||||
A(x=10, y=20).save()
|
||||
A(x=15, y=30).save()
|
||||
B(x=20, y=40).save()
|
||||
B(x=30, y=50).save()
|
||||
C(x=40, y=60).save()
|
||||
A(x=10).save()
|
||||
A(x=15).save()
|
||||
B(x=20).save()
|
||||
B(x=30).save()
|
||||
C(x=40).save()
|
||||
|
||||
self.assertEqual(A.objects.count(), 5)
|
||||
self.assertEqual(B.objects.count(), 3)
|
||||
self.assertEqual(C.objects.count(), 1)
|
||||
|
||||
with no_sub_classes(A) as A:
|
||||
with no_sub_classes(A):
|
||||
self.assertEqual(A.objects.count(), 2)
|
||||
|
||||
for obj in A.objects:
|
||||
self.assertEqual(obj.__class__, A)
|
||||
|
||||
with no_sub_classes(B) as B:
|
||||
with no_sub_classes(B):
|
||||
self.assertEqual(B.objects.count(), 2)
|
||||
|
||||
for obj in B.objects:
|
||||
self.assertEqual(obj.__class__, B)
|
||||
|
||||
with no_sub_classes(C) as C:
|
||||
with no_sub_classes(C):
|
||||
self.assertEqual(C.objects.count(), 1)
|
||||
|
||||
for obj in C.objects:
|
||||
@@ -185,18 +183,124 @@ class ContextManagersTest(unittest.TestCase):
|
||||
self.assertEqual(B.objects.count(), 3)
|
||||
self.assertEqual(C.objects.count(), 1)
|
||||
|
||||
def test_no_sub_classes_modification_to_document_class_are_temporary(self):
|
||||
class A(Document):
|
||||
x = IntField()
|
||||
meta = {'allow_inheritance': True}
|
||||
|
||||
class B(A):
|
||||
z = IntField()
|
||||
|
||||
self.assertEqual(A._subclasses, ('A', 'A.B'))
|
||||
with no_sub_classes(A):
|
||||
self.assertEqual(A._subclasses, ('A',))
|
||||
self.assertEqual(A._subclasses, ('A', 'A.B'))
|
||||
|
||||
self.assertEqual(B._subclasses, ('A.B',))
|
||||
with no_sub_classes(B):
|
||||
self.assertEqual(B._subclasses, ('A.B',))
|
||||
self.assertEqual(B._subclasses, ('A.B',))
|
||||
|
||||
def test_no_subclass_context_manager_does_not_swallow_exception(self):
|
||||
class User(Document):
|
||||
name = StringField()
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
with no_sub_classes(User):
|
||||
raise TypeError()
|
||||
|
||||
def test_query_counter_does_not_swallow_exception(self):
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
with query_counter() as q:
|
||||
raise TypeError()
|
||||
|
||||
def test_query_counter_temporarily_modifies_profiling_level(self):
|
||||
connect('mongoenginetest')
|
||||
db = get_db()
|
||||
|
||||
initial_profiling_level = db.profiling_level()
|
||||
|
||||
try:
|
||||
NEW_LEVEL = 1
|
||||
db.set_profiling_level(NEW_LEVEL)
|
||||
self.assertEqual(db.profiling_level(), NEW_LEVEL)
|
||||
with query_counter() as q:
|
||||
self.assertEqual(db.profiling_level(), 2)
|
||||
self.assertEqual(db.profiling_level(), NEW_LEVEL)
|
||||
except Exception:
|
||||
db.set_profiling_level(initial_profiling_level) # Ensures it gets reseted no matter the outcome of the test
|
||||
raise
|
||||
|
||||
def test_query_counter(self):
|
||||
connect('mongoenginetest')
|
||||
db = get_db()
|
||||
db.test.find({})
|
||||
|
||||
collection = db.query_counter
|
||||
collection.drop()
|
||||
|
||||
def issue_1_count_query():
|
||||
collection.find({}).count()
|
||||
|
||||
def issue_1_insert_query():
|
||||
collection.insert_one({'test': 'garbage'})
|
||||
|
||||
def issue_1_find_query():
|
||||
collection.find_one()
|
||||
|
||||
counter = 0
|
||||
with query_counter() as q:
|
||||
self.assertEqual(q, counter)
|
||||
self.assertEqual(q, counter) # Ensures previous count query did not get counted
|
||||
|
||||
for _ in range(10):
|
||||
issue_1_insert_query()
|
||||
counter += 1
|
||||
self.assertEqual(q, counter)
|
||||
|
||||
for _ in range(4):
|
||||
issue_1_find_query()
|
||||
counter += 1
|
||||
self.assertEqual(q, counter)
|
||||
|
||||
for _ in range(3):
|
||||
issue_1_count_query()
|
||||
counter += 1
|
||||
self.assertEqual(q, counter)
|
||||
|
||||
def test_query_counter_counts_getmore_queries(self):
|
||||
connect('mongoenginetest')
|
||||
db = get_db()
|
||||
|
||||
collection = db.query_counter
|
||||
collection.drop()
|
||||
|
||||
many_docs = [{'test': 'garbage %s' % i} for i in range(150)]
|
||||
collection.insert_many(many_docs) # first batch of documents contains 101 documents
|
||||
|
||||
with query_counter() as q:
|
||||
self.assertEqual(0, q)
|
||||
self.assertEqual(q, 0)
|
||||
list(collection.find())
|
||||
self.assertEqual(q, 2) # 1st select + 1 getmore
|
||||
|
||||
for i in range(1, 51):
|
||||
db.test.find({}).count()
|
||||
def test_query_counter_ignores_particular_queries(self):
|
||||
connect('mongoenginetest')
|
||||
db = get_db()
|
||||
|
||||
self.assertEqual(50, q)
|
||||
collection = db.query_counter
|
||||
collection.insert_many([{'test': 'garbage %s' % i} for i in range(10)])
|
||||
|
||||
with query_counter() as q:
|
||||
self.assertEqual(q, 0)
|
||||
cursor = collection.find()
|
||||
self.assertEqual(q, 0) # cursor wasn't opened yet
|
||||
_ = next(cursor) # opens the cursor and fires the find query
|
||||
self.assertEqual(q, 1)
|
||||
|
||||
cursor.close() # issues a `killcursors` query that is ignored by the context
|
||||
self.assertEqual(q, 1)
|
||||
_ = db.system.indexes.find_one() # queries on db.system.indexes are ignored as well
|
||||
self.assertEqual(q, 1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -200,8 +200,8 @@ class FieldTest(unittest.TestCase):
|
||||
group = Group(author=user, members=[user]).save()
|
||||
|
||||
raw_data = Group._get_collection().find_one()
|
||||
self.assertTrue(isinstance(raw_data['author'], DBRef))
|
||||
self.assertTrue(isinstance(raw_data['members'][0], DBRef))
|
||||
self.assertIsInstance(raw_data['author'], DBRef)
|
||||
self.assertIsInstance(raw_data['members'][0], DBRef)
|
||||
group = Group.objects.first()
|
||||
|
||||
self.assertEqual(group.author, user)
|
||||
@@ -224,8 +224,8 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(group.members, [user])
|
||||
|
||||
raw_data = Group._get_collection().find_one()
|
||||
self.assertTrue(isinstance(raw_data['author'], ObjectId))
|
||||
self.assertTrue(isinstance(raw_data['members'][0], ObjectId))
|
||||
self.assertIsInstance(raw_data['author'], ObjectId)
|
||||
self.assertIsInstance(raw_data['members'][0], ObjectId)
|
||||
|
||||
def test_recursive_reference(self):
|
||||
"""Ensure that ReferenceFields can reference their own documents.
|
||||
@@ -469,7 +469,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -485,7 +485,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -502,7 +502,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
UserA.drop_collection()
|
||||
UserB.drop_collection()
|
||||
@@ -560,7 +560,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -576,7 +576,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -593,7 +593,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for m in group_obj.members:
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
UserA.drop_collection()
|
||||
UserB.drop_collection()
|
||||
@@ -633,7 +633,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, User))
|
||||
self.assertIsInstance(m, User)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -646,7 +646,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, User))
|
||||
self.assertIsInstance(m, User)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -660,7 +660,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, User))
|
||||
self.assertIsInstance(m, User)
|
||||
|
||||
User.drop_collection()
|
||||
Group.drop_collection()
|
||||
@@ -715,7 +715,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -731,7 +731,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -748,7 +748,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
Group.objects.delete()
|
||||
Group().save()
|
||||
@@ -806,7 +806,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, UserA))
|
||||
self.assertIsInstance(m, UserA)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -822,7 +822,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, UserA))
|
||||
self.assertIsInstance(m, UserA)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -839,7 +839,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 2)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue(isinstance(m, UserA))
|
||||
self.assertIsInstance(m, UserA)
|
||||
|
||||
UserA.drop_collection()
|
||||
Group.drop_collection()
|
||||
@@ -894,7 +894,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Document select_related
|
||||
with query_counter() as q:
|
||||
@@ -910,7 +910,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
# Queryset select_related
|
||||
with query_counter() as q:
|
||||
@@ -927,7 +927,7 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(q, 4)
|
||||
|
||||
for k, m in group_obj.members.iteritems():
|
||||
self.assertTrue('User' in m.__class__.__name__)
|
||||
self.assertIn('User', m.__class__.__name__)
|
||||
|
||||
Group.objects.delete()
|
||||
Group().save()
|
||||
@@ -1029,7 +1029,6 @@ class FieldTest(unittest.TestCase):
|
||||
self.assertEqual(type(foo.bar), Bar)
|
||||
self.assertEqual(type(foo.baz), Baz)
|
||||
|
||||
|
||||
def test_document_reload_reference_integrity(self):
|
||||
"""
|
||||
Ensure reloading a document with multiple similar id
|
||||
@@ -1209,10 +1208,10 @@ class FieldTest(unittest.TestCase):
|
||||
|
||||
# Can't use query_counter across databases - so test the _data object
|
||||
book = Book.objects.first()
|
||||
self.assertFalse(isinstance(book._data['author'], User))
|
||||
self.assertNotIsInstance(book._data['author'], User)
|
||||
|
||||
book.select_related()
|
||||
self.assertTrue(isinstance(book._data['author'], User))
|
||||
self.assertIsInstance(book._data['author'], User)
|
||||
|
||||
def test_non_ascii_pk(self):
|
||||
"""
|
||||
|
||||
38
tests/test_utils.py
Normal file
38
tests/test_utils.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import unittest
|
||||
import re
|
||||
|
||||
from mongoengine.base.utils import LazyRegexCompiler
|
||||
|
||||
signal_output = []
|
||||
|
||||
|
||||
class LazyRegexCompilerTest(unittest.TestCase):
|
||||
|
||||
def test_lazy_regex_compiler_verify_laziness_of_descriptor(self):
|
||||
class UserEmail(object):
|
||||
EMAIL_REGEX = LazyRegexCompiler('@', flags=32)
|
||||
|
||||
descriptor = UserEmail.__dict__['EMAIL_REGEX']
|
||||
self.assertIsNone(descriptor._compiled_regex)
|
||||
|
||||
regex = UserEmail.EMAIL_REGEX
|
||||
self.assertEqual(regex, re.compile('@', flags=32))
|
||||
self.assertEqual(regex.search('user@domain.com').group(), '@')
|
||||
|
||||
user_email = UserEmail()
|
||||
self.assertIs(user_email.EMAIL_REGEX, UserEmail.EMAIL_REGEX)
|
||||
|
||||
def test_lazy_regex_compiler_verify_cannot_set_descriptor_on_instance(self):
|
||||
class UserEmail(object):
|
||||
EMAIL_REGEX = LazyRegexCompiler('@')
|
||||
|
||||
user_email = UserEmail()
|
||||
with self.assertRaises(AttributeError):
|
||||
user_email.EMAIL_REGEX = re.compile('@')
|
||||
|
||||
def test_lazy_regex_compiler_verify_can_override_class_attr(self):
|
||||
class UserEmail(object):
|
||||
EMAIL_REGEX = LazyRegexCompiler('@')
|
||||
|
||||
UserEmail.EMAIL_REGEX = re.compile('cookies')
|
||||
self.assertEqual(UserEmail.EMAIL_REGEX.search('Cake & cookies').group(), 'cookies')
|
||||
@@ -7,12 +7,19 @@ from mongoengine.connection import get_db, get_connection
|
||||
from mongoengine.python_support import IS_PYMONGO_3
|
||||
|
||||
|
||||
MONGO_TEST_DB = 'mongoenginetest'
|
||||
MONGO_TEST_DB = 'mongoenginetest' # standard name for the test database
|
||||
|
||||
|
||||
# Constant that can be used to compare the version retrieved with
|
||||
# get_mongodb_version()
|
||||
MONGODB_26 = (2, 6)
|
||||
MONGODB_3 = (3,0)
|
||||
MONGODB_32 = (3, 2)
|
||||
|
||||
|
||||
class MongoDBTestCase(unittest.TestCase):
|
||||
"""Base class for tests that need a mongodb connection
|
||||
db is being dropped automatically
|
||||
It ensures that the db is clean at the beginning and dropped at the end automatically
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
@@ -27,40 +34,46 @@ class MongoDBTestCase(unittest.TestCase):
|
||||
|
||||
|
||||
def get_mongodb_version():
|
||||
"""Return the version tuple of the MongoDB server that the default
|
||||
connection is connected to.
|
||||
"""
|
||||
return tuple(get_connection().server_info()['versionArray'])
|
||||
"""Return the version of the connected mongoDB (first 2 digits)
|
||||
|
||||
def _decorated_with_ver_requirement(func, ver_tuple):
|
||||
:return: tuple(int, int)
|
||||
"""
|
||||
version_list = get_connection().server_info()['versionArray'][:2] # e.g: (3, 2)
|
||||
return tuple(version_list)
|
||||
|
||||
|
||||
def _decorated_with_ver_requirement(func, version):
|
||||
"""Return a given function decorated with the version requirement
|
||||
for a particular MongoDB version tuple.
|
||||
|
||||
:param version: The version required (tuple(int, int))
|
||||
"""
|
||||
def _inner(*args, **kwargs):
|
||||
mongodb_ver = get_mongodb_version()
|
||||
if mongodb_ver >= ver_tuple:
|
||||
MONGODB_V = get_mongodb_version()
|
||||
if MONGODB_V >= version:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
raise SkipTest('Needs MongoDB v{}+'.format(
|
||||
'.'.join([str(v) for v in ver_tuple])
|
||||
))
|
||||
raise SkipTest('Needs MongoDB v{}+'.format('.'.join(str(n) for n in version)))
|
||||
|
||||
_inner.__name__ = func.__name__
|
||||
_inner.__doc__ = func.__doc__
|
||||
|
||||
return _inner
|
||||
|
||||
def needs_mongodb_v26(func):
|
||||
|
||||
def requires_mongodb_gte_26(func):
|
||||
"""Raise a SkipTest exception if we're working with MongoDB version
|
||||
lower than v2.6.
|
||||
"""
|
||||
return _decorated_with_ver_requirement(func, (2, 6))
|
||||
return _decorated_with_ver_requirement(func, MONGODB_26)
|
||||
|
||||
def needs_mongodb_v3(func):
|
||||
|
||||
def requires_mongodb_gte_3(func):
|
||||
"""Raise a SkipTest exception if we're working with MongoDB version
|
||||
lower than v3.0.
|
||||
"""
|
||||
return _decorated_with_ver_requirement(func, (3, 0))
|
||||
return _decorated_with_ver_requirement(func, MONGODB_3)
|
||||
|
||||
|
||||
def skip_pymongo3(f):
|
||||
"""Raise a SkipTest exception if we're running a test against
|
||||
|
||||
Reference in New Issue
Block a user