Skip to content

Commit 4a4fd0e

Browse files
committed
Replace some usages of config.{rootdir,inifile} with config.{rootpath,inipath}
1 parent 0db263a commit 4a4fd0e

File tree

10 files changed

+116
-99
lines changed

10 files changed

+116
-99
lines changed

src/_pytest/cacheprovider.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def clear_cache(cls, cachedir: Path) -> None:
7878

7979
@staticmethod
8080
def cache_dir_from_config(config: Config) -> Path:
81-
return resolve_from_str(config.getini("cache_dir"), config.rootdir)
81+
return resolve_from_str(config.getini("cache_dir"), config.rootpath)
8282

8383
def warn(self, fmt: str, **args: object) -> None:
8484
import warnings
@@ -264,7 +264,7 @@ def __init__(self, config: Config) -> None:
264264

265265
def get_last_failed_paths(self) -> Set[Path]:
266266
"""Return a set with all Paths()s of the previously failed nodeids."""
267-
rootpath = Path(str(self.config.rootdir))
267+
rootpath = self.config.rootpath
268268
result = {rootpath / nodeid.split("::")[0] for nodeid in self.lastfailed}
269269
return {x for x in result if x.exists()}
270270

@@ -495,7 +495,7 @@ def pytest_report_header(config: Config) -> Optional[str]:
495495
# starting with .., ../.. if sensible
496496

497497
try:
498-
displaypath = cachedir.relative_to(str(config.rootdir))
498+
displaypath = cachedir.relative_to(config.rootpath)
499499
except ValueError:
500500
displaypath = cachedir
501501
return "cachedir: {}".format(displaypath)

src/_pytest/config/__init__.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from _pytest.compat import TYPE_CHECKING
4646
from _pytest.outcomes import fail
4747
from _pytest.outcomes import Skipped
48+
from _pytest.pathlib import bestrelpath
4849
from _pytest.pathlib import import_path
4950
from _pytest.pathlib import ImportMode
5051
from _pytest.pathlib import Path
@@ -1028,9 +1029,9 @@ def notify_exception(
10281029

10291030
def cwd_relative_nodeid(self, nodeid: str) -> str:
10301031
# nodeid's are relative to the rootpath, compute relative to cwd.
1031-
if self.invocation_dir != self.rootdir:
1032-
fullpath = self.rootdir.join(nodeid)
1033-
nodeid = self.invocation_dir.bestrelpath(fullpath)
1032+
if self.invocation_params.dir != self.rootpath:
1033+
fullpath = self.rootpath / nodeid
1034+
nodeid = bestrelpath(self.invocation_params.dir, fullpath)
10341035
return nodeid
10351036

10361037
@classmethod
@@ -1068,8 +1069,8 @@ def _initini(self, args: Sequence[str]) -> None:
10681069
self.rootpath = rootpath
10691070
self.inipath = inipath
10701071
self.inicfg = inicfg
1071-
self._parser.extra_info["rootdir"] = self.rootdir
1072-
self._parser.extra_info["inifile"] = self.inifile
1072+
self._parser.extra_info["rootdir"] = str(self.rootpath)
1073+
self._parser.extra_info["inifile"] = str(self.inipath)
10731074
self._parser.addini("addopts", "extra command line options", "args")
10741075
self._parser.addini("minversion", "minimally required pytest version")
10751076
self._parser.addini(
@@ -1158,9 +1159,8 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None:
11581159
args, namespace=copy.copy(self.option)
11591160
)
11601161
self._validate_plugins()
1161-
if self.known_args_namespace.confcutdir is None and self.inifile:
1162-
confcutdir = py.path.local(self.inifile).dirname
1163-
self.known_args_namespace.confcutdir = confcutdir
1162+
if self.known_args_namespace.confcutdir is None and self.inipath:
1163+
self.known_args_namespace.confcutdir = str(self.inipath.parent)
11641164
try:
11651165
self.hook.pytest_load_initial_conftests(
11661166
early_config=self, args=args, parser=self._parser
@@ -1192,13 +1192,13 @@ def _checkversion(self) -> None:
11921192

11931193
if not isinstance(minver, str):
11941194
raise pytest.UsageError(
1195-
"%s: 'minversion' must be a single value" % self.inifile
1195+
"%s: 'minversion' must be a single value" % self.inipath
11961196
)
11971197

11981198
if Version(minver) > Version(pytest.__version__):
11991199
raise pytest.UsageError(
12001200
"%s: 'minversion' requires pytest-%s, actual pytest-%s'"
1201-
% (self.inifile, minver, pytest.__version__,)
1201+
% (self.inipath, minver, pytest.__version__,)
12021202
)
12031203

12041204
def _validate_keys(self) -> None:
@@ -1268,10 +1268,10 @@ def parse(self, args: List[str], addopts: bool = True) -> None:
12681268
args, self.option, namespace=self.option
12691269
)
12701270
if not args:
1271-
if self.invocation_dir == self.rootdir:
1271+
if self.invocation_params.dir == self.rootpath:
12721272
args = self.getini("testpaths")
12731273
if not args:
1274-
args = [str(self.invocation_dir)]
1274+
args = [str(self.invocation_params.dir)]
12751275
self.args = args
12761276
except PrintHelp:
12771277
pass
@@ -1331,10 +1331,10 @@ def _getini(self, name: str):
13311331
#
13321332
if type == "pathlist":
13331333
# TODO: This assert is probably not valid in all cases.
1334-
assert self.inifile is not None
1335-
dp = py.path.local(self.inifile).dirpath()
1334+
assert self.inipath is not None
1335+
dp = self.inipath.parent
13361336
input_values = shlex.split(value) if isinstance(value, str) else value
1337-
return [dp.join(x, abs=True) for x in input_values]
1337+
return [py.path.local(str(dp / x)) for x in input_values]
13381338
elif type == "args":
13391339
return shlex.split(value) if isinstance(value, str) else value
13401340
elif type == "linelist":

src/_pytest/fixtures.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from _pytest.mark import ParameterSet
5151
from _pytest.outcomes import fail
5252
from _pytest.outcomes import TEST_OUTCOME
53+
from _pytest.pathlib import absolutepath
5354

5455
if TYPE_CHECKING:
5556
from typing import Deque
@@ -1450,7 +1451,7 @@ def getfixtureinfo(
14501451
def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
14511452
nodeid = None
14521453
try:
1453-
p = py.path.local(plugin.__file__) # type: ignore[attr-defined]
1454+
p = absolutepath(plugin.__file__) # type: ignore[attr-defined]
14541455
except AttributeError:
14551456
pass
14561457
else:
@@ -1459,8 +1460,13 @@ def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
14591460
# Construct the base nodeid which is later used to check
14601461
# what fixtures are visible for particular tests (as denoted
14611462
# by their test id).
1462-
if p.basename.startswith("conftest.py"):
1463-
nodeid = p.dirpath().relto(self.config.rootdir)
1463+
if p.name.startswith("conftest.py"):
1464+
try:
1465+
nodeid = str(p.parent.relative_to(self.config.rootpath))
1466+
except ValueError:
1467+
nodeid = ""
1468+
if nodeid == ".":
1469+
nodeid = ""
14641470
if os.sep != nodes.SEP:
14651471
nodeid = nodeid.replace(os.sep, nodes.SEP)
14661472

src/_pytest/logging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ def set_log_path(self, fname: str) -> None:
603603
fpath = Path(fname)
604604

605605
if not fpath.is_absolute():
606-
fpath = Path(str(self._config.rootdir), fpath)
606+
fpath = self._config.rootpath / fpath
607607

608608
if not fpath.parent.exists():
609609
fpath.parent.mkdir(exist_ok=True, parents=True)

src/_pytest/main.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from _pytest.fixtures import FixtureManager
3434
from _pytest.outcomes import exit
3535
from _pytest.pathlib import absolutepath
36+
from _pytest.pathlib import bestrelpath
3637
from _pytest.pathlib import Path
3738
from _pytest.pathlib import visit
3839
from _pytest.reports import CollectReport
@@ -411,11 +412,11 @@ class Failed(Exception):
411412

412413

413414
@attr.s
414-
class _bestrelpath_cache(Dict[py.path.local, str]):
415-
path = attr.ib(type=py.path.local)
415+
class _bestrelpath_cache(Dict[Path, str]):
416+
path = attr.ib(type=Path)
416417

417-
def __missing__(self, path: py.path.local) -> str:
418-
r = self.path.bestrelpath(path) # type: str
418+
def __missing__(self, path: Path) -> str:
419+
r = bestrelpath(self.path, path)
419420
self[path] = r
420421
return r
421422

@@ -430,8 +431,8 @@ class Session(nodes.FSCollector):
430431
exitstatus = None # type: Union[int, ExitCode]
431432

432433
def __init__(self, config: Config) -> None:
433-
nodes.FSCollector.__init__(
434-
self, config.rootdir, parent=None, config=config, session=self, nodeid=""
434+
super().__init__(
435+
config.rootdir, parent=None, config=config, session=self, nodeid=""
435436
)
436437
self.testsfailed = 0
437438
self.testscollected = 0
@@ -442,8 +443,8 @@ def __init__(self, config: Config) -> None:
442443
self._initialpaths = frozenset() # type: FrozenSet[py.path.local]
443444

444445
self._bestrelpathcache = _bestrelpath_cache(
445-
config.rootdir
446-
) # type: Dict[py.path.local, str]
446+
config.rootpath
447+
) # type: Dict[Path, str]
447448

448449
self.config.pluginmanager.register(self, name="session")
449450

@@ -461,7 +462,7 @@ def __repr__(self) -> str:
461462
self.testscollected,
462463
)
463464

464-
def _node_location_to_relpath(self, node_path: py.path.local) -> str:
465+
def _node_location_to_relpath(self, node_path: Path) -> str:
465466
# bestrelpath is a quite slow function.
466467
return self._bestrelpathcache[node_path]
467468

@@ -585,7 +586,9 @@ def perform_collect( # noqa: F811
585586
initialpaths = [] # type: List[py.path.local]
586587
for arg in args:
587588
fspath, parts = resolve_collection_argument(
588-
self.config.invocation_dir, arg, as_pypath=self.config.option.pyargs
589+
self.config.invocation_params.dir,
590+
arg,
591+
as_pypath=self.config.option.pyargs,
589592
)
590593
self._initial_parts.append((fspath, parts))
591594
initialpaths.append(fspath)
@@ -803,7 +806,7 @@ def search_pypath(module_name: str) -> str:
803806

804807

805808
def resolve_collection_argument(
806-
invocation_dir: py.path.local, arg: str, *, as_pypath: bool = False
809+
invocation_path: Path, arg: str, *, as_pypath: bool = False
807810
) -> Tuple[py.path.local, List[str]]:
808811
"""Parse path arguments optionally containing selection parts and return (fspath, names).
809812
@@ -830,7 +833,7 @@ def resolve_collection_argument(
830833
strpath, *parts = str(arg).split("::")
831834
if as_pypath:
832835
strpath = search_pypath(strpath)
833-
fspath = Path(str(invocation_dir), strpath)
836+
fspath = invocation_path / strpath
834837
fspath = absolutepath(fspath)
835838
if not fspath.exists():
836839
msg = (

src/_pytest/nodes.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from _pytest.mark.structures import MarkDecorator
3232
from _pytest.mark.structures import NodeKeywords
3333
from _pytest.outcomes import fail
34+
from _pytest.pathlib import absolutepath
3435
from _pytest.pathlib import Path
3536
from _pytest.store import Store
3637

@@ -401,7 +402,7 @@ def _repr_failure_py(
401402
# It will be better to just always display paths relative to invocation_dir, but
402403
# this requires a lot of plumbing (#6428).
403404
try:
404-
abspath = Path(os.getcwd()) != Path(str(self.config.invocation_dir))
405+
abspath = Path(os.getcwd()) != self.config.invocation_params.dir
405406
except OSError:
406407
abspath = True
407408

@@ -594,10 +595,7 @@ def reportinfo(self) -> Tuple[Union[py.path.local, str], Optional[int], str]:
594595
@cached_property
595596
def location(self) -> Tuple[str, Optional[int], str]:
596597
location = self.reportinfo()
597-
if isinstance(location[0], py.path.local):
598-
fspath = location[0]
599-
else:
600-
fspath = py.path.local(location[0])
598+
fspath = absolutepath(str(location[0]))
601599
relfspath = self.session._node_location_to_relpath(fspath)
602600
assert type(location[2]) is str
603601
return (relfspath, location[1], location[2])

src/_pytest/pathlib.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,7 @@ def make_numbered_dir_with_cleanup(
366366
raise e
367367

368368

369-
def resolve_from_str(input: str, root: py.path.local) -> Path:
370-
rootpath = Path(root)
369+
def resolve_from_str(input: str, rootpath: Path) -> Path:
371370
input = expanduser(input)
372371
input = expandvars(input)
373372
if isabs(input):

src/_pytest/terminal.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
from _pytest.config.argparsing import Parser
4141
from _pytest.nodes import Item
4242
from _pytest.nodes import Node
43+
from _pytest.pathlib import absolutepath
44+
from _pytest.pathlib import bestrelpath
45+
from _pytest.pathlib import Path
4346
from _pytest.reports import BaseReport
4447
from _pytest.reports import CollectReport
4548
from _pytest.reports import TestReport
@@ -297,9 +300,9 @@ def get_location(self, config: Config) -> Optional[str]:
297300
if self.fslocation:
298301
if isinstance(self.fslocation, tuple) and len(self.fslocation) >= 2:
299302
filename, linenum = self.fslocation[:2]
300-
relpath = py.path.local(filename).relto(config.invocation_dir)
301-
if not relpath:
302-
relpath = str(filename)
303+
relpath = bestrelpath(
304+
config.invocation_params.dir, absolutepath(filename)
305+
)
303306
return "{}:{}".format(relpath, linenum)
304307
else:
305308
return str(self.fslocation)
@@ -319,11 +322,12 @@ def __init__(self, config: Config, file: Optional[TextIO] = None) -> None:
319322
self._main_color = None # type: Optional[str]
320323
self._known_types = None # type: Optional[List[str]]
321324
self.startdir = config.invocation_dir
325+
self.startpath = config.invocation_params.dir
322326
if file is None:
323327
file = sys.stdout
324328
self._tw = _pytest.config.create_terminal_writer(config, file)
325329
self._screen_width = self._tw.fullwidth
326-
self.currentfspath = None # type: Any
330+
self.currentfspath = None # type: Union[None, Path, str, int]
327331
self.reportchars = getreportopt(config)
328332
self.hasmarkup = self._tw.hasmarkup
329333
self.isatty = file.isatty()
@@ -385,19 +389,17 @@ def hasopt(self, char: str) -> bool:
385389
return char in self.reportchars
386390

387391
def write_fspath_result(self, nodeid: str, res, **markup: bool) -> None:
388-
fspath = self.config.rootdir.join(nodeid.split("::")[0])
389-
# NOTE: explicitly check for None to work around py bug, and for less
390-
# overhead in general (https://github.com/pytest-dev/py/pull/207).
392+
fspath = self.config.rootpath / nodeid.split("::")[0]
391393
if self.currentfspath is None or fspath != self.currentfspath:
392394
if self.currentfspath is not None and self._show_progress_info:
393395
self._write_progress_information_filling_space()
394396
self.currentfspath = fspath
395-
relfspath = self.startdir.bestrelpath(fspath)
397+
relfspath = bestrelpath(self.startpath, fspath)
396398
self._tw.line()
397399
self._tw.write(relfspath + " ")
398400
self._tw.write(res, flush=True, **markup)
399401

400-
def write_ensure_prefix(self, prefix, extra: str = "", **kwargs) -> None:
402+
def write_ensure_prefix(self, prefix: str, extra: str = "", **kwargs) -> None:
401403
if self.currentfspath != prefix:
402404
self._tw.line()
403405
self.currentfspath = prefix
@@ -709,14 +711,14 @@ def _write_report_lines_from_hooks(
709711
self.write_line(line)
710712

711713
def pytest_report_header(self, config: Config) -> List[str]:
712-
line = "rootdir: %s" % config.rootdir
714+
line = "rootdir: %s" % config.rootpath
713715

714-
if config.inifile:
715-
line += ", configfile: " + config.rootdir.bestrelpath(config.inifile)
716+
if config.inipath:
717+
line += ", configfile: " + bestrelpath(config.rootpath, config.inipath)
716718

717719
testpaths = config.getini("testpaths")
718720
if testpaths and config.args == testpaths:
719-
rel_paths = [config.rootdir.bestrelpath(x) for x in testpaths]
721+
rel_paths = [bestrelpath(config.rootpath, x) for x in testpaths]
720722
line += ", testpaths: {}".format(", ".join(rel_paths))
721723
result = [line]
722724

@@ -860,7 +862,7 @@ def mkrel(nodeid):
860862
if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace(
861863
"\\", nodes.SEP
862864
):
863-
res += " <- " + self.startdir.bestrelpath(fspath)
865+
res += " <- " + bestrelpath(self.startpath, fspath)
864866
else:
865867
res = "[location]"
866868
return res + " "
@@ -1102,7 +1104,7 @@ def show_xpassed(lines: List[str]) -> None:
11021104

11031105
def show_skipped(lines: List[str]) -> None:
11041106
skipped = self.stats.get("skipped", []) # type: List[CollectReport]
1105-
fskips = _folded_skips(self.startdir, skipped) if skipped else []
1107+
fskips = _folded_skips(self.startpath, skipped) if skipped else []
11061108
if not fskips:
11071109
return
11081110
verbose_word = skipped[0]._get_verbose_word(self.config)
@@ -1230,7 +1232,7 @@ def _get_line_with_reprcrash_message(
12301232

12311233

12321234
def _folded_skips(
1233-
startdir: py.path.local, skipped: Sequence[CollectReport],
1235+
startpath: Path, skipped: Sequence[CollectReport],
12341236
) -> List[Tuple[int, str, Optional[int], str]]:
12351237
d = {} # type: Dict[Tuple[str, Optional[int], str], List[CollectReport]]
12361238
for event in skipped:
@@ -1239,7 +1241,7 @@ def _folded_skips(
12391241
assert len(event.longrepr) == 3, (event, event.longrepr)
12401242
fspath, lineno, reason = event.longrepr
12411243
# For consistency, report all fspaths in relative form.
1242-
fspath = startdir.bestrelpath(py.path.local(fspath))
1244+
fspath = bestrelpath(startpath, Path(fspath))
12431245
keywords = getattr(event, "keywords", {})
12441246
# Folding reports with global pytestmark variable.
12451247
# This is a workaround, because for now we cannot identify the scope of a skip marker

0 commit comments

Comments
 (0)