Merge branch 'master' into pr/674
This commit is contained in:
@@ -15,7 +15,7 @@ from tests.fixtures import (PickleEmbedded, PickleTest, PickleSignalsTest,
|
||||
|
||||
from mongoengine import *
|
||||
from mongoengine.errors import (NotRegistered, InvalidDocumentError,
|
||||
InvalidQueryError)
|
||||
InvalidQueryError, NotUniqueError)
|
||||
from mongoengine.queryset import NULLIFY, Q
|
||||
from mongoengine.connection import get_db
|
||||
from mongoengine.base import get_document
|
||||
@@ -57,7 +57,7 @@ class InstanceTest(unittest.TestCase):
|
||||
date = DateTimeField(default=datetime.now)
|
||||
meta = {
|
||||
'max_documents': 10,
|
||||
'max_size': 90000,
|
||||
'max_size': 4096,
|
||||
}
|
||||
|
||||
Log.drop_collection()
|
||||
@@ -75,7 +75,7 @@ class InstanceTest(unittest.TestCase):
|
||||
options = Log.objects._collection.options()
|
||||
self.assertEqual(options['capped'], True)
|
||||
self.assertEqual(options['max'], 10)
|
||||
self.assertEqual(options['size'], 90000)
|
||||
self.assertTrue(options['size'] >= 4096)
|
||||
|
||||
# Check that the document cannot be redefined with different options
|
||||
def recreate_log_document():
|
||||
@@ -990,6 +990,16 @@ class InstanceTest(unittest.TestCase):
|
||||
|
||||
self.assertRaises(InvalidQueryError, update_no_op_raises)
|
||||
|
||||
def test_update_unique_field(self):
|
||||
class Doc(Document):
|
||||
name = StringField(unique=True)
|
||||
|
||||
doc1 = Doc(name="first").save()
|
||||
doc2 = Doc(name="second").save()
|
||||
|
||||
self.assertRaises(NotUniqueError, lambda:
|
||||
doc2.update(set__name=doc1.name))
|
||||
|
||||
def test_embedded_update(self):
|
||||
"""
|
||||
Test update on `EmbeddedDocumentField` fields
|
||||
@@ -2411,7 +2421,7 @@ class InstanceTest(unittest.TestCase):
|
||||
for parameter_name, parameter in self.parameters.iteritems():
|
||||
parameter.expand()
|
||||
|
||||
class System(Document):
|
||||
class NodesSystem(Document):
|
||||
name = StringField(required=True)
|
||||
nodes = MapField(ReferenceField(Node, dbref=False))
|
||||
|
||||
@@ -2419,18 +2429,18 @@ class InstanceTest(unittest.TestCase):
|
||||
for node_name, node in self.nodes.iteritems():
|
||||
node.expand()
|
||||
node.save(*args, **kwargs)
|
||||
super(System, self).save(*args, **kwargs)
|
||||
super(NodesSystem, self).save(*args, **kwargs)
|
||||
|
||||
System.drop_collection()
|
||||
NodesSystem.drop_collection()
|
||||
Node.drop_collection()
|
||||
|
||||
system = System(name="system")
|
||||
system = NodesSystem(name="system")
|
||||
system.nodes["node"] = Node()
|
||||
system.save()
|
||||
system.nodes["node"].parameters["param"] = Parameter()
|
||||
system.save()
|
||||
|
||||
system = System.objects.first()
|
||||
system = NodesSystem.objects.first()
|
||||
self.assertEqual("UNDEFINED", system.nodes["node"].parameters["param"].macros["test"].value)
|
||||
|
||||
def test_embedded_document_equality(self):
|
||||
|
||||
@@ -279,7 +279,7 @@ class FileTest(unittest.TestCase):
|
||||
t.image.put(f)
|
||||
self.fail("Should have raised an invalidation error")
|
||||
except ValidationError, e:
|
||||
self.assertEqual("%s" % e, "Invalid image: cannot identify image file")
|
||||
self.assertEqual("%s" % e, "Invalid image: cannot identify image file %s" % f)
|
||||
|
||||
t = TestImage()
|
||||
t.image.put(open(TEST_IMAGE_PATH, 'rb'))
|
||||
|
||||
@@ -3,3 +3,4 @@ from field_list import *
|
||||
from queryset import *
|
||||
from visitor import *
|
||||
from geo import *
|
||||
from modify import *
|
||||
102
tests/queryset/modify.py
Normal file
102
tests/queryset/modify.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import sys
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
import unittest
|
||||
|
||||
from mongoengine import connect, Document, IntField
|
||||
|
||||
__all__ = ("FindAndModifyTest",)
|
||||
|
||||
|
||||
class Doc(Document):
|
||||
id = IntField(primary_key=True)
|
||||
value = IntField()
|
||||
|
||||
|
||||
class FindAndModifyTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
connect(db="mongoenginetest")
|
||||
Doc.drop_collection()
|
||||
|
||||
def assertDbEqual(self, docs):
|
||||
self.assertEqual(list(Doc._collection.find().sort("id")), docs)
|
||||
|
||||
def test_modify(self):
|
||||
Doc(id=0, value=0).save()
|
||||
doc = Doc(id=1, value=1).save()
|
||||
|
||||
old_doc = Doc.objects(id=1).modify(set__value=-1)
|
||||
self.assertEqual(old_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
|
||||
|
||||
def test_modify_with_new(self):
|
||||
Doc(id=0, value=0).save()
|
||||
doc = Doc(id=1, value=1).save()
|
||||
|
||||
new_doc = Doc.objects(id=1).modify(set__value=-1, new=True)
|
||||
doc.value = -1
|
||||
self.assertEqual(new_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
|
||||
|
||||
def test_modify_not_existing(self):
|
||||
Doc(id=0, value=0).save()
|
||||
self.assertEqual(Doc.objects(id=1).modify(set__value=-1), None)
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}])
|
||||
|
||||
def test_modify_with_upsert(self):
|
||||
Doc(id=0, value=0).save()
|
||||
old_doc = Doc.objects(id=1).modify(set__value=1, upsert=True)
|
||||
self.assertEqual(old_doc, None)
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}])
|
||||
|
||||
def test_modify_with_upsert_existing(self):
|
||||
Doc(id=0, value=0).save()
|
||||
doc = Doc(id=1, value=1).save()
|
||||
|
||||
old_doc = Doc.objects(id=1).modify(set__value=-1, upsert=True)
|
||||
self.assertEqual(old_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
|
||||
|
||||
def test_modify_with_upsert_with_new(self):
|
||||
Doc(id=0, value=0).save()
|
||||
new_doc = Doc.objects(id=1).modify(upsert=True, new=True, set__value=1)
|
||||
self.assertEqual(new_doc.to_mongo(), {"_id": 1, "value": 1})
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}])
|
||||
|
||||
def test_modify_with_remove(self):
|
||||
Doc(id=0, value=0).save()
|
||||
doc = Doc(id=1, value=1).save()
|
||||
|
||||
old_doc = Doc.objects(id=1).modify(remove=True)
|
||||
self.assertEqual(old_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}])
|
||||
|
||||
def test_find_and_modify_with_remove_not_existing(self):
|
||||
Doc(id=0, value=0).save()
|
||||
self.assertEqual(Doc.objects(id=1).modify(remove=True), None)
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}])
|
||||
|
||||
def test_modify_with_order_by(self):
|
||||
Doc(id=0, value=3).save()
|
||||
Doc(id=1, value=2).save()
|
||||
Doc(id=2, value=1).save()
|
||||
doc = Doc(id=3, value=0).save()
|
||||
|
||||
old_doc = Doc.objects().order_by("-id").modify(set__value=-1)
|
||||
self.assertEqual(old_doc.to_json(), doc.to_json())
|
||||
self.assertDbEqual([
|
||||
{"_id": 0, "value": 3}, {"_id": 1, "value": 2},
|
||||
{"_id": 2, "value": 1}, {"_id": 3, "value": -1}])
|
||||
|
||||
def test_modify_with_fields(self):
|
||||
Doc(id=0, value=0).save()
|
||||
Doc(id=1, value=1).save()
|
||||
|
||||
old_doc = Doc.objects(id=1).only("id").modify(set__value=-1)
|
||||
self.assertEqual(old_doc.to_mongo(), {"_id": 1})
|
||||
self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -650,7 +650,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
blogs.append(Blog(title="post %s" % i, posts=[post1, post2]))
|
||||
|
||||
Blog.objects.insert(blogs, load_bulk=False)
|
||||
self.assertEqual(q, 1) # 1 for the insert
|
||||
self.assertEqual(q, 99) # profiling logs each doc now :(
|
||||
|
||||
Blog.drop_collection()
|
||||
Blog.ensure_indexes()
|
||||
@@ -659,7 +659,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.assertEqual(q, 0)
|
||||
|
||||
Blog.objects.insert(blogs)
|
||||
self.assertEqual(q, 2) # 1 for insert, and 1 for in bulk fetch
|
||||
self.assertEqual(q, 100) # 99 or insert, and 1 for in bulk fetch
|
||||
|
||||
Blog.drop_collection()
|
||||
|
||||
@@ -1040,6 +1040,76 @@ class QuerySetTest(unittest.TestCase):
|
||||
expected = [blog_post_1, blog_post_2, blog_post_3]
|
||||
self.assertSequence(qs, expected)
|
||||
|
||||
def test_clear_ordering(self):
|
||||
""" Make sure one can clear the query set ordering by applying a
|
||||
consecutive order_by()
|
||||
"""
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
|
||||
Person.drop_collection()
|
||||
Person(name="A").save()
|
||||
Person(name="B").save()
|
||||
|
||||
qs = Person.objects.order_by('-name')
|
||||
|
||||
# Make sure we can clear a previously specified ordering
|
||||
with query_counter() as q:
|
||||
lst = list(qs.order_by())
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertTrue('$orderby' not in op['query'])
|
||||
self.assertEqual(lst[0].name, 'A')
|
||||
|
||||
# Make sure previously specified ordering is preserved during
|
||||
# consecutive calls to the same query set
|
||||
with query_counter() as q:
|
||||
lst = list(qs)
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertTrue('$orderby' in op['query'])
|
||||
self.assertEqual(lst[0].name, 'B')
|
||||
|
||||
def test_clear_default_ordering(self):
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
meta = {
|
||||
'ordering': ['-name']
|
||||
}
|
||||
|
||||
Person.drop_collection()
|
||||
Person(name="A").save()
|
||||
Person(name="B").save()
|
||||
|
||||
qs = Person.objects
|
||||
|
||||
# Make sure clearing default ordering works
|
||||
with query_counter() as q:
|
||||
lst = list(qs.order_by())
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertTrue('$orderby' not in op['query'])
|
||||
self.assertEqual(lst[0].name, 'A')
|
||||
|
||||
# Make sure default ordering is preserved during consecutive calls
|
||||
# to the same query set
|
||||
with query_counter() as q:
|
||||
lst = list(qs)
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertTrue('$orderby' in op['query'])
|
||||
self.assertEqual(lst[0].name, 'B')
|
||||
|
||||
def test_find_embedded(self):
|
||||
"""Ensure that an embedded document is properly returned from a query.
|
||||
"""
|
||||
@@ -3586,7 +3656,13 @@ class QuerySetTest(unittest.TestCase):
|
||||
|
||||
[x for x in people]
|
||||
self.assertEqual(100, len(people._result_cache))
|
||||
self.assertEqual(None, people._len)
|
||||
|
||||
import platform
|
||||
|
||||
if platform.python_implementation() != "PyPy":
|
||||
# PyPy evaluates __len__ when iterating with list comprehensions while CPython does not.
|
||||
# This may be a bug in PyPy (PyPy/#1802) but it does not affect the behavior of MongoEngine.
|
||||
self.assertEqual(None, people._len)
|
||||
self.assertEqual(q, 1)
|
||||
|
||||
list(people)
|
||||
@@ -3814,6 +3890,111 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.assertEqual(Example.objects(size=instance_size).count(), 1)
|
||||
self.assertEqual(Example.objects(size__in=[instance_size]).count(), 1)
|
||||
|
||||
def test_cursor_in_an_if_stmt(self):
|
||||
|
||||
class Test(Document):
|
||||
test_field = StringField()
|
||||
|
||||
Test.drop_collection()
|
||||
queryset = Test.objects
|
||||
|
||||
if queryset:
|
||||
raise AssertionError('Empty cursor returns True')
|
||||
|
||||
test = Test()
|
||||
test.test_field = 'test'
|
||||
test.save()
|
||||
|
||||
queryset = Test.objects
|
||||
if not test:
|
||||
raise AssertionError('Cursor has data and returned False')
|
||||
|
||||
queryset.next()
|
||||
if not queryset:
|
||||
raise AssertionError('Cursor has data and it must returns True,'
|
||||
' even in the last item.')
|
||||
|
||||
def test_bool_performance(self):
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
|
||||
Person.drop_collection()
|
||||
for i in xrange(100):
|
||||
Person(name="No: %s" % i).save()
|
||||
|
||||
with query_counter() as q:
|
||||
if Person.objects:
|
||||
pass
|
||||
|
||||
self.assertEqual(q, 1)
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertEqual(op['nreturned'], 1)
|
||||
|
||||
|
||||
def test_bool_with_ordering(self):
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
|
||||
Person.drop_collection()
|
||||
Person(name="Test").save()
|
||||
|
||||
qs = Person.objects.order_by('name')
|
||||
|
||||
with query_counter() as q:
|
||||
|
||||
if qs:
|
||||
pass
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertFalse('$orderby' in op['query'],
|
||||
'BaseQuerySet cannot use orderby in if stmt')
|
||||
|
||||
with query_counter() as p:
|
||||
|
||||
for x in qs:
|
||||
pass
|
||||
|
||||
op = p.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertTrue('$orderby' in op['query'],
|
||||
'BaseQuerySet cannot remove orderby in for loop')
|
||||
|
||||
def test_bool_with_ordering_from_meta_dict(self):
|
||||
|
||||
class Person(Document):
|
||||
name = StringField()
|
||||
meta = {
|
||||
'ordering': ['name']
|
||||
}
|
||||
|
||||
Person.drop_collection()
|
||||
|
||||
Person(name="B").save()
|
||||
Person(name="C").save()
|
||||
Person(name="A").save()
|
||||
|
||||
with query_counter() as q:
|
||||
|
||||
if Person.objects:
|
||||
pass
|
||||
|
||||
op = q.db.system.profile.find({"ns":
|
||||
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
||||
|
||||
self.assertFalse('$orderby' in op['query'],
|
||||
'BaseQuerySet must remove orderby from meta in boolen test')
|
||||
|
||||
self.assertEqual(Person.objects.first().name, 'A')
|
||||
self.assertTrue(Person.objects._has_data(),
|
||||
'Cursor has data and returned False')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user