Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for py.path objects in IO readers #57091

Merged
merged 19 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8b72c80
CLN: Remove testing for py.path objects
mroeschke Aug 2, 2023
81ebfc5
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Aug 4, 2023
fabac8e
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Aug 10, 2023
8a7a891
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Aug 18, 2023
75660b4
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Aug 25, 2023
f309da4
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Sep 11, 2023
e06901b
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Oct 12, 2023
1592a08
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Oct 19, 2023
2f773f5
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Oct 30, 2023
6b041c4
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Nov 6, 2023
28edd05
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Nov 17, 2023
2ad1d4c
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Nov 21, 2023
3a7d074
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Dec 4, 2023
3993cd0
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Dec 11, 2023
cf9132e
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Dec 27, 2023
419301a
Merge remote-tracking branch 'upstream/main' into cln/py
mroeschke Jan 26, 2024
33d9a90
Add whatsnew
mroeschke Jan 26, 2024
5c4a1e7
Missed annotation
mroeschke Jan 26, 2024
c57884f
Add whatsnew
mroeschke Jan 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@
"dateutil": ("https://dateutil.readthedocs.io/en/latest/", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"numpy": ("https://numpy.org/doc/stable/", 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),
Expand Down
4 changes: 2 additions & 2 deletions doc/source/user_guide/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 explicitly supported in IO methods. Use :py:class:`pathlib.Path` objects instead (:issue:`57091`)
-

.. ---------------------------------------------------------------------------
Expand Down
2 changes: 0 additions & 2 deletions pandas/_testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
Series,
)
from pandas._testing._io import (
round_trip_localpath,
round_trip_pathlib,
round_trip_pickle,
write_to_compressed,
Expand Down Expand Up @@ -609,7 +608,6 @@ def shares_memory(left, right) -> bool:
"OBJECT_DTYPES",
"raise_assert_detail",
"raises_chained_assignment_error",
"round_trip_localpath",
"round_trip_pathlib",
"round_trip_pickle",
"setitem",
Expand Down
29 changes: 0 additions & 29 deletions pandas/_testing/_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -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") -> None:
"""
Write data to a compressed file.
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,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}

Expand Down
2 changes: 1 addition & 1 deletion pandas/io/excel/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,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.
Expand Down
8 changes: 4 additions & 4 deletions pandas/io/stata.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,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}
Expand Down Expand Up @@ -2258,7 +2258,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.
Expand Down Expand Up @@ -3208,7 +3208,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.
Expand Down Expand Up @@ -3594,7 +3594,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.
Expand Down
13 changes: 0 additions & 13 deletions pandas/tests/io/excel/test_readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,19 +966,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)
Expand Down
12 changes: 0 additions & 12 deletions pandas/tests/io/excel/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1319,18 +1319,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 = DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=Index(list("ABCD")),
index=Index([f"i-{i}" for i in range(30)]),
)
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(
Expand Down
14 changes: 0 additions & 14 deletions pandas/tests/io/parser/common/test_file_buffer_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,6 @@ def test_path_path_lib(all_parsers):
tm.assert_frame_equal(df, result)


@xfail_pyarrow # AssertionError: DataFrame.index are different
def test_path_local_path(all_parsers):
parser = all_parsers
df = DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=Index(list("ABCD"), dtype=object),
index=Index([f"i-{i}" for i in range(30)], dtype=object),
)
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
Expand Down
20 changes: 0 additions & 20 deletions pandas/tests/io/pytables/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
_maybe_remove,
ensure_clean_store,
)
from pandas.util import _test_decorators as td

from pandas.io.pytables import TableIterator

Expand Down Expand Up @@ -337,25 +336,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, key="df", mode="a")
actual = read_hdf(path_obj, key="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
Expand Down
19 changes: 0 additions & 19 deletions pandas/tests/io/pytables/test_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -958,25 +958,6 @@ def test_pickle_path_localpath():
tm.assert_frame_equal(df, result)


def test_path_localpath_hdfstore():
df = DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=Index(list("ABCD"), dtype=object),
index=Index([f"i-{i}" for i in range(30)], dtype=object),
)

def writer(path):
with HDFStore(path) as store:
df.to_hdf(store, key="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 = DataFrame(
Expand Down
12 changes: 0 additions & 12 deletions pandas/tests/io/sas/test_sas7bdat.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from pandas.compat import IS64
from pandas.errors import EmptyDataError
import pandas.util._test_decorators as td

import pandas as pd
import pandas._testing as tm
Expand Down Expand Up @@ -82,17 +81,6 @@ def test_path_pathlib(self, dirpath, data_test_ix):
df = pd.read_sas(fname, encoding="utf-8")
tm.assert_frame_equal(df, expected)

@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

expected, 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, expected)

@pytest.mark.slow
@pytest.mark.parametrize("chunksize", (3, 5, 10, 11))
@pytest.mark.parametrize("k", range(1, 17))
Expand Down
21 changes: 1 addition & 20 deletions pandas/tests/io/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import pytest

from pandas.compat import is_platform_windows
import pandas.util._test_decorators as td

import pandas as pd
import pandas._testing as tm
Expand All @@ -41,16 +40,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__))


Expand Down Expand Up @@ -86,13 +75,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)
Expand All @@ -105,7 +87,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)
Expand All @@ -114,7 +96,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:
Expand Down
9 changes: 0 additions & 9 deletions pandas/tests/io/test_feather.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,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 = pd.DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=pd.Index(list("ABCD"), dtype=object),
index=pd.Index([f"i-{i}" for i in range(30)], dtype=object),
).reset_index()
result = tm.round_trip_localpath(df.to_feather, read_feather)
tm.assert_frame_equal(df, result)

def test_passthrough_keywords(self):
df = pd.DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
Expand Down
10 changes: 0 additions & 10 deletions pandas/tests/io/test_pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,6 @@ def test_pickle_path_pathlib():
tm.assert_frame_equal(df, result)


def test_pickle_path_localpath():
df = DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=Index(list("ABCD"), dtype=object),
index=Index([f"i-{i}" for i in range(30)], dtype=object),
)
result = tm.round_trip_localpath(df.to_pickle, pd.read_pickle)
tm.assert_frame_equal(df, result)


# ---------------------
# test pickle compression
# ---------------------
Expand Down
11 changes: 0 additions & 11 deletions pandas/tests/io/test_stata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1546,17 +1546,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 = DataFrame(
1.1 * np.arange(120).reshape((30, 4)),
columns=pd.Index(list("ABCD"), dtype=object),
index=pd.Index([f"i-{i}" for i in range(30)], dtype=object),
)
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
Expand Down
Loading