Raise error if save_condition fails #991

This commit is contained in:
Emmanuel Leblond 2015-05-21 17:35:51 +02:00
parent 548a552638
commit 3e000f9be1
2 changed files with 12 additions and 5 deletions

View File

@ -266,7 +266,8 @@ class Document(BaseDocument):
to cascading saves. Implies ``cascade=True``. to cascading saves. Implies ``cascade=True``.
:param _refs: A list of processed references used in cascading saves :param _refs: A list of processed references used in cascading saves
:param save_condition: only perform save if matching record in db :param save_condition: only perform save if matching record in db
satisfies condition(s) (e.g., version number) satisfies condition(s) (e.g., version number).
Raises :class:`OperationError` if the conditions are not satisfied
.. versionchanged:: 0.5 .. versionchanged:: 0.5
In existing documents it only saves changed fields using In existing documents it only saves changed fields using
@ -348,6 +349,9 @@ class Document(BaseDocument):
upsert = save_condition is None upsert = save_condition is None
last_error = collection.update(select_dict, update_query, last_error = collection.update(select_dict, update_query,
upsert=upsert, **write_concern) upsert=upsert, **write_concern)
if save_condition is not None and last_error['nModified'] == 0:
raise OperationError('Race condition preventing'
' document update detected')
created = is_new_object(last_error) created = is_new_object(last_error)
if cascade is None: if cascade is None:

View File

@ -954,11 +954,12 @@ class InstanceTest(unittest.TestCase):
self.assertEqual(w1.save_id, UUID(1)) self.assertEqual(w1.save_id, UUID(1))
self.assertEqual(w1.count, 0) self.assertEqual(w1.count, 0)
# mismatch in save_condition prevents save # mismatch in save_condition prevents save and raise exception
flip(w1) flip(w1)
self.assertTrue(w1.toggle) self.assertTrue(w1.toggle)
self.assertEqual(w1.count, 1) self.assertEqual(w1.count, 1)
w1.save(save_condition={'save_id': UUID(42)}) self.assertRaises(OperationError,
w1.save, save_condition={'save_id': UUID(42)})
w1.reload() w1.reload()
self.assertFalse(w1.toggle) self.assertFalse(w1.toggle)
self.assertEqual(w1.count, 0) self.assertEqual(w1.count, 0)
@ -986,7 +987,8 @@ class InstanceTest(unittest.TestCase):
self.assertEqual(w1.count, 2) self.assertEqual(w1.count, 2)
flip(w2) flip(w2)
flip(w2) flip(w2)
w2.save(save_condition={'save_id': old_id}) self.assertRaises(OperationError,
w2.save, save_condition={'save_id': old_id})
w2.reload() w2.reload()
self.assertFalse(w2.toggle) self.assertFalse(w2.toggle)
self.assertEqual(w2.count, 2) self.assertEqual(w2.count, 2)
@ -998,7 +1000,8 @@ class InstanceTest(unittest.TestCase):
self.assertTrue(w1.toggle) self.assertTrue(w1.toggle)
self.assertEqual(w1.count, 3) self.assertEqual(w1.count, 3)
flip(w1) flip(w1)
w1.save(save_condition={'count__gte': w1.count}) self.assertRaises(OperationError,
w1.save, save_condition={'count__gte': w1.count})
w1.reload() w1.reload()
self.assertTrue(w1.toggle) self.assertTrue(w1.toggle)
self.assertEqual(w1.count, 3) self.assertEqual(w1.count, 3)