From 3e000f9be1d7e4fdd93317b6da0ab4a0e07b5431 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Thu, 21 May 2015 17:35:51 +0200 Subject: [PATCH] Raise error if save_condition fails #991 --- mongoengine/document.py | 6 +++++- tests/document/instance.py | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/mongoengine/document.py b/mongoengine/document.py index 060919ca..2c4872e9 100644 --- a/mongoengine/document.py +++ b/mongoengine/document.py @@ -266,7 +266,8 @@ class Document(BaseDocument): to cascading saves. Implies ``cascade=True``. :param _refs: A list of processed references used in cascading saves :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 In existing documents it only saves changed fields using @@ -348,6 +349,9 @@ class Document(BaseDocument): upsert = save_condition is None last_error = collection.update(select_dict, update_query, 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) if cascade is None: diff --git a/tests/document/instance.py b/tests/document/instance.py index 2cfdef65..3ccabacd 100644 --- a/tests/document/instance.py +++ b/tests/document/instance.py @@ -954,11 +954,12 @@ class InstanceTest(unittest.TestCase): self.assertEqual(w1.save_id, UUID(1)) self.assertEqual(w1.count, 0) - # mismatch in save_condition prevents save + # mismatch in save_condition prevents save and raise exception flip(w1) self.assertTrue(w1.toggle) 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() self.assertFalse(w1.toggle) self.assertEqual(w1.count, 0) @@ -986,7 +987,8 @@ class InstanceTest(unittest.TestCase): self.assertEqual(w1.count, 2) 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() self.assertFalse(w2.toggle) self.assertEqual(w2.count, 2) @@ -998,7 +1000,8 @@ class InstanceTest(unittest.TestCase): self.assertTrue(w1.toggle) self.assertEqual(w1.count, 3) flip(w1) - w1.save(save_condition={'count__gte': w1.count}) + self.assertRaises(OperationError, + w1.save, save_condition={'count__gte': w1.count}) w1.reload() self.assertTrue(w1.toggle) self.assertEqual(w1.count, 3)