diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fc7d31..575f1f5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -482,3 +482,4 @@ The old `smart_open.smart_open` function is deprecated, but continues to work as - support for multistream bzip files (PR #9, @pombredanne) - introduce this CHANGELOG + diff --git a/smart_open/s3.py b/smart_open/s3.py index 09433ad7..60ae2a99 100644 --- a/smart_open/s3.py +++ b/smart_open/s3.py @@ -1209,8 +1209,8 @@ def write(self, b): return length def terminate(self): - """Nothing to cancel in single-part uploads.""" - return + self._buf = None + logger.debug('%s: terminated singlepart upload', self) # # Internal methods. diff --git a/smart_open/tests/test_s3.py b/smart_open/tests/test_s3.py index ff44ad4f..61aec986 100644 --- a/smart_open/tests/test_s3.py +++ b/smart_open/tests/test_s3.py @@ -795,6 +795,26 @@ def test_str(self): with smart_open.s3.open(BUCKET_NAME, 'key', 'wb', multipart_upload=False) as fout: assert str(fout) == "smart_open.s3.SinglepartWriter('test-smartopen', 'key')" + def test_ensure_no_side_effects_on_exception(self): + class WriteError(Exception): + pass + + s3_resource = _resource("s3") + obj = s3_resource.Object(BUCKET_NAME, KEY_NAME) + + # wrap in closure to ease writer dereferencing + def _run(): + with smart_open.s3.open(BUCKET_NAME, obj.key, "wb", multipart_upload=False) as fout: + fout.write(b"this should not be written") + raise WriteError + + try: + _run() + except WriteError: + pass + finally: + self.assertRaises(s3_resource.meta.client.exceptions.NoSuchKey, obj.get) + ARBITRARY_CLIENT_ERROR = botocore.client.ClientError(error_response={}, operation_name='bar')