Some py.path.local -> pathlib.Path
This commit is contained in:
parent
cb8142b8ec
commit
2cb34a99cb
|
@ -27,8 +27,6 @@ from typing import Tuple
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
import py
|
||||
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest._version import version
|
||||
from _pytest.assertion import util
|
||||
|
@ -37,6 +35,7 @@ from _pytest.assertion.util import ( # noqa: F401
|
|||
)
|
||||
from _pytest.config import Config
|
||||
from _pytest.main import Session
|
||||
from _pytest.pathlib import absolutepath
|
||||
from _pytest.pathlib import fnmatch_ex
|
||||
from _pytest.store import StoreKey
|
||||
|
||||
|
@ -215,7 +214,7 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader)
|
|||
return True
|
||||
|
||||
if self.session is not None:
|
||||
if self.session.isinitpath(py.path.local(fn)):
|
||||
if self.session.isinitpath(absolutepath(fn)):
|
||||
state.trace(f"matched test file (was specified on cmdline): {fn!r}")
|
||||
return True
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from gettext import gettext
|
||||
|
@ -14,8 +15,6 @@ from typing import Tuple
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
import py
|
||||
|
||||
import _pytest._io
|
||||
from _pytest.compat import final
|
||||
from _pytest.config.exceptions import UsageError
|
||||
|
@ -97,14 +96,14 @@ class Parser:
|
|||
|
||||
def parse(
|
||||
self,
|
||||
args: Sequence[Union[str, py.path.local]],
|
||||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> argparse.Namespace:
|
||||
from _pytest._argcomplete import try_argcomplete
|
||||
|
||||
self.optparser = self._getparser()
|
||||
try_argcomplete(self.optparser)
|
||||
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]
|
||||
strargs = [os.fspath(x) for x in args]
|
||||
return self.optparser.parse_args(strargs, namespace=namespace)
|
||||
|
||||
def _getparser(self) -> "MyOptionParser":
|
||||
|
@ -128,7 +127,7 @@ class Parser:
|
|||
|
||||
def parse_setoption(
|
||||
self,
|
||||
args: Sequence[Union[str, py.path.local]],
|
||||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
option: argparse.Namespace,
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> List[str]:
|
||||
|
@ -139,7 +138,7 @@ class Parser:
|
|||
|
||||
def parse_known_args(
|
||||
self,
|
||||
args: Sequence[Union[str, py.path.local]],
|
||||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> argparse.Namespace:
|
||||
"""Parse and return a namespace object with known arguments at this point."""
|
||||
|
@ -147,13 +146,13 @@ class Parser:
|
|||
|
||||
def parse_known_and_unknown_args(
|
||||
self,
|
||||
args: Sequence[Union[str, py.path.local]],
|
||||
args: Sequence[Union[str, "os.PathLike[str]"]],
|
||||
namespace: Optional[argparse.Namespace] = None,
|
||||
) -> Tuple[argparse.Namespace, List[str]]:
|
||||
"""Parse and return a namespace object with known arguments, and
|
||||
the remaining arguments unknown at this point."""
|
||||
optparser = self._getparser()
|
||||
strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]
|
||||
strargs = [os.fspath(x) for x in args]
|
||||
return optparser.parse_known_args(strargs, namespace=namespace)
|
||||
|
||||
def addini(
|
||||
|
|
|
@ -648,12 +648,13 @@ class FixtureRequest:
|
|||
if has_params:
|
||||
frame = inspect.stack()[3]
|
||||
frameinfo = inspect.getframeinfo(frame[0])
|
||||
source_path = py.path.local(frameinfo.filename)
|
||||
source_path = absolutepath(frameinfo.filename)
|
||||
source_lineno = frameinfo.lineno
|
||||
rel_source_path = source_path.relto(funcitem.config.rootdir)
|
||||
if rel_source_path:
|
||||
source_path_str = rel_source_path
|
||||
else:
|
||||
try:
|
||||
source_path_str = str(
|
||||
source_path.relative_to(funcitem.config.rootpath)
|
||||
)
|
||||
except ValueError:
|
||||
source_path_str = str(source_path)
|
||||
msg = (
|
||||
"The requested fixture has no parameter defined for test:\n"
|
||||
|
@ -876,7 +877,7 @@ class FixtureLookupError(LookupError):
|
|||
class FixtureLookupErrorRepr(TerminalRepr):
|
||||
def __init__(
|
||||
self,
|
||||
filename: Union[str, py.path.local],
|
||||
filename: Union[str, "os.PathLike[str]"],
|
||||
firstlineno: int,
|
||||
tblines: Sequence[str],
|
||||
errorstring: str,
|
||||
|
@ -903,7 +904,7 @@ class FixtureLookupErrorRepr(TerminalRepr):
|
|||
f"{FormattedExcinfo.flow_marker} {line.strip()}", red=True,
|
||||
)
|
||||
tw.line()
|
||||
tw.line("%s:%d" % (self.filename, self.firstlineno + 1))
|
||||
tw.line("%s:%d" % (os.fspath(self.filename), self.firstlineno + 1))
|
||||
|
||||
|
||||
def fail_fixturefunc(fixturefunc, msg: str) -> "NoReturn":
|
||||
|
|
|
@ -467,7 +467,7 @@ class Session(nodes.FSCollector):
|
|||
self.shouldfail: Union[bool, str] = False
|
||||
self.trace = config.trace.root.get("collection")
|
||||
self.startdir = config.invocation_dir
|
||||
self._initialpaths: FrozenSet[py.path.local] = frozenset()
|
||||
self._initialpaths: FrozenSet[Path] = frozenset()
|
||||
|
||||
self._bestrelpathcache: Dict[Path, str] = _bestrelpath_cache(config.rootpath)
|
||||
|
||||
|
@ -510,8 +510,8 @@ class Session(nodes.FSCollector):
|
|||
|
||||
pytest_collectreport = pytest_runtest_logreport
|
||||
|
||||
def isinitpath(self, path: py.path.local) -> bool:
|
||||
return path in self._initialpaths
|
||||
def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool:
|
||||
return Path(path) in self._initialpaths
|
||||
|
||||
def gethookproxy(self, fspath: "os.PathLike[str]"):
|
||||
# Check if we have the common case of running
|
||||
|
@ -601,14 +601,14 @@ class Session(nodes.FSCollector):
|
|||
self.trace.root.indent += 1
|
||||
|
||||
self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = []
|
||||
self._initial_parts: List[Tuple[py.path.local, List[str]]] = []
|
||||
self._initial_parts: List[Tuple[Path, List[str]]] = []
|
||||
self.items: List[nodes.Item] = []
|
||||
|
||||
hook = self.config.hook
|
||||
|
||||
items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items
|
||||
try:
|
||||
initialpaths: List[py.path.local] = []
|
||||
initialpaths: List[Path] = []
|
||||
for arg in args:
|
||||
fspath, parts = resolve_collection_argument(
|
||||
self.config.invocation_params.dir,
|
||||
|
@ -669,13 +669,13 @@ class Session(nodes.FSCollector):
|
|||
# No point in finding packages when collecting doctests.
|
||||
if not self.config.getoption("doctestmodules", False):
|
||||
pm = self.config.pluginmanager
|
||||
confcutdir = py.path.local(pm._confcutdir) if pm._confcutdir else None
|
||||
for parent in reversed(argpath.parts()):
|
||||
if confcutdir and confcutdir.relto(parent):
|
||||
confcutdir = pm._confcutdir
|
||||
for parent in (argpath, *argpath.parents):
|
||||
if confcutdir and parent in confcutdir.parents:
|
||||
break
|
||||
|
||||
if parent.isdir():
|
||||
pkginit = parent.join("__init__.py")
|
||||
if parent.is_dir():
|
||||
pkginit = py.path.local(parent / "__init__.py")
|
||||
if pkginit.isfile() and pkginit not in node_cache1:
|
||||
col = self._collectfile(pkginit, handle_dupes=False)
|
||||
if col:
|
||||
|
@ -685,7 +685,7 @@ class Session(nodes.FSCollector):
|
|||
|
||||
# If it's a directory argument, recurse and look for any Subpackages.
|
||||
# Let the Package collector deal with subnodes, don't collect here.
|
||||
if argpath.check(dir=1):
|
||||
if argpath.is_dir():
|
||||
assert not names, "invalid arg {!r}".format((argpath, names))
|
||||
|
||||
seen_dirs: Set[py.path.local] = set()
|
||||
|
@ -717,15 +717,16 @@ class Session(nodes.FSCollector):
|
|||
node_cache2[key] = x
|
||||
yield x
|
||||
else:
|
||||
assert argpath.check(file=1)
|
||||
assert argpath.is_file()
|
||||
|
||||
if argpath in node_cache1:
|
||||
col = node_cache1[argpath]
|
||||
argpath_ = py.path.local(argpath)
|
||||
if argpath_ in node_cache1:
|
||||
col = node_cache1[argpath_]
|
||||
else:
|
||||
collect_root = pkg_roots.get(argpath.dirname, self)
|
||||
col = collect_root._collectfile(argpath, handle_dupes=False)
|
||||
collect_root = pkg_roots.get(argpath_.dirname, self)
|
||||
col = collect_root._collectfile(argpath_, handle_dupes=False)
|
||||
if col:
|
||||
node_cache1[argpath] = col
|
||||
node_cache1[argpath_] = col
|
||||
|
||||
matching = []
|
||||
work: List[
|
||||
|
@ -782,9 +783,7 @@ class Session(nodes.FSCollector):
|
|||
# first yielded item will be the __init__ Module itself, so
|
||||
# just use that. If this special case isn't taken, then all the
|
||||
# files in the package will be yielded.
|
||||
if argpath.basename == "__init__.py" and isinstance(
|
||||
matching[0], Package
|
||||
):
|
||||
if argpath.name == "__init__.py" and isinstance(matching[0], Package):
|
||||
try:
|
||||
yield next(iter(matching[0].collect()))
|
||||
except StopIteration:
|
||||
|
@ -833,7 +832,7 @@ def search_pypath(module_name: str) -> str:
|
|||
|
||||
def resolve_collection_argument(
|
||||
invocation_path: Path, arg: str, *, as_pypath: bool = False
|
||||
) -> Tuple[py.path.local, List[str]]:
|
||||
) -> Tuple[Path, List[str]]:
|
||||
"""Parse path arguments optionally containing selection parts and return (fspath, names).
|
||||
|
||||
Command-line arguments can point to files and/or directories, and optionally contain
|
||||
|
@ -875,4 +874,4 @@ def resolve_collection_argument(
|
|||
else "directory argument cannot contain :: selection parts: {arg}"
|
||||
)
|
||||
raise UsageError(msg.format(arg=arg))
|
||||
return py.path.local(str(fspath)), parts
|
||||
return fspath, parts
|
||||
|
|
|
@ -4,7 +4,6 @@ import re
|
|||
import sys
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Generator
|
||||
from typing import List
|
||||
|
@ -325,20 +324,14 @@ class MonkeyPatch:
|
|||
|
||||
invalidate_caches()
|
||||
|
||||
def chdir(self, path) -> None:
|
||||
def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None:
|
||||
"""Change the current working directory to the specified path.
|
||||
|
||||
Path can be a string or a py.path.local object.
|
||||
Path can be a string or a path object.
|
||||
"""
|
||||
if self._cwd is None:
|
||||
self._cwd = os.getcwd()
|
||||
if hasattr(path, "chdir"):
|
||||
path.chdir()
|
||||
elif isinstance(path, Path):
|
||||
# Modern python uses the fspath protocol here LEGACY
|
||||
os.chdir(str(path))
|
||||
else:
|
||||
os.chdir(path)
|
||||
os.chdir(path)
|
||||
|
||||
def undo(self) -> None:
|
||||
"""Undo previous changes.
|
||||
|
|
|
@ -480,10 +480,14 @@ class Collector(Node):
|
|||
excinfo.traceback = ntraceback.filter()
|
||||
|
||||
|
||||
def _check_initialpaths_for_relpath(session, fspath):
|
||||
def _check_initialpaths_for_relpath(
|
||||
session: "Session", fspath: py.path.local
|
||||
) -> Optional[str]:
|
||||
for initial_path in session._initialpaths:
|
||||
if fspath.common(initial_path) == initial_path:
|
||||
return fspath.relto(initial_path)
|
||||
initial_path_ = py.path.local(initial_path)
|
||||
if fspath.common(initial_path_) == initial_path_:
|
||||
return fspath.relto(initial_path_)
|
||||
return None
|
||||
|
||||
|
||||
class FSCollector(Collector):
|
||||
|
|
|
@ -30,8 +30,6 @@ from typing import Set
|
|||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
import py
|
||||
|
||||
from _pytest.compat import assert_never
|
||||
from _pytest.outcomes import skip
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
@ -456,7 +454,7 @@ class ImportPathMismatchError(ImportError):
|
|||
|
||||
|
||||
def import_path(
|
||||
p: Union[str, py.path.local, Path],
|
||||
p: Union[str, "os.PathLike[str]"],
|
||||
*,
|
||||
mode: Union[str, ImportMode] = ImportMode.prepend,
|
||||
) -> ModuleType:
|
||||
|
@ -482,7 +480,7 @@ def import_path(
|
|||
"""
|
||||
mode = ImportMode(mode)
|
||||
|
||||
path = Path(str(p))
|
||||
path = Path(p)
|
||||
|
||||
if not path.exists():
|
||||
raise ImportError(path)
|
||||
|
|
|
@ -17,8 +17,6 @@ from typing import Mapping
|
|||
from typing import Optional
|
||||
from typing import Set
|
||||
|
||||
import py
|
||||
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from _pytest.assertion import util
|
||||
|
@ -1311,7 +1309,7 @@ class TestEarlyRewriteBailout:
|
|||
import importlib.machinery
|
||||
|
||||
self.find_spec_calls: List[str] = []
|
||||
self.initial_paths: Set[py.path.local] = set()
|
||||
self.initial_paths: Set[Path] = set()
|
||||
|
||||
class StubSession:
|
||||
_initialpaths = self.initial_paths
|
||||
|
@ -1346,7 +1344,7 @@ class TestEarlyRewriteBailout:
|
|||
pytester.makepyfile(test_foo="def test_foo(): pass")
|
||||
pytester.makepyfile(bar="def bar(): pass")
|
||||
foobar_path = pytester.makepyfile(foobar="def foobar(): pass")
|
||||
self.initial_paths.add(py.path.local(foobar_path))
|
||||
self.initial_paths.add(foobar_path)
|
||||
|
||||
# conftest files should always be rewritten
|
||||
assert hook.find_spec("conftest") is not None
|
||||
|
|
|
@ -4,13 +4,12 @@ import re
|
|||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import py.path
|
||||
|
||||
import pytest
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config import UsageError
|
||||
from _pytest.main import resolve_collection_argument
|
||||
from _pytest.main import validate_basetemp
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.pytester import Testdir
|
||||
|
||||
|
||||
|
@ -109,40 +108,37 @@ def test_validate_basetemp_integration(testdir):
|
|||
|
||||
class TestResolveCollectionArgument:
|
||||
@pytest.fixture
|
||||
def invocation_dir(self, testdir: Testdir) -> py.path.local:
|
||||
testdir.syspathinsert(str(testdir.tmpdir / "src"))
|
||||
testdir.chdir()
|
||||
def invocation_path(self, pytester: Pytester) -> Path:
|
||||
pytester.syspathinsert(pytester.path / "src")
|
||||
pytester.chdir()
|
||||
|
||||
pkg = testdir.tmpdir.join("src/pkg").ensure_dir()
|
||||
pkg.join("__init__.py").ensure()
|
||||
pkg.join("test.py").ensure()
|
||||
return testdir.tmpdir
|
||||
pkg = pytester.path.joinpath("src/pkg")
|
||||
pkg.mkdir(parents=True)
|
||||
pkg.joinpath("__init__.py").touch()
|
||||
pkg.joinpath("test.py").touch()
|
||||
return pytester.path
|
||||
|
||||
@pytest.fixture
|
||||
def invocation_path(self, invocation_dir: py.path.local) -> Path:
|
||||
return Path(str(invocation_dir))
|
||||
|
||||
def test_file(self, invocation_dir: py.path.local, invocation_path: Path) -> None:
|
||||
def test_file(self, invocation_path: Path) -> None:
|
||||
"""File and parts."""
|
||||
assert resolve_collection_argument(invocation_path, "src/pkg/test.py") == (
|
||||
invocation_dir / "src/pkg/test.py",
|
||||
invocation_path / "src/pkg/test.py",
|
||||
[],
|
||||
)
|
||||
assert resolve_collection_argument(invocation_path, "src/pkg/test.py::") == (
|
||||
invocation_dir / "src/pkg/test.py",
|
||||
invocation_path / "src/pkg/test.py",
|
||||
[""],
|
||||
)
|
||||
assert resolve_collection_argument(
|
||||
invocation_path, "src/pkg/test.py::foo::bar"
|
||||
) == (invocation_dir / "src/pkg/test.py", ["foo", "bar"])
|
||||
) == (invocation_path / "src/pkg/test.py", ["foo", "bar"])
|
||||
assert resolve_collection_argument(
|
||||
invocation_path, "src/pkg/test.py::foo::bar::"
|
||||
) == (invocation_dir / "src/pkg/test.py", ["foo", "bar", ""])
|
||||
) == (invocation_path / "src/pkg/test.py", ["foo", "bar", ""])
|
||||
|
||||
def test_dir(self, invocation_dir: py.path.local, invocation_path: Path) -> None:
|
||||
def test_dir(self, invocation_path: Path) -> None:
|
||||
"""Directory and parts."""
|
||||
assert resolve_collection_argument(invocation_path, "src/pkg") == (
|
||||
invocation_dir / "src/pkg",
|
||||
invocation_path / "src/pkg",
|
||||
[],
|
||||
)
|
||||
|
||||
|
@ -156,16 +152,16 @@ class TestResolveCollectionArgument:
|
|||
):
|
||||
resolve_collection_argument(invocation_path, "src/pkg::foo::bar")
|
||||
|
||||
def test_pypath(self, invocation_dir: py.path.local, invocation_path: Path) -> None:
|
||||
def test_pypath(self, invocation_path: Path) -> None:
|
||||
"""Dotted name and parts."""
|
||||
assert resolve_collection_argument(
|
||||
invocation_path, "pkg.test", as_pypath=True
|
||||
) == (invocation_dir / "src/pkg/test.py", [])
|
||||
) == (invocation_path / "src/pkg/test.py", [])
|
||||
assert resolve_collection_argument(
|
||||
invocation_path, "pkg.test::foo::bar", as_pypath=True
|
||||
) == (invocation_dir / "src/pkg/test.py", ["foo", "bar"])
|
||||
) == (invocation_path / "src/pkg/test.py", ["foo", "bar"])
|
||||
assert resolve_collection_argument(invocation_path, "pkg", as_pypath=True) == (
|
||||
invocation_dir / "src/pkg",
|
||||
invocation_path / "src/pkg",
|
||||
[],
|
||||
)
|
||||
|
||||
|
@ -191,13 +187,11 @@ class TestResolveCollectionArgument:
|
|||
):
|
||||
resolve_collection_argument(invocation_path, "foobar", as_pypath=True)
|
||||
|
||||
def test_absolute_paths_are_resolved_correctly(
|
||||
self, invocation_dir: py.path.local, invocation_path: Path
|
||||
) -> None:
|
||||
def test_absolute_paths_are_resolved_correctly(self, invocation_path: Path) -> None:
|
||||
"""Absolute paths resolve back to absolute paths."""
|
||||
full_path = str(invocation_dir / "src")
|
||||
full_path = str(invocation_path / "src")
|
||||
assert resolve_collection_argument(invocation_path, full_path) == (
|
||||
py.path.local(os.path.abspath("src")),
|
||||
Path(os.path.abspath("src")),
|
||||
[],
|
||||
)
|
||||
|
||||
|
@ -206,7 +200,7 @@ class TestResolveCollectionArgument:
|
|||
drive, full_path_without_drive = os.path.splitdrive(full_path)
|
||||
assert resolve_collection_argument(
|
||||
invocation_path, full_path_without_drive
|
||||
) == (py.path.local(os.path.abspath("src")), [])
|
||||
) == (Path(os.path.abspath("src")), [])
|
||||
|
||||
|
||||
def test_module_full_path_without_drive(testdir):
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from typing import cast
|
||||
from typing import List
|
||||
from typing import Type
|
||||
|
||||
|
@ -73,17 +74,21 @@ def test__check_initialpaths_for_relpath() -> None:
|
|||
class FakeSession1:
|
||||
_initialpaths = [cwd]
|
||||
|
||||
assert nodes._check_initialpaths_for_relpath(FakeSession1, cwd) == ""
|
||||
session = cast(pytest.Session, FakeSession1)
|
||||
|
||||
assert nodes._check_initialpaths_for_relpath(session, cwd) == ""
|
||||
|
||||
sub = cwd.join("file")
|
||||
|
||||
class FakeSession2:
|
||||
_initialpaths = [cwd]
|
||||
|
||||
assert nodes._check_initialpaths_for_relpath(FakeSession2, sub) == "file"
|
||||
session = cast(pytest.Session, FakeSession2)
|
||||
|
||||
assert nodes._check_initialpaths_for_relpath(session, sub) == "file"
|
||||
|
||||
outside = py.path.local("/outside")
|
||||
assert nodes._check_initialpaths_for_relpath(FakeSession2, outside) is None
|
||||
assert nodes._check_initialpaths_for_relpath(session, outside) is None
|
||||
|
||||
|
||||
def test_failure_with_changed_cwd(pytester: Pytester) -> None:
|
||||
|
|
Loading…
Reference in New Issue