From 04155f78d4f825ebb1ae02568d8f6cacc061273e Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 17 Nov 2023 17:49:41 -0800 Subject: [PATCH] DEPR: to_clipboard, read_clipboard --- doc/source/whatsnew/v2.2.0.rst | 1 + pandas/io/clipboards.py | 15 +++++ pandas/tests/io/test_clipboard.py | 103 +++++++++++++++++++----------- 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 3d34955a3baa5..29c768a24dd87 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -264,6 +264,7 @@ Other Deprecations - Changed :meth:`Timedelta.resolution_string` to return ``h``, ``min``, ``s``, ``ms``, ``us``, and ``ns`` instead of ``H``, ``T``, ``S``, ``L``, ``U``, and ``N``, for compatibility with respective deprecations in frequency aliases (:issue:`52536`) - Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`) - Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`) +- Deprecated :meth:`DataFrame.to_clipboard`, :meth:`Series.to_clipboard`, and :func:`pd.read_clipboard` (:issue:`52129`) - Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`) - Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`) - Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_clipboard`. (:issue:`54229`) diff --git a/pandas/io/clipboards.py b/pandas/io/clipboards.py index a15e37328e9fa..96a77a22e2c21 100644 --- a/pandas/io/clipboards.py +++ b/pandas/io/clipboards.py @@ -71,6 +71,13 @@ def read_clipboard( 0 1 2 3 1 4 5 6 """ + warnings.warn( + # GH#52129 + "pd.read_clipboard is deprecated and will be removed in a future " + "version. Copy to a string and use pd.read_csv instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) encoding = kwargs.pop("encoding", "utf-8") # only utf-8 is valid for passed value because that's what clipboard @@ -154,6 +161,14 @@ def to_clipboard( - Windows: - OS X: """ + warnings.warn( + # GH#52129 + f"{type(obj).__name__}.to_clipboard is deprecated and will be removed " + "in a future version. Use obj.to_csv instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + encoding = kwargs.pop("encoding", "utf-8") # testing if an invalid encoding is passed to clipboard diff --git a/pandas/tests/io/test_clipboard.py b/pandas/tests/io/test_clipboard.py index 10e0467c5d74d..688f90a58e68e 100644 --- a/pandas/tests/io/test_clipboard.py +++ b/pandas/tests/io/test_clipboard.py @@ -242,10 +242,75 @@ def test_mock_clipboard(mock_clipboard): assert result == "abc" +@pytest.mark.single_cpu +@pytest.mark.clipboard +@pytest.mark.usefixtures("mock_clipboard") +def test_excel_sep_warning(df): + # Two character separator is not supported in to_clipboard + # Test that multi-character separators are not silently passed + with tm.assert_produces_warning( + (UserWarning, FutureWarning), + match="to_clipboard in excel mode requires a single character separator.", + check_stacklevel=False, + ): + df.to_clipboard(excel=True, sep=r"\t") + + +@pytest.mark.single_cpu +@pytest.mark.clipboard +@pytest.mark.usefixtures("mock_clipboard") +def test_copy_delim_warning(df): + # Separator is ignored when excel=False and should produce a warning + msg = "DataFrame.to_clipboard is deprecated and will be removed" + with tm.assert_produces_warning((UserWarning, FutureWarning), match=msg): + df.to_clipboard(excel=False, sep="\t") + + +@pytest.mark.single_cpu +@pytest.mark.clipboard +@pytest.mark.usefixtures("mock_clipboard") +def test_to_clipboard_pos_args_deprecation(): + # GH#54229 + df = DataFrame({"a": [1, 2, 3]}) + msg = ( + r"Starting with pandas version 3.0 all arguments of to_clipboard " + r"will be keyword-only." + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + df.to_clipboard(True, None) + + +@pytest.mark.single_cpu +@pytest.mark.clipboard +@pytest.mark.usefixtures("mock_clipboard") +@pytest.mark.parametrize("data", ["\U0001f44d...", "Ωœ∑`...", "abcd..."]) +@pytest.mark.xfail( + (os.environ.get("DISPLAY") is None and not is_platform_mac()) + or is_ci_environment(), + reason="Cannot pass if a headless system is not put in place with Xvfb", + strict=not is_ci_environment(), # Flaky failures in the CI +) +def test_raw_roundtrip(data): + # PR #25040 wide unicode wasn't copied correctly on PY3 on windows + clipboard_set(data) + assert data == clipboard_get() + + @pytest.mark.single_cpu @pytest.mark.clipboard @pytest.mark.usefixtures("mock_clipboard") class TestClipboard: + @pytest.fixture(autouse=True) + def assert_deprecated(self): + msg = "|".join( + [ + "DataFrame.to_clipboard is deprecated and will be removed", + "pd.read_clipboard is deprecated", + ] + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + yield + def check_round_trip_frame(self, data, excel=None, sep=None, encoding=None): data.to_clipboard(excel=excel, sep=sep, encoding=encoding) result = read_clipboard(sep=sep or "\t", index_col=0, encoding=encoding) @@ -267,21 +332,6 @@ def test_round_trip_frame_string(self, df): assert df.to_string() == result.to_string() assert df.shape == result.shape - # Two character separator is not supported in to_clipboard - # Test that multi-character separators are not silently passed - def test_excel_sep_warning(self, df): - with tm.assert_produces_warning( - UserWarning, - match="to_clipboard in excel mode requires a single character separator.", - check_stacklevel=False, - ): - df.to_clipboard(excel=True, sep=r"\t") - - # Separator is ignored when excel=False and should produce a warning - def test_copy_delim_warning(self, df): - with tm.assert_produces_warning(): - df.to_clipboard(excel=False, sep="\t") - # Tests that the default behavior of to_clipboard is tab # delimited and excel="True" @pytest.mark.parametrize("sep", ["\t", None, "default"]) @@ -401,19 +451,6 @@ def test_invalid_encoding(self, df): def test_round_trip_valid_encodings(self, enc, df): self.check_round_trip_frame(df, encoding=enc) - @pytest.mark.single_cpu - @pytest.mark.parametrize("data", ["\U0001f44d...", "Ωœ∑`...", "abcd..."]) - @pytest.mark.xfail( - (os.environ.get("DISPLAY") is None and not is_platform_mac()) - or is_ci_environment(), - reason="Cannot pass if a headless system is not put in place with Xvfb", - strict=not is_ci_environment(), # Flaky failures in the CI - ) - def test_raw_roundtrip(self, data): - # PR #25040 wide unicode wasn't copied correctly on PY3 on windows - clipboard_set(data) - assert data == clipboard_get() - @pytest.mark.parametrize("engine", ["c", "python"]) def test_read_clipboard_dtype_backend( self, request, mock_clipboard, string_storage, dtype_backend, engine @@ -471,13 +508,3 @@ def test_invalid_dtype_backend(self): ) with pytest.raises(ValueError, match=msg): read_clipboard(dtype_backend="numpy") - - def test_to_clipboard_pos_args_deprecation(self): - # GH-54229 - df = DataFrame({"a": [1, 2, 3]}) - msg = ( - r"Starting with pandas version 3.0 all arguments of to_clipboard " - r"will be keyword-only." - ) - with tm.assert_produces_warning(FutureWarning, match=msg): - df.to_clipboard(True, None)