From 882428b725bb93d40f6ff3df99bdc24ce0aee9db Mon Sep 17 00:00:00 2001 From: Sooyong Kim Date: Fri, 10 May 2024 00:50:33 +1200 Subject: [PATCH] [s3] Fix newlines test for python 3.11 and above SpooledTemporaryFile introduced new changes in 3.11 (https://docs.python.org/3/library/tempfile.html) It now fully implements the io.BufferedIOBase and io.TextIOBase abstract base classes allowing the file to be readable in the mode that it was specified (without accessing the underlying ._file object). It seems like wrapping the underlying ._file is forbidden for versions 3.11 and higher (results in the ValueError) Having two have separate methods for different versions isn't the prettiest fix but should suffice. --- storages/backends/s3.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/storages/backends/s3.py b/storages/backends/s3.py index b6627e00..93f67276 100644 --- a/storages/backends/s3.py +++ b/storages/backends/s3.py @@ -185,7 +185,16 @@ def _get_file(self): if self._storage.gzip and self.obj.content_encoding == "gzip": self._file = self._decompress_file(mode=self._mode, file=self._file) elif "b" not in self._mode: - self._file = io.TextIOWrapper(self._file._file, encoding="utf-8") + if hasattr(self._file, "readable"): + # For versions > Python 3.10 compatibility + # See SpooledTemporaryFile changes in 3.11 (https://docs.python.org/3/library/tempfile.html) + # Now fully implements the io.BufferedIOBase and io.TextIOBase abstract base classes allowing the file + # to be readable in the mode that it was specified (without accessing the underlying _file object). + # In this case, we need to wrap the file in a TextIOWrapper to ensure that the file is read as a text file. + self._file = io.TextIOWrapper(self._file, encoding="utf-8") + else: + # For versions <= Python 3.10 compatibility + self._file = io.TextIOWrapper(self._file._file, encoding="utf-8") self._closed = False return self._file