Merge branch 'master' into pr/636
This commit is contained in:
@@ -735,5 +735,47 @@ class DeltaTest(unittest.TestCase):
|
||||
mydoc._clear_changed_fields()
|
||||
self.assertEqual([], mydoc._get_changed_fields())
|
||||
|
||||
def test_referenced_object_changed_attributes(self):
|
||||
"""Ensures that when you save a new reference to a field, the referenced object isn't altered"""
|
||||
|
||||
class Organization(Document):
|
||||
name = StringField()
|
||||
|
||||
class User(Document):
|
||||
name = StringField()
|
||||
org = ReferenceField('Organization', required=True)
|
||||
|
||||
Organization.drop_collection()
|
||||
User.drop_collection()
|
||||
|
||||
org1 = Organization(name='Org 1')
|
||||
org1.save()
|
||||
|
||||
org2 = Organization(name='Org 2')
|
||||
org2.save()
|
||||
|
||||
user = User(name='Fred', org=org1)
|
||||
user.save()
|
||||
|
||||
org1.reload()
|
||||
org2.reload()
|
||||
user.reload()
|
||||
self.assertEqual(org1.name, 'Org 1')
|
||||
self.assertEqual(org2.name, 'Org 2')
|
||||
self.assertEqual(user.name, 'Fred')
|
||||
|
||||
user.name = 'Harold'
|
||||
user.org = org2
|
||||
|
||||
org2.name = 'New Org 2'
|
||||
self.assertEqual(org2.name, 'New Org 2')
|
||||
|
||||
user.save()
|
||||
org2.save()
|
||||
|
||||
self.assertEqual(org2.name, 'New Org 2')
|
||||
org2.reload()
|
||||
self.assertEqual(org2.name, 'New Org 2')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -292,6 +292,44 @@ class DynamicTest(unittest.TestCase):
|
||||
person.save()
|
||||
self.assertEqual(Person.objects.first().age, 35)
|
||||
|
||||
def test_dynamic_and_embedded_dict_access(self):
|
||||
"""Ensure embedded dynamic documents work with dict[] style access"""
|
||||
|
||||
class Address(EmbeddedDocument):
|
||||
city = StringField()
|
||||
|
||||
class Person(DynamicDocument):
|
||||
name = StringField()
|
||||
|
||||
Person.drop_collection()
|
||||
|
||||
Person(name="Ross", address=Address(city="London")).save()
|
||||
|
||||
person = Person.objects.first()
|
||||
person.attrval = "This works"
|
||||
|
||||
person["phone"] = "555-1212" # but this should too
|
||||
|
||||
# Same thing two levels deep
|
||||
person["address"]["city"] = "Lundenne"
|
||||
person.save()
|
||||
|
||||
self.assertEqual(Person.objects.first().address.city, "Lundenne")
|
||||
|
||||
self.assertEqual(Person.objects.first().phone, "555-1212")
|
||||
|
||||
person = Person.objects.first()
|
||||
person.address = Address(city="Londinium")
|
||||
person.save()
|
||||
|
||||
self.assertEqual(Person.objects.first().address.city, "Londinium")
|
||||
|
||||
|
||||
person = Person.objects.first()
|
||||
person["age"] = 35
|
||||
person.save()
|
||||
self.assertEqual(Person.objects.first().age, 35)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -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():
|
||||
@@ -820,6 +820,80 @@ class InstanceTest(unittest.TestCase):
|
||||
p1.reload()
|
||||
self.assertEqual(p1.name, p.parent.name)
|
||||
|
||||
def test_save_atomicity_condition(self):
|
||||
|
||||
class Widget(Document):
|
||||
toggle = BooleanField(default=False)
|
||||
count = IntField(default=0)
|
||||
save_id = UUIDField()
|
||||
|
||||
def flip(widget):
|
||||
widget.toggle = not widget.toggle
|
||||
widget.count += 1
|
||||
|
||||
def UUID(i):
|
||||
return uuid.UUID(int=i)
|
||||
|
||||
Widget.drop_collection()
|
||||
|
||||
w1 = Widget(toggle=False, save_id=UUID(1))
|
||||
|
||||
# ignore save_condition on new record creation
|
||||
w1.save(save_condition={'save_id':UUID(42)})
|
||||
w1.reload()
|
||||
self.assertFalse(w1.toggle)
|
||||
self.assertEqual(w1.save_id, UUID(1))
|
||||
self.assertEqual(w1.count, 0)
|
||||
|
||||
# mismatch in save_condition prevents save
|
||||
flip(w1)
|
||||
self.assertTrue(w1.toggle)
|
||||
self.assertEqual(w1.count, 1)
|
||||
w1.save(save_condition={'save_id':UUID(42)})
|
||||
w1.reload()
|
||||
self.assertFalse(w1.toggle)
|
||||
self.assertEqual(w1.count, 0)
|
||||
|
||||
# matched save_condition allows save
|
||||
flip(w1)
|
||||
self.assertTrue(w1.toggle)
|
||||
self.assertEqual(w1.count, 1)
|
||||
w1.save(save_condition={'save_id':UUID(1)})
|
||||
w1.reload()
|
||||
self.assertTrue(w1.toggle)
|
||||
self.assertEqual(w1.count, 1)
|
||||
|
||||
# save_condition can be used to ensure atomic read & updates
|
||||
# i.e., prevent interleaved reads and writes from separate contexts
|
||||
w2 = Widget.objects.get()
|
||||
self.assertEqual(w1, w2)
|
||||
old_id = w1.save_id
|
||||
|
||||
flip(w1)
|
||||
w1.save_id = UUID(2)
|
||||
w1.save(save_condition={'save_id':old_id})
|
||||
w1.reload()
|
||||
self.assertFalse(w1.toggle)
|
||||
self.assertEqual(w1.count, 2)
|
||||
flip(w2)
|
||||
flip(w2)
|
||||
w2.save(save_condition={'save_id':old_id})
|
||||
w2.reload()
|
||||
self.assertFalse(w2.toggle)
|
||||
self.assertEqual(w2.count, 2)
|
||||
|
||||
# save_condition uses mongoengine-style operator syntax
|
||||
flip(w1)
|
||||
w1.save(save_condition={'count__lt':w1.count})
|
||||
w1.reload()
|
||||
self.assertTrue(w1.toggle)
|
||||
self.assertEqual(w1.count, 3)
|
||||
flip(w1)
|
||||
w1.save(save_condition={'count__gte':w1.count})
|
||||
w1.reload()
|
||||
self.assertTrue(w1.toggle)
|
||||
self.assertEqual(w1.count, 3)
|
||||
|
||||
def test_update(self):
|
||||
"""Ensure that an existing document is updated instead of be
|
||||
overwritten."""
|
||||
@@ -990,6 +1064,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
|
||||
@@ -2415,7 +2499,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))
|
||||
|
||||
@@ -2423,18 +2507,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):
|
||||
|
||||
Reference in New Issue
Block a user