Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 467dff2

Browse files
committed
Stop document context manager from saving if an error is raised.
1 parent 2744202 commit 467dff2

File tree

3 files changed

+49
-5
lines changed

3 files changed

+49
-5
lines changed

CHANGES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Unreleased
22

3-
- [IMPROVED] Updated `Getting started` section with a `get_query_result` example.
3+
- [FIXED] Bug where document context manager performed remote save despite
4+
uncaught exceptions being raised inside `with` block.
45
- [FIXED] Fixed parameter type of `selector` in docstring.
6+
- [IMPROVED] Updated `Getting started` section with a `get_query_result` example.
57

68
# 2.11.0 (2019-01-21)
79

src/cloudant/document.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,13 @@ def __enter__(self):
341341

342342
return self
343343

344-
def __exit__(self, *args):
344+
def __exit__(self, exc_type, exc_value, traceback):
345345
"""
346-
Support context like editing of document fields. Handles context exit
347-
logic. Executes a Document.save() upon exit.
346+
Support context like editing of document fields. Handles context exit
347+
logic. Executes a `Document.save()` upon exit if no exception occurred.
348348
"""
349-
self.save()
349+
if exc_type is None:
350+
self.save()
350351

351352
def __setitem__(self, key, value):
352353
"""

tests/unit/document_tests.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,47 @@ def test_document_context_manager_no_doc_id(self):
622622
self.assertTrue(doc['_rev'].startswith('1-'))
623623
self.assertEqual(self.db['julia006'], doc)
624624

625+
def test_document_context_manager_creation_failure_on_error(self):
626+
"""
627+
Test that the document context manager skips document creation if there
628+
is an error.
629+
"""
630+
with self.assertRaises(ZeroDivisionError), Document(self.db, 'julia006') as doc:
631+
doc['name'] = 'julia'
632+
doc['age'] = 6
633+
raise ZeroDivisionError()
634+
635+
doc = Document(self.db, 'julia006')
636+
try:
637+
doc.fetch()
638+
except requests.HTTPError as err:
639+
self.assertEqual(err.response.status_code, 404)
640+
else:
641+
self.fail('Above statement should raise a HTTPError.')
642+
643+
def test_document_context_manager_update_failure_on_error(self):
644+
"""
645+
Test that the document context manager skips document update if there
646+
is an error.
647+
"""
648+
# Create the document.
649+
doc = Document(self.db, 'julia006')
650+
doc['name'] = 'julia'
651+
doc['age'] = 6
652+
doc.save()
653+
654+
# Make a document update and then raise an error.
655+
with self.assertRaises(ZeroDivisionError), Document(self.db, 'julia006') as doc:
656+
doc['age'] = 7
657+
raise ZeroDivisionError()
658+
659+
# Assert the change persists locally.
660+
self.assertEqual(doc['age'], 7)
661+
662+
# Assert the document has not been saved to remote server.
663+
self.assertTrue(doc['_rev'].startswith('1-'))
664+
self.assertEqual(self.db['julia006']['age'], 6)
665+
625666
def test_document_context_manager_doc_create(self):
626667
"""
627668
Test that the document context manager will create a doc if it does

0 commit comments

Comments
 (0)