Skip to content

Commit 1620b3d

Browse files
committed
Some py.path.local -> pathlib.Path
1 parent cb8142b commit 1620b3d

File tree

9 files changed

+81
-87
lines changed

9 files changed

+81
-87
lines changed

src/_pytest/assertion/rewrite.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
from typing import TYPE_CHECKING
2828
from typing import Union
2929

30-
import py
31-
3230
from _pytest._io.saferepr import saferepr
3331
from _pytest._version import version
3432
from _pytest.assertion import util
@@ -215,7 +213,7 @@ def _should_rewrite(self, name: str, fn: str, state: "AssertionState") -> bool:
215213
return True
216214

217215
if self.session is not None:
218-
if self.session.isinitpath(py.path.local(fn)):
216+
if self.session.isinitpath(fn):
219217
state.trace(f"matched test file (was specified on cmdline): {fn!r}")
220218
return True
221219

src/_pytest/config/argparsing.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import argparse
2+
import os
23
import sys
34
import warnings
45
from gettext import gettext
@@ -14,8 +15,6 @@
1415
from typing import TYPE_CHECKING
1516
from typing import Union
1617

17-
import py
18-
1918
import _pytest._io
2019
from _pytest.compat import final
2120
from _pytest.config.exceptions import UsageError
@@ -97,14 +96,14 @@ def addoption(self, *opts: str, **attrs: Any) -> None:
9796

9897
def parse(
9998
self,
100-
args: Sequence[Union[str, py.path.local]],
99+
args: Sequence[Union[str, "os.PathLike[str]"]],
101100
namespace: Optional[argparse.Namespace] = None,
102101
) -> argparse.Namespace:
103102
from _pytest._argcomplete import try_argcomplete
104103

105104
self.optparser = self._getparser()
106105
try_argcomplete(self.optparser)
107-
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]
106+
strargs = [os.fspath(x) for x in args]
108107
return self.optparser.parse_args(strargs, namespace=namespace)
109108

110109
def _getparser(self) -> "MyOptionParser":
@@ -128,7 +127,7 @@ def _getparser(self) -> "MyOptionParser":
128127

129128
def parse_setoption(
130129
self,
131-
args: Sequence[Union[str, py.path.local]],
130+
args: Sequence[Union[str, "os.PathLike[str]"]],
132131
option: argparse.Namespace,
133132
namespace: Optional[argparse.Namespace] = None,
134133
) -> List[str]:
@@ -139,21 +138,21 @@ def parse_setoption(
139138

140139
def parse_known_args(
141140
self,
142-
args: Sequence[Union[str, py.path.local]],
141+
args: Sequence[Union[str, "os.PathLike[str]"]],
143142
namespace: Optional[argparse.Namespace] = None,
144143
) -> argparse.Namespace:
145144
"""Parse and return a namespace object with known arguments at this point."""
146145
return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
147146

148147
def parse_known_and_unknown_args(
149148
self,
150-
args: Sequence[Union[str, py.path.local]],
149+
args: Sequence[Union[str, "os.PathLike[str]"]],
151150
namespace: Optional[argparse.Namespace] = None,
152151
) -> Tuple[argparse.Namespace, List[str]]:
153152
"""Parse and return a namespace object with known arguments, and
154153
the remaining arguments unknown at this point."""
155154
optparser = self._getparser()
156-
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]
155+
strargs = [os.fspath(x) for x in args]
157156
return optparser.parse_known_args(strargs, namespace=namespace)
158157

159158
def addini(

src/_pytest/fixtures.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -648,12 +648,13 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None:
648648
if has_params:
649649
frame = inspect.stack()[3]
650650
frameinfo = inspect.getframeinfo(frame[0])
651-
source_path = py.path.local(frameinfo.filename)
651+
source_path = absolutepath(frameinfo.filename)
652652
source_lineno = frameinfo.lineno
653-
rel_source_path = source_path.relto(funcitem.config.rootdir)
654-
if rel_source_path:
655-
source_path_str = rel_source_path
656-
else:
653+
try:
654+
source_path_str = str(
655+
source_path.relative_to(funcitem.config.rootpath)
656+
)
657+
except ValueError:
657658
source_path_str = str(source_path)
658659
msg = (
659660
"The requested fixture has no parameter defined for test:\n"
@@ -876,7 +877,7 @@ def formatrepr(self) -> "FixtureLookupErrorRepr":
876877
class FixtureLookupErrorRepr(TerminalRepr):
877878
def __init__(
878879
self,
879-
filename: Union[str, py.path.local],
880+
filename: Union[str, "os.PathLike[str]"],
880881
firstlineno: int,
881882
tblines: Sequence[str],
882883
errorstring: str,
@@ -903,7 +904,7 @@ def toterminal(self, tw: TerminalWriter) -> None:
903904
f"{FormattedExcinfo.flow_marker} {line.strip()}", red=True,
904905
)
905906
tw.line()
906-
tw.line("%s:%d" % (self.filename, self.firstlineno + 1))
907+
tw.line("%s:%d" % (os.fspath(self.filename), self.firstlineno + 1))
907908

908909

909910
def fail_fixturefunc(fixturefunc, msg: str) -> "NoReturn":

src/_pytest/main.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ def __init__(self, config: Config) -> None:
467467
self.shouldfail: Union[bool, str] = False
468468
self.trace = config.trace.root.get("collection")
469469
self.startdir = config.invocation_dir
470-
self._initialpaths: FrozenSet[py.path.local] = frozenset()
470+
self._initialpaths: FrozenSet[Path] = frozenset()
471471

472472
self._bestrelpathcache: Dict[Path, str] = _bestrelpath_cache(config.rootpath)
473473

@@ -510,8 +510,8 @@ def pytest_runtest_logreport(
510510

511511
pytest_collectreport = pytest_runtest_logreport
512512

513-
def isinitpath(self, path: py.path.local) -> bool:
514-
return path in self._initialpaths
513+
def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool:
514+
return Path(path) in self._initialpaths
515515

516516
def gethookproxy(self, fspath: "os.PathLike[str]"):
517517
# Check if we have the common case of running
@@ -601,14 +601,14 @@ def perform_collect(
601601
self.trace.root.indent += 1
602602

603603
self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = []
604-
self._initial_parts: List[Tuple[py.path.local, List[str]]] = []
604+
self._initial_parts: List[Tuple[Path, List[str]]] = []
605605
self.items: List[nodes.Item] = []
606606

607607
hook = self.config.hook
608608

609609
items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items
610610
try:
611-
initialpaths: List[py.path.local] = []
611+
initialpaths: List[Path] = []
612612
for arg in args:
613613
fspath, parts = resolve_collection_argument(
614614
self.config.invocation_params.dir,
@@ -669,13 +669,13 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
669669
# No point in finding packages when collecting doctests.
670670
if not self.config.getoption("doctestmodules", False):
671671
pm = self.config.pluginmanager
672-
confcutdir = py.path.local(pm._confcutdir) if pm._confcutdir else None
673-
for parent in reversed(argpath.parts()):
674-
if confcutdir and confcutdir.relto(parent):
672+
confcutdir = pm._confcutdir
673+
for parent in (argpath, *argpath.parents):
674+
if confcutdir and parent in confcutdir.parents:
675675
break
676676

677-
if parent.isdir():
678-
pkginit = parent.join("__init__.py")
677+
if parent.is_dir():
678+
pkginit = py.path.local(parent / "__init__.py")
679679
if pkginit.isfile() and pkginit not in node_cache1:
680680
col = self._collectfile(pkginit, handle_dupes=False)
681681
if col:
@@ -685,7 +685,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
685685

686686
# If it's a directory argument, recurse and look for any Subpackages.
687687
# Let the Package collector deal with subnodes, don't collect here.
688-
if argpath.check(dir=1):
688+
if argpath.is_dir():
689689
assert not names, "invalid arg {!r}".format((argpath, names))
690690

691691
seen_dirs: Set[py.path.local] = set()
@@ -717,15 +717,16 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
717717
node_cache2[key] = x
718718
yield x
719719
else:
720-
assert argpath.check(file=1)
720+
assert argpath.is_file()
721721

722-
if argpath in node_cache1:
723-
col = node_cache1[argpath]
722+
argpath_ = py.path.local(argpath)
723+
if argpath_ in node_cache1:
724+
col = node_cache1[argpath_]
724725
else:
725-
collect_root = pkg_roots.get(argpath.dirname, self)
726-
col = collect_root._collectfile(argpath, handle_dupes=False)
726+
collect_root = pkg_roots.get(argpath_.dirname, self)
727+
col = collect_root._collectfile(argpath_, handle_dupes=False)
727728
if col:
728-
node_cache1[argpath] = col
729+
node_cache1[argpath_] = col
729730

730731
matching = []
731732
work: List[
@@ -782,9 +783,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
782783
# first yielded item will be the __init__ Module itself, so
783784
# just use that. If this special case isn't taken, then all the
784785
# files in the package will be yielded.
785-
if argpath.basename == "__init__.py" and isinstance(
786-
matching[0], Package
787-
):
786+
if argpath.name == "__init__.py" and isinstance(matching[0], Package):
788787
try:
789788
yield next(iter(matching[0].collect()))
790789
except StopIteration:
@@ -833,7 +832,7 @@ def search_pypath(module_name: str) -> str:
833832

834833
def resolve_collection_argument(
835834
invocation_path: Path, arg: str, *, as_pypath: bool = False
836-
) -> Tuple[py.path.local, List[str]]:
835+
) -> Tuple[Path, List[str]]:
837836
"""Parse path arguments optionally containing selection parts and return (fspath, names).
838837
839838
Command-line arguments can point to files and/or directories, and optionally contain
@@ -875,4 +874,4 @@ def resolve_collection_argument(
875874
else "directory argument cannot contain :: selection parts: {arg}"
876875
)
877876
raise UsageError(msg.format(arg=arg))
878-
return py.path.local(str(fspath)), parts
877+
return fspath, parts

src/_pytest/monkeypatch.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import sys
55
import warnings
66
from contextlib import contextmanager
7-
from pathlib import Path
87
from typing import Any
98
from typing import Generator
109
from typing import List
@@ -325,18 +324,15 @@ def syspath_prepend(self, path) -> None:
325324

326325
invalidate_caches()
327326

328-
def chdir(self, path) -> None:
327+
def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None:
329328
"""Change the current working directory to the specified path.
330329
331-
Path can be a string or a py.path.local object.
330+
Path can be a string or a path object.
332331
"""
333332
if self._cwd is None:
334333
self._cwd = os.getcwd()
335334
if hasattr(path, "chdir"):
336-
path.chdir()
337-
elif isinstance(path, Path):
338-
# Modern python uses the fspath protocol here LEGACY
339-
os.chdir(str(path))
335+
path.chdir() # type: ignore[union-attr]
340336
else:
341337
os.chdir(path)
342338

src/_pytest/nodes.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,14 @@ def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
480480
excinfo.traceback = ntraceback.filter()
481481

482482

483-
def _check_initialpaths_for_relpath(session, fspath):
483+
def _check_initialpaths_for_relpath(
484+
session: "Session", fspath: py.path.local
485+
) -> Optional[str]:
484486
for initial_path in session._initialpaths:
485-
if fspath.common(initial_path) == initial_path:
486-
return fspath.relto(initial_path)
487+
initial_path_ = py.path.local(initial_path)
488+
if fspath.common(initial_path_) == initial_path_:
489+
return fspath.relto(initial_path_)
490+
return None
487491

488492

489493
class FSCollector(Collector):

src/_pytest/pathlib.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
from typing import TypeVar
3131
from typing import Union
3232

33-
import py
34-
3533
from _pytest.compat import assert_never
3634
from _pytest.outcomes import skip
3735
from _pytest.warning_types import PytestWarning
@@ -456,7 +454,7 @@ class ImportPathMismatchError(ImportError):
456454

457455

458456
def import_path(
459-
p: Union[str, py.path.local, Path],
457+
p: Union[str, "os.PathLike[str]"],
460458
*,
461459
mode: Union[str, ImportMode] = ImportMode.prepend,
462460
) -> ModuleType:
@@ -482,7 +480,7 @@ def import_path(
482480
"""
483481
mode = ImportMode(mode)
484482

485-
path = Path(str(p))
483+
path = Path(p)
486484

487485
if not path.exists():
488486
raise ImportError(path)

0 commit comments

Comments
 (0)