Skip to content

Commit c089649

Browse files
committed
Fix unintentional exception clobbering when rollback fails
1 parent 2b70949 commit c089649

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

atomicwrites/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,18 @@ def open(self):
116116
def _open(self, get_fileobject):
117117
f = None # make sure f exists even if get_fileobject() fails
118118
try:
119+
success = False
119120
with get_fileobject() as f:
120121
yield f
121122
self.sync(f)
122123
self.commit(f)
123-
except:
124-
try:
125-
self.rollback(f)
126-
except Exception:
127-
pass
128-
raise
124+
success = True
125+
finally:
126+
if not success:
127+
try:
128+
self.rollback(f)
129+
except Exception:
130+
pass
129131

130132
def get_fileobject(self, dir=None, **kwargs):
131133
'''Return the temporary file to use.'''

tests/test_atomicwrites.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,17 @@ def test_dont_remove_simultaneously_created_file(tmpdir):
5151
assert excinfo.value.errno == errno.EEXIST
5252
assert fname.read() == 'harhar'
5353
assert len(tmpdir.listdir()) == 1
54+
55+
56+
# Verify that nested exceptions during rollback do not overwrite the initial
57+
# exception that triggered a rollback.
58+
def test_open_reraise(tmpdir):
59+
fname = tmpdir.join('ha')
60+
with pytest.raises(AssertionError):
61+
with atomic_write(str(fname), overwrite=False) as f:
62+
# Mess with f, so rollback will trigger an OSError. We're testing
63+
# that the initial AssertionError triggered below is propagated up
64+
# the stack, not the second exception triggered during rollback.
65+
f.name = "asdf"
66+
# Now trigger our own exception.
67+
assert False, "Intentional failure for testing purposes"

0 commit comments

Comments
 (0)