diff --git a/storages/backends/s3.py b/storages/backends/s3.py index 66f7a0cf..71cc00e4 100644 --- a/storages/backends/s3.py +++ b/storages/backends/s3.py @@ -132,6 +132,7 @@ def __init__(self, name, mode, storage, buffer_size=None): self.obj.load(**params) self._is_dirty = False self._raw_bytes_written = 0 + self._closed = False self._file = None self._multipart = None self._parts = None @@ -148,7 +149,7 @@ def size(self): @property def closed(self): - return not self._file or self._file.closed + return self._closed def _get_file(self): if self._file is None: @@ -168,6 +169,7 @@ def _get_file(self): self._file.seek(0) if self._storage.gzip and self.obj.content_encoding == "gzip": self._file = self._decompress_file(mode=self._mode, file=self._file) + self._closed = False return self._file def _set_file(self, value): @@ -262,6 +264,7 @@ def close(self): if self._file is not None: self._file.close() self._file = None + self._closed = True @deconstructible diff --git a/tests/test_s3.py b/tests/test_s3.py index 6f43980a..95def021 100644 --- a/tests/test_s3.py +++ b/tests/test_s3.py @@ -904,18 +904,22 @@ def test_loading_ssec(self): def test_closed(self): f = s3.S3File("test", "wb", self.storage) - with self.subTest("is True after init"): - self.assertTrue(f.closed) + with self.subTest("after init"): + self.assertFalse(f.closed) - with self.subTest("is False after file access"): + with self.subTest("after file access"): # Ensure _get_file has been called f.file self.assertFalse(f.closed) - with self.subTest("is True after close"): + with self.subTest("after close"): f.close() self.assertTrue(f.closed) + with self.subTest("reopening"): + f.file + self.assertFalse(f.closed) + @mock_s3 class S3StorageTestsWithMoto(TestCase):