Skip to content

Commit 77cb110

Browse files
drop usage of py.path.local calls
Co-authored-by: Bruno Oliveira <[email protected]>
1 parent 22dad53 commit 77cb110

20 files changed

+138
-131
lines changed

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ repos:
8787
xml\.
8888
)
8989
types: [python]
90+
- id: py-path-deprecated
91+
name: py.path usage is deprecated
92+
language: pygrep
93+
entry: \bpy\.path\.local
94+
exclude: docs
95+
types: [python]

src/_pytest/_code/code.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
import attr
3333
import pluggy
34-
import py
3534

3635
import _pytest
3736
from _pytest._code.source import findsource
@@ -1230,7 +1229,7 @@ def getfslineno(obj: object) -> Tuple[Union[str, Path], int]:
12301229
if _PLUGGY_DIR.name == "__init__.py":
12311230
_PLUGGY_DIR = _PLUGGY_DIR.parent
12321231
_PYTEST_DIR = Path(_pytest.__file__).parent
1233-
_PY_DIR = Path(py.__file__).parent
1232+
_PY_DIR = Path(__import__("py").__file__).parent
12341233

12351234

12361235
def filter_traceback(entry: TracebackEntry) -> bool:

src/_pytest/cacheprovider.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
from typing import Union
1414

1515
import attr
16-
import py
1716

1817
from .pathlib import resolve_from_str
1918
from .pathlib import rm_rf
2019
from .reports import CollectReport
2120
from _pytest import nodes
2221
from _pytest._io import TerminalWriter
2322
from _pytest.compat import final
23+
from _pytest.compat import LEGACY_PATH
24+
from _pytest.compat import legacy_path
2425
from _pytest.config import Config
2526
from _pytest.config import ExitCode
2627
from _pytest.config import hookimpl
@@ -120,7 +121,7 @@ def warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None:
120121
stacklevel=3,
121122
)
122123

123-
def makedir(self, name: str) -> py.path.local:
124+
def makedir(self, name: str) -> LEGACY_PATH:
124125
"""Return a directory path object with the given name.
125126
126127
If the directory does not yet exist, it will be created. You can use
@@ -137,7 +138,7 @@ def makedir(self, name: str) -> py.path.local:
137138
raise ValueError("name is not allowed to contain path separators")
138139
res = self._cachedir.joinpath(self._CACHE_PREFIX_DIRS, path)
139140
res.mkdir(exist_ok=True, parents=True)
140-
return py.path.local(res)
141+
return legacy_path(res)
141142

142143
def _getvaluepath(self, key: str) -> Path:
143144
return self._cachedir.joinpath(self._CACHE_PREFIX_VALUES, Path(key))

src/_pytest/compat.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@
3232
_T = TypeVar("_T")
3333
_S = TypeVar("_S")
3434

35-
#: constant to prepare valuing py.path.local replacements/lazy proxies later on
35+
#: constant to prepare valuing pylib path replacements/lazy proxies later on
3636
# intended for removal in pytest 8.0 or 9.0
3737

38-
LEGACY_PATH = py.path.local
38+
# fmt: off
39+
# intentional space to create a fake difference for the verification
40+
LEGACY_PATH = py.path. local
41+
# fmt: on
3942

4043

4144
def legacy_path(path: Union[str, "os.PathLike[str]"]) -> LEGACY_PATH:
42-
"""Internal wrapper to prepare lazy proxies for py.path.local instances"""
43-
return py.path.local(path)
45+
"""Internal wrapper to prepare lazy proxies for legacy_path instances"""
46+
return LEGACY_PATH(path)
4447

4548

4649
# fmt: off

src/_pytest/config/__init__.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from typing import Union
3333

3434
import attr
35-
import py
3635
from pluggy import HookimplMarker
3736
from pluggy import HookspecMarker
3837
from pluggy import PluginManager
@@ -48,6 +47,8 @@
4847
from _pytest._io import TerminalWriter
4948
from _pytest.compat import final
5049
from _pytest.compat import importlib_metadata
50+
from _pytest.compat import LEGACY_PATH
51+
from _pytest.compat import legacy_path
5152
from _pytest.outcomes import fail
5253
from _pytest.outcomes import Skipped
5354
from _pytest.pathlib import absolutepath
@@ -937,15 +938,15 @@ def __init__(
937938
self.cache: Optional[Cache] = None
938939

939940
@property
940-
def invocation_dir(self) -> py.path.local:
941+
def invocation_dir(self) -> LEGACY_PATH:
941942
"""The directory from which pytest was invoked.
942943
943944
Prefer to use :attr:`invocation_params.dir <InvocationParams.dir>`,
944945
which is a :class:`pathlib.Path`.
945946
946-
:type: py.path.local
947+
:type: LEGACY_PATH
947948
"""
948-
return py.path.local(str(self.invocation_params.dir))
949+
return legacy_path(str(self.invocation_params.dir))
949950

950951
@property
951952
def rootpath(self) -> Path:
@@ -958,14 +959,14 @@ def rootpath(self) -> Path:
958959
return self._rootpath
959960

960961
@property
961-
def rootdir(self) -> py.path.local:
962+
def rootdir(self) -> LEGACY_PATH:
962963
"""The path to the :ref:`rootdir <rootdir>`.
963964
964965
Prefer to use :attr:`rootpath`, which is a :class:`pathlib.Path`.
965966
966-
:type: py.path.local
967+
:type: LEGACY_PATH
967968
"""
968-
return py.path.local(str(self.rootpath))
969+
return legacy_path(str(self.rootpath))
969970

970971
@property
971972
def inipath(self) -> Optional[Path]:
@@ -978,14 +979,14 @@ def inipath(self) -> Optional[Path]:
978979
return self._inipath
979980

980981
@property
981-
def inifile(self) -> Optional[py.path.local]:
982+
def inifile(self) -> Optional[LEGACY_PATH]:
982983
"""The path to the :ref:`configfile <configfiles>`.
983984
984985
Prefer to use :attr:`inipath`, which is a :class:`pathlib.Path`.
985986
986-
:type: Optional[py.path.local]
987+
:type: Optional[LEGACY_PATH]
987988
"""
988-
return py.path.local(str(self.inipath)) if self.inipath else None
989+
return legacy_path(str(self.inipath)) if self.inipath else None
989990

990991
def add_cleanup(self, func: Callable[[], None]) -> None:
991992
"""Add a function to be called when the config object gets out of
@@ -1420,7 +1421,7 @@ def _getini(self, name: str):
14201421
assert self.inipath is not None
14211422
dp = self.inipath.parent
14221423
input_values = shlex.split(value) if isinstance(value, str) else value
1423-
return [py.path.local(str(dp / x)) for x in input_values]
1424+
return [legacy_path(str(dp / x)) for x in input_values]
14241425
elif type == "args":
14251426
return shlex.split(value) if isinstance(value, str) else value
14261427
elif type == "linelist":
@@ -1446,7 +1447,7 @@ def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]:
14461447
for relroot in relroots:
14471448
if isinstance(relroot, Path):
14481449
pass
1449-
elif isinstance(relroot, py.path.local):
1450+
elif isinstance(relroot, LEGACY_PATH):
14501451
relroot = Path(relroot)
14511452
else:
14521453
relroot = relroot.replace("/", os.sep)

src/_pytest/deprecated.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
NODE_FSPATH = UnformattedWarning(
9393
PytestDeprecationWarning,
9494
"{type}.fspath is deprecated and will be replaced by {type}.path.\n"
95-
"see TODO;URL for details on replacing py.path.local with pathlib.Path",
95+
"see https://docs.pytest.org/en/latest/deprecations.html#node-fspath-in-favor-of-pathlib-and-node-path",
9696
)
9797

9898
# You want to make some `__init__` or function "private".

src/_pytest/doctest.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@
2222
from typing import TYPE_CHECKING
2323
from typing import Union
2424

25-
import py.path
26-
2725
import pytest
2826
from _pytest import outcomes
2927
from _pytest._code.code import ExceptionInfo
3028
from _pytest._code.code import ReprFileLocation
3129
from _pytest._code.code import TerminalRepr
3230
from _pytest._io import TerminalWriter
31+
from _pytest.compat import LEGACY_PATH
3332
from _pytest.compat import legacy_path
3433
from _pytest.compat import safe_getattr
3534
from _pytest.config import Config
@@ -123,7 +122,7 @@ def pytest_unconfigure() -> None:
123122

124123
def pytest_collect_file(
125124
fspath: Path,
126-
path: py.path.local,
125+
path: LEGACY_PATH,
127126
parent: Collector,
128127
) -> Optional[Union["DoctestModule", "DoctestTextfile"]]:
129128
config = parent.config

src/_pytest/hookspec.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from typing import TYPE_CHECKING
1212
from typing import Union
1313

14-
import py.path
1514
from pluggy import HookspecMarker
1615

1716
from _pytest.deprecated import WARNING_CAPTURED_HOOK
@@ -42,6 +41,7 @@
4241
from _pytest.reports import TestReport
4342
from _pytest.runner import CallInfo
4443
from _pytest.terminal import TerminalReporter
44+
from _pytest.compat import LEGACY_PATH
4545

4646

4747
hookspec = HookspecMarker("pytest")
@@ -263,7 +263,7 @@ def pytest_collection_finish(session: "Session") -> None:
263263

264264
@hookspec(firstresult=True)
265265
def pytest_ignore_collect(
266-
fspath: Path, path: py.path.local, config: "Config"
266+
fspath: Path, path: "LEGACY_PATH", config: "Config"
267267
) -> Optional[bool]:
268268
"""Return True to prevent considering this path for collection.
269269
@@ -273,7 +273,7 @@ def pytest_ignore_collect(
273273
Stops at first non-None result, see :ref:`firstresult`.
274274
275275
:param pathlib.Path fspath: The path to analyze.
276-
:param py.path.local path: The path to analyze.
276+
:param LEGACY_PATH path: The path to analyze.
277277
:param _pytest.config.Config config: The pytest config object.
278278
279279
.. versionchanged:: 6.3.0
@@ -283,14 +283,14 @@ def pytest_ignore_collect(
283283

284284

285285
def pytest_collect_file(
286-
fspath: Path, path: py.path.local, parent: "Collector"
286+
fspath: Path, path: "LEGACY_PATH", parent: "Collector"
287287
) -> "Optional[Collector]":
288288
"""Create a Collector for the given path, or None if not relevant.
289289
290290
The new node needs to have the specified ``parent`` as a parent.
291291
292292
:param pathlib.Path fspath: The path to analyze.
293-
:param py.path.local path: The path to collect.
293+
:param LEGACY_PATH path: The path to collect.
294294
295295
.. versionchanged:: 6.3.0
296296
The ``fspath`` parameter was added as a :class:`pathlib.Path`
@@ -335,7 +335,7 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor
335335

336336
@hookspec(firstresult=True)
337337
def pytest_pycollect_makemodule(
338-
fspath: Path, path: py.path.local, parent
338+
fspath: Path, path: "LEGACY_PATH", parent
339339
) -> Optional["Module"]:
340340
"""Return a Module collector or None for the given path.
341341
@@ -346,7 +346,7 @@ def pytest_pycollect_makemodule(
346346
Stops at first non-None result, see :ref:`firstresult`.
347347
348348
:param pathlib.Path fspath: The path of the module to collect.
349-
:param py.path.local path: The path of the module to collect.
349+
:param legacy_path path: The path of the module to collect.
350350
351351
.. versionchanged:: 6.3.0
352352
The ``fspath`` parameter was added as a :class:`pathlib.Path`
@@ -676,13 +676,13 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No
676676

677677

678678
def pytest_report_header(
679-
config: "Config", startpath: Path, startdir: py.path.local
679+
config: "Config", startpath: Path, startdir: "LEGACY_PATH"
680680
) -> Union[str, List[str]]:
681681
"""Return a string or list of strings to be displayed as header info for terminal reporting.
682682
683683
:param _pytest.config.Config config: The pytest config object.
684684
:param Path startpath: The starting dir.
685-
:param py.path.local startdir: The starting dir.
685+
:param LEGACY_PATH startdir: The starting dir.
686686
687687
.. note::
688688
@@ -706,7 +706,7 @@ def pytest_report_header(
706706
def pytest_report_collectionfinish(
707707
config: "Config",
708708
startpath: Path,
709-
startdir: py.path.local,
709+
startdir: "LEGACY_PATH",
710710
items: Sequence["Item"],
711711
) -> Union[str, List[str]]:
712712
"""Return a string or list of strings to be displayed after collection
@@ -718,7 +718,7 @@ def pytest_report_collectionfinish(
718718
719719
:param _pytest.config.Config config: The pytest config object.
720720
:param Path startpath: The starting path.
721-
:param py.path.local startdir: The starting dir.
721+
:param LEGACY_PATH startdir: The starting dir.
722722
:param items: List of pytest items that are going to be executed; this list should not be modified.
723723
724724
.. note::

src/_pytest/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
from typing import Union
2222

2323
import attr
24-
import py
2524

2625
import _pytest._code
2726
from _pytest import nodes
2827
from _pytest.compat import final
28+
from _pytest.compat import legacy_path
2929
from _pytest.config import Config
3030
from _pytest.config import directory_arg
3131
from _pytest.config import ExitCode
@@ -543,7 +543,7 @@ def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
543543
if direntry.name == "__pycache__":
544544
return False
545545
fspath = Path(direntry.path)
546-
path = py.path.local(fspath)
546+
path = legacy_path(fspath)
547547
ihook = self.gethookproxy(fspath.parent)
548548
if ihook.pytest_ignore_collect(fspath=fspath, path=path, config=self.config):
549549
return False
@@ -555,7 +555,7 @@ def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
555555
def _collectfile(
556556
self, fspath: Path, handle_dupes: bool = True
557557
) -> Sequence[nodes.Collector]:
558-
path = py.path.local(fspath)
558+
path = legacy_path(fspath)
559559
assert (
560560
fspath.is_file()
561561
), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(

0 commit comments

Comments
 (0)