diff --git a/doc/source/whatsnew/v1.3.3.rst b/doc/source/whatsnew/v1.3.3.rst index 1ecae3d344f79..9be673f16c6e0 100644 --- a/doc/source/whatsnew/v1.3.3.rst +++ b/doc/source/whatsnew/v1.3.3.rst @@ -29,6 +29,7 @@ Fixed regressions - Fixed regression in :meth:`DataFrame.corr` where Kendall correlation would produce incorrect results for columns with repeated values (:issue:`43401`) - Fixed regression in :meth:`DataFrame.groupby` where aggregation on columns with object types dropped results on those columns (:issue:`42395`, :issue:`43108`) - Fixed regression in :meth:`Series.fillna` raising ``TypeError`` when filling ``float`` ``Series`` with list-like fill value having a dtype which couldn't cast lostlessly (like ``float32`` filled with ``float64``) (:issue:`43424`) +- Fixed regression in :func:`read_csv` throwing an ``AttributeError`` when the file handle is an ``tempfile.SpooledTemporaryFile`` object (:issue:`43439`) - .. --------------------------------------------------------------------------- diff --git a/pandas/io/common.py b/pandas/io/common.py index 06b00a9cbb4eb..16747569e80b5 100644 --- a/pandas/io/common.py +++ b/pandas/io/common.py @@ -15,6 +15,7 @@ ) import mmap import os +import tempfile from typing import ( IO, Any, @@ -943,8 +944,15 @@ def _is_binary_mode(handle: FilePathOrBuffer, mode: str) -> bool: if "t" in mode or "b" in mode: return "b" in mode - # classes that expect string but have 'b' in mode - text_classes = (codecs.StreamWriter, codecs.StreamReader, codecs.StreamReaderWriter) + # exceptions + text_classes = ( + # classes that expect string but have 'b' in mode + codecs.StreamWriter, + codecs.StreamReader, + codecs.StreamReaderWriter, + # cannot be wrapped in TextIOWrapper GH43439 + tempfile.SpooledTemporaryFile, + ) if issubclass(type(handle), text_classes): return False diff --git a/pandas/tests/io/parser/test_encoding.py b/pandas/tests/io/parser/test_encoding.py index 006438df2a5e0..9cf2f068eb318 100644 --- a/pandas/tests/io/parser/test_encoding.py +++ b/pandas/tests/io/parser/test_encoding.py @@ -237,3 +237,16 @@ def test_encoding_memory_map(all_parsers, encoding): expected.to_csv(file, index=False, encoding=encoding) df = parser.read_csv(file, encoding=encoding, memory_map=True) tm.assert_frame_equal(df, expected) + + +def test_not_readable(all_parsers): + # GH43439 + parser = all_parsers + if parser.engine in ("python", "pyarrow"): + pytest.skip("SpooledTemporaryFile does only work with the c-engine") + with tempfile.SpooledTemporaryFile() as handle: + handle.write(b"abcd") + handle.seek(0) + df = parser.read_csv(handle) + expected = DataFrame([], columns=["abcd"]) + tm.assert_frame_equal(df, expected)