From 8b72c80d3ab87097efa9181fec5011a7a440695c Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Wed, 2 Aug 2023 09:56:27 -0700 Subject: [PATCH 1/4] CLN: Remove testing for py.path objects --- doc/source/conf.py | 1 - doc/source/user_guide/io.rst | 4 +-- pandas/_testing/__init__.py | 2 -- pandas/_testing/_io.py | 29 ------------------- pandas/io/common.py | 2 +- pandas/io/excel/_base.py | 2 +- pandas/io/stata.py | 8 ++--- pandas/tests/io/excel/test_readers.py | 13 --------- pandas/tests/io/excel/test_writers.py | 8 ----- .../io/parser/common/test_file_buffer_url.py | 9 ------ pandas/tests/io/pytables/test_read.py | 20 ------------- pandas/tests/io/pytables/test_store.py | 15 ---------- pandas/tests/io/sas/test_sas7bdat.py | 12 -------- pandas/tests/io/test_common.py | 20 +------------ pandas/tests/io/test_feather.py | 5 ---- pandas/tests/io/test_pickle.py | 6 ---- pandas/tests/io/test_stata.py | 7 ----- 17 files changed, 9 insertions(+), 154 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 0d69e030f913a..bac04b844ba81 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -453,7 +453,6 @@ "matplotlib": ("https://matplotlib.org/stable/", None), "numpy": ("https://numpy.org/doc/stable/", None), "pandas-gbq": ("https://pandas-gbq.readthedocs.io/en/latest/", None), - "py": ("https://pylib.readthedocs.io/en/latest/", None), "python": ("https://docs.python.org/3/", None), "scipy": ("https://docs.scipy.org/doc/scipy/", None), "pyarrow": ("https://arrow.apache.org/docs/", None), diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index 006ab5c49e24c..6c622ac835c47 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -61,8 +61,8 @@ Basic +++++ filepath_or_buffer : various - Either a path to a file (a :class:`python:str`, :class:`python:pathlib.Path`, - or :class:`py:py._path.local.LocalPath`), URL (including http, ftp, and S3 + Either a path to a file (a :class:`python:str`, :class:`python:pathlib.Path`) + URL (including http, ftp, and S3 locations), or any object with a ``read()`` method (such as an open file or :class:`~python:io.StringIO`). sep : str, defaults to ``','`` for :func:`read_csv`, ``\t`` for :func:`read_table` diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index 78c882dc94a99..215e6c3ca6111 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -49,7 +49,6 @@ bdate_range, ) from pandas._testing._io import ( - round_trip_localpath, round_trip_pathlib, round_trip_pickle, write_to_compressed, @@ -1130,7 +1129,6 @@ def shares_memory(left, right) -> bool: "rands", "reset_display_options", "raises_chained_assignment_error", - "round_trip_localpath", "round_trip_pathlib", "round_trip_pickle", "setitem", diff --git a/pandas/_testing/_io.py b/pandas/_testing/_io.py index 49fde6d08fa11..1612fdfc881b3 100644 --- a/pandas/_testing/_io.py +++ b/pandas/_testing/_io.py @@ -89,35 +89,6 @@ def round_trip_pathlib(writer, reader, path: str | None = None): return obj -def round_trip_localpath(writer, reader, path: str | None = None): - """ - Write an object to file specified by a py.path LocalPath and read it back. - - Parameters - ---------- - writer : callable bound to pandas object - IO writing function (e.g. DataFrame.to_csv ) - reader : callable - IO reading function (e.g. pd.read_csv ) - path : str, default None - The path where the object is written and then read. - - Returns - ------- - pandas object - The original object that was serialized and then re-read. - """ - import pytest - - LocalPath = pytest.importorskip("py.path").local - if path is None: - path = "___localpath___" - with ensure_clean(path) as path: - writer(LocalPath(path)) - obj = reader(LocalPath(path)) - return obj - - def write_to_compressed(compression, path, data, dest: str = "test"): """ Write data to a compressed file. diff --git a/pandas/io/common.py b/pandas/io/common.py index 35e93d287f31a..ed8847102d2d3 100644 --- a/pandas/io/common.py +++ b/pandas/io/common.py @@ -303,7 +303,7 @@ def _get_filepath_or_buffer( Parameters ---------- - filepath_or_buffer : a url, filepath (str, py.path.local or pathlib.Path), + filepath_or_buffer : a url, filepath (str or pathlib.Path), or buffer {compression_options} diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 7c67f85ed3d1e..479b4a8e71b05 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -1442,7 +1442,7 @@ class ExcelFile: Parameters ---------- - path_or_buffer : str, bytes, path object (pathlib.Path or py._path.local.LocalPath), + path_or_buffer : str, bytes, pathlib.Path, A file-like object, xlrd workbook or openpyxl workbook. If a string or path object, expected to be a path to a .xls, .xlsx, .xlsb, .xlsm, .odf, .ods, or .odt file. diff --git a/pandas/io/stata.py b/pandas/io/stata.py index 698a2882ada39..0b48697e8909a 100644 --- a/pandas/io/stata.py +++ b/pandas/io/stata.py @@ -215,7 +215,7 @@ Parameters ---------- path_or_buf : path (string), buffer or path object - string, path object (pathlib.Path or py._path.local.LocalPath) or object + string, pathlib.Path or object implementing a binary read() functions. {_statafile_processing_params1} {_statafile_processing_params2} @@ -2299,7 +2299,7 @@ class StataWriter(StataParser): Parameters ---------- fname : path (string), buffer or path object - string, path object (pathlib.Path or py._path.local.LocalPath) or + string, pathlib.Path or object implementing a binary write() functions. If using a buffer then the buffer will not be automatically closed after the file is written. @@ -3244,7 +3244,7 @@ class StataWriter117(StataWriter): Parameters ---------- fname : path (string), buffer or path object - string, path object (pathlib.Path or py._path.local.LocalPath) or + string, pathlib.Path or object implementing a binary write() functions. If using a buffer then the buffer will not be automatically closed after the file is written. @@ -3630,7 +3630,7 @@ class StataWriterUTF8(StataWriter117): Parameters ---------- fname : path (string), buffer or path object - string, path object (pathlib.Path or py._path.local.LocalPath) or + string, pathlib.Path or object implementing a binary write() functions. If using a buffer then the buffer will not be automatically closed after the file is written. diff --git a/pandas/tests/io/excel/test_readers.py b/pandas/tests/io/excel/test_readers.py index 7df5b928858d8..d5e5266495f42 100644 --- a/pandas/tests/io/excel/test_readers.py +++ b/pandas/tests/io/excel/test_readers.py @@ -940,19 +940,6 @@ def test_read_from_pathlib_path(self, read_ext): tm.assert_frame_equal(expected, actual) - @td.skip_if_no("py.path") - def test_read_from_py_localpath(self, read_ext): - # GH12655 - from py.path import local as LocalPath - - str_path = os.path.join("test1" + read_ext) - expected = pd.read_excel(str_path, sheet_name="Sheet1", index_col=0) - - path_obj = LocalPath().join("test1" + read_ext) - actual = pd.read_excel(path_obj, sheet_name="Sheet1", index_col=0) - - tm.assert_frame_equal(expected, actual) - def test_close_from_py_localpath(self, read_ext): # GH31467 str_path = os.path.join("test1" + read_ext) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 905c733ea5ef1..29b1c3ad652ad 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -1215,14 +1215,6 @@ def test_path_path_lib(self, engine, ext): result = tm.round_trip_pathlib(writer, reader, path=f"foo{ext}") tm.assert_frame_equal(result, df) - def test_path_local_path(self, engine, ext): - df = tm.makeDataFrame() - writer = partial(df.to_excel, engine=engine) - - reader = partial(pd.read_excel, index_col=0) - result = tm.round_trip_localpath(writer, reader, path=f"foo{ext}") - tm.assert_frame_equal(result, df) - def test_merged_cell_custom_objects(self, path): # see GH-27006 mi = MultiIndex.from_tuples( diff --git a/pandas/tests/io/parser/common/test_file_buffer_url.py b/pandas/tests/io/parser/common/test_file_buffer_url.py index 5ee629947db48..8b8423f5ac5d6 100644 --- a/pandas/tests/io/parser/common/test_file_buffer_url.py +++ b/pandas/tests/io/parser/common/test_file_buffer_url.py @@ -67,15 +67,6 @@ def test_path_path_lib(all_parsers): tm.assert_frame_equal(df, result) -def test_path_local_path(all_parsers): - parser = all_parsers - df = tm.makeDataFrame() - result = tm.round_trip_localpath( - df.to_csv, lambda p: parser.read_csv(p, index_col=0) - ) - tm.assert_frame_equal(df, result) - - def test_nonexistent_path(all_parsers): # gh-2428: pls no segfault # gh-14086: raise more helpful FileNotFoundError diff --git a/pandas/tests/io/pytables/test_read.py b/pandas/tests/io/pytables/test_read.py index 89b234b24522c..e85f808e1cda0 100644 --- a/pandas/tests/io/pytables/test_read.py +++ b/pandas/tests/io/pytables/test_read.py @@ -21,7 +21,6 @@ _maybe_remove, ensure_clean_store, ) -from pandas.util import _test_decorators as td from pandas.io.pytables import TableIterator @@ -331,25 +330,6 @@ def test_read_from_pathlib_path(tmp_path, setup_path): tm.assert_frame_equal(expected, actual) -@td.skip_if_no("py.path") -def test_read_from_py_localpath(tmp_path, setup_path): - # GH11773 - from py.path import local as LocalPath - - expected = DataFrame( - np.random.default_rng(2).random((4, 5)), - index=list("abcd"), - columns=list("ABCDE"), - ) - filename = tmp_path / setup_path - path_obj = LocalPath(filename) - - expected.to_hdf(path_obj, "df", mode="a") - actual = read_hdf(path_obj, "df") - - tm.assert_frame_equal(expected, actual) - - @pytest.mark.parametrize("format", ["fixed", "table"]) def test_read_hdf_series_mode_r(tmp_path, format, setup_path): # GH 16583 diff --git a/pandas/tests/io/pytables/test_store.py b/pandas/tests/io/pytables/test_store.py index 5d45c92ece0dc..c2fdc3c0839df 100644 --- a/pandas/tests/io/pytables/test_store.py +++ b/pandas/tests/io/pytables/test_store.py @@ -828,21 +828,6 @@ def test_pickle_path_localpath(): tm.assert_frame_equal(df, result) -def test_path_localpath_hdfstore(): - df = tm.makeDataFrame() - - def writer(path): - with HDFStore(path) as store: - df.to_hdf(store, "df") - - def reader(path): - with HDFStore(path) as store: - return read_hdf(store, "df") - - result = tm.round_trip_localpath(writer, reader) - tm.assert_frame_equal(df, result) - - @pytest.mark.parametrize("propindexes", [True, False]) def test_copy(propindexes): df = tm.makeDataFrame() diff --git a/pandas/tests/io/sas/test_sas7bdat.py b/pandas/tests/io/sas/test_sas7bdat.py index d56139d32b1da..19c365e50e7cc 100644 --- a/pandas/tests/io/sas/test_sas7bdat.py +++ b/pandas/tests/io/sas/test_sas7bdat.py @@ -9,7 +9,6 @@ import pytest from pandas.errors import EmptyDataError -import pandas.util._test_decorators as td import pandas as pd import pandas._testing as tm @@ -80,17 +79,6 @@ def test_path_pathlib(self, dirpath, data_test_ix): df = pd.read_sas(fname, encoding="utf-8") tm.assert_frame_equal(df, df0) - @td.skip_if_no("py.path") - @pytest.mark.slow - def test_path_localpath(self, dirpath, data_test_ix): - from py.path import local as LocalPath - - df0, test_ix = data_test_ix - for k in test_ix: - fname = LocalPath(os.path.join(dirpath, f"test{k}.sas7bdat")) - df = pd.read_sas(fname, encoding="utf-8") - tm.assert_frame_equal(df, df0) - @pytest.mark.slow @pytest.mark.parametrize("chunksize", (3, 5, 10, 11)) @pytest.mark.parametrize("k", range(1, 17)) diff --git a/pandas/tests/io/test_common.py b/pandas/tests/io/test_common.py index 435b9bdade944..15c6d8d0c753f 100644 --- a/pandas/tests/io/test_common.py +++ b/pandas/tests/io/test_common.py @@ -36,16 +36,6 @@ def __fspath__(self): return self.path -# Functions that consume a string path and return a string or path-like object -path_types = [str, CustomFSPath, Path] - -try: - from py.path import local as LocalPath - - path_types.append(LocalPath) -except ImportError: - pass - HERE = os.path.abspath(os.path.dirname(__file__)) @@ -81,13 +71,6 @@ def test_stringify_path_pathlib(self): redundant_path = icom.stringify_path(Path("foo//bar")) assert redundant_path == os.path.join("foo", "bar") - @td.skip_if_no("py.path") - def test_stringify_path_localpath(self): - path = os.path.join("foo", "bar") - abs_path = os.path.abspath(path) - lpath = LocalPath(path) - assert icom.stringify_path(lpath) == abs_path - def test_stringify_path_fspath(self): p = CustomFSPath("foo/bar.csv") result = icom.stringify_path(p) @@ -100,7 +83,7 @@ def test_stringify_file_and_path_like(self): with fsspec.open(f"file://{path}", mode="wb") as fsspec_obj: assert fsspec_obj == icom.stringify_path(fsspec_obj) - @pytest.mark.parametrize("path_type", path_types) + @pytest.mark.parametrize("path_type", [str, CustomFSPath, Path]) def test_infer_compression_from_path(self, compression_format, path_type): extension, expected = compression_format path = path_type("foo/bar.csv" + extension) @@ -109,7 +92,6 @@ def test_infer_compression_from_path(self, compression_format, path_type): @pytest.mark.parametrize("path_type", [str, CustomFSPath, Path]) def test_get_handle_with_path(self, path_type): - # ignore LocalPath: it creates strange paths: /absolute/~/sometest with tempfile.TemporaryDirectory(dir=Path.home()) as tmp: filename = path_type("~/" + Path(tmp).name + "/sometest") with icom.get_handle(filename, "w") as handles: diff --git a/pandas/tests/io/test_feather.py b/pandas/tests/io/test_feather.py index 9de097fe8c0e6..0d6b5511eb84d 100644 --- a/pandas/tests/io/test_feather.py +++ b/pandas/tests/io/test_feather.py @@ -132,11 +132,6 @@ def test_path_pathlib(self): result = tm.round_trip_pathlib(df.to_feather, read_feather) tm.assert_frame_equal(df, result) - def test_path_localpath(self): - df = tm.makeDataFrame().reset_index() - result = tm.round_trip_localpath(df.to_feather, read_feather) - tm.assert_frame_equal(df, result) - def test_passthrough_keywords(self): df = tm.makeDataFrame().reset_index() self.check_round_trip(df, write_kwargs={"version": 1}) diff --git a/pandas/tests/io/test_pickle.py b/pandas/tests/io/test_pickle.py index d66d5d532962c..70e6ec7707967 100644 --- a/pandas/tests/io/test_pickle.py +++ b/pandas/tests/io/test_pickle.py @@ -224,12 +224,6 @@ def test_pickle_path_pathlib(): tm.assert_frame_equal(df, result) -def test_pickle_path_localpath(): - df = tm.makeDataFrame() - result = tm.round_trip_localpath(df.to_pickle, pd.read_pickle) - tm.assert_frame_equal(df, result) - - # --------------------- # test pickle compression # --------------------- diff --git a/pandas/tests/io/test_stata.py b/pandas/tests/io/test_stata.py index 6130271325bee..9856c628a83d3 100644 --- a/pandas/tests/io/test_stata.py +++ b/pandas/tests/io/test_stata.py @@ -1562,13 +1562,6 @@ def test_path_pathlib(self): result = tm.round_trip_pathlib(df.to_stata, reader) tm.assert_frame_equal(df, result) - def test_pickle_path_localpath(self): - df = tm.makeDataFrame() - df.index.name = "index" - reader = lambda x: read_stata(x).set_index("index") - result = tm.round_trip_localpath(df.to_stata, reader) - tm.assert_frame_equal(df, result) - @pytest.mark.parametrize("write_index", [True, False]) def test_value_labels_iterator(self, write_index): # GH 16923 From 33d9a90c51d7a502d7125c32d3839800552f78b6 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:47:15 -0800 Subject: [PATCH 2/4] Add whatsnew --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 950082f9281c5..d2fb0f2cbdbbd 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -84,7 +84,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor Other API changes ^^^^^^^^^^^^^^^^^ -- +- 3rd party ``py.path`` objects are no longer supported in IO methods. Use :py:class:`pathlib.Path` objects instead (:issue:`?`) - .. --------------------------------------------------------------------------- From 5c4a1e76f80012cbab481f65db465ec3671ffaa1 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:48:14 -0800 Subject: [PATCH 3/4] Missed annotation --- pandas/_testing/_io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_testing/_io.py b/pandas/_testing/_io.py index aad284df2bd14..2955108d3db1a 100644 --- a/pandas/_testing/_io.py +++ b/pandas/_testing/_io.py @@ -89,7 +89,7 @@ def round_trip_pathlib(writer, reader, path: str | None = None): return obj -def write_to_compressed(compression, path, data, dest: str = "test"): +def write_to_compressed(compression, path, data, dest: str = "test") -> None: """ Write data to a compressed file. From c57884f38bce460dc81452b74328631920793ead Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:56:39 -0800 Subject: [PATCH 4/4] Add whatsnew --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index d2fb0f2cbdbbd..73201fa93a8aa 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -84,7 +84,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor Other API changes ^^^^^^^^^^^^^^^^^ -- 3rd party ``py.path`` objects are no longer supported in IO methods. Use :py:class:`pathlib.Path` objects instead (:issue:`?`) +- 3rd party ``py.path`` objects are no longer explicitly supported in IO methods. Use :py:class:`pathlib.Path` objects instead (:issue:`57091`) - .. ---------------------------------------------------------------------------