From ab89c088cfcb7dbcd6e3cc69d0d002086fe118ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Tue, 23 Feb 2021 19:11:07 -0500 Subject: [PATCH] REGR: compressed to_json with URL-like paths and binary objects --- doc/source/whatsnew/v1.2.3.rst | 2 ++ pandas/io/json/_json.py | 2 +- pandas/tests/io/json/test_compression.py | 12 ++++++++++++ pandas/tests/io/test_fsspec.py | 14 +++++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v1.2.3.rst b/doc/source/whatsnew/v1.2.3.rst index 41cea7fe125a1..9b02a7892c078 100644 --- a/doc/source/whatsnew/v1.2.3.rst +++ b/doc/source/whatsnew/v1.2.3.rst @@ -18,6 +18,8 @@ Fixed regressions - Fixed regression in :meth:`~DataFrame.to_excel` raising ``KeyError`` when giving duplicate columns with ``columns`` attribute (:issue:`39695`) - Fixed regression in :class:`IntegerArray` unary ops propagating mask on assignment (:issue:`39943`) - Fixed regression in :meth:`DataFrame.__setitem__` not aligning :class:`DataFrame` on right-hand side for boolean indexer (:issue:`39931`) +- Fixed regression in :meth:`~DataFrame.to_json` failing to use ``compression`` with URL-like paths that are internally opened in binary mode or with user-provided file objects that are opened in binary mode (:issue:`39985`) +- .. --------------------------------------------------------------------------- diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index 635a493d03d61..f050a6a086584 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -130,7 +130,7 @@ def to_json( if path_or_buf is not None: # apply compression and byte/text conversion with get_handle( - path_or_buf, "wt", compression=compression, storage_options=storage_options + path_or_buf, "w", compression=compression, storage_options=storage_options ) as handles: handles.handle.write(s) else: diff --git a/pandas/tests/io/json/test_compression.py b/pandas/tests/io/json/test_compression.py index 6ead81db1fab0..8c69ffedf1df4 100644 --- a/pandas/tests/io/json/test_compression.py +++ b/pandas/tests/io/json/test_compression.py @@ -1,3 +1,5 @@ +from io import BytesIO + import pytest import pandas.util._test_decorators as td @@ -117,3 +119,13 @@ def test_to_json_compression(compression_only, read_infer, to_infer): df.to_json(path, compression=to_compression) result = pd.read_json(path, compression=read_compression) tm.assert_frame_equal(result, df) + + +def test_to_json_compression_mode(compression): + # GH 39985 (read_json does not support user-provided binary files) + expected = pd.DataFrame({"A": [1]}) + + with BytesIO() as buffer: + expected.to_json(buffer, compression=compression) + # df = pd.read_json(buffer, compression=compression) + # tm.assert_frame_equal(expected, df) diff --git a/pandas/tests/io/test_fsspec.py b/pandas/tests/io/test_fsspec.py index 3131131682ccd..d97aaa2ea2763 100644 --- a/pandas/tests/io/test_fsspec.py +++ b/pandas/tests/io/test_fsspec.py @@ -248,11 +248,19 @@ def test_pickle_options(fsspectest): @td.skip_array_manager_not_yet_implemented # TODO(ArrayManager) JSON -def test_json_options(fsspectest): +def test_json_options(fsspectest, compression): df = DataFrame({"a": [0]}) - df.to_json("testmem://afile", storage_options={"test": "json_write"}) + df.to_json( + "testmem://afile", + compression=compression, + storage_options={"test": "json_write"}, + ) assert fsspectest.test[0] == "json_write" - out = read_json("testmem://afile", storage_options={"test": "json_read"}) + out = read_json( + "testmem://afile", + compression=compression, + storage_options={"test": "json_read"}, + ) assert fsspectest.test[0] == "json_read" tm.assert_frame_equal(df, out)