nodes: micro-optimize _imply_path
This commit is contained in:
parent
54811b24e2
commit
076ac901bb
|
@ -93,26 +93,40 @@ def iterparentnodeids(nodeid: str) -> Iterator[str]:
|
|||
yield nodeid
|
||||
|
||||
|
||||
def _check_path(path: Path, fspath: LEGACY_PATH) -> None:
|
||||
if Path(fspath) != path:
|
||||
raise ValueError(
|
||||
f"Path({fspath!r}) != {path!r}\n"
|
||||
"if both path and fspath are given they need to be equal"
|
||||
)
|
||||
|
||||
|
||||
def _imply_path(
|
||||
path: Optional[Path], fspath: Optional[LEGACY_PATH]
|
||||
) -> Tuple[Path, LEGACY_PATH]:
|
||||
if path is not None:
|
||||
if fspath is not None:
|
||||
if Path(fspath) != path:
|
||||
raise ValueError(
|
||||
f"Path({fspath!r}) != {path!r}\n"
|
||||
"if both path and fspath are given they need to be equal"
|
||||
)
|
||||
assert Path(fspath) == path, f"{fspath} != {path}"
|
||||
_check_path(path, fspath)
|
||||
else:
|
||||
fspath = legacy_path(path)
|
||||
return path, fspath
|
||||
|
||||
else:
|
||||
assert fspath is not None
|
||||
return Path(fspath), fspath
|
||||
|
||||
|
||||
# Optimization: use _imply_path_only over _imply_path when only need Path.
|
||||
# This is to avoid `legacy_path(path)` which is surprisingly heavy.
|
||||
def _imply_path_only(path: Optional[Path], fspath: Optional[LEGACY_PATH]) -> Path:
|
||||
if path is not None:
|
||||
if fspath is not None:
|
||||
_check_path(path, fspath)
|
||||
return path
|
||||
else:
|
||||
assert fspath is not None
|
||||
return Path(fspath)
|
||||
|
||||
|
||||
_NodeType = TypeVar("_NodeType", bound="Node")
|
||||
|
||||
|
||||
|
@ -196,7 +210,9 @@ class Node(metaclass=NodeMeta):
|
|||
self.session = parent.session
|
||||
|
||||
#: Filesystem path where this node was collected from (can be None).
|
||||
self.path = _imply_path(path or getattr(parent, "path", None), fspath=fspath)[0]
|
||||
self.path = _imply_path_only(
|
||||
path or getattr(parent, "path", None), fspath=fspath
|
||||
)
|
||||
|
||||
# The explicit annotation is to avoid publicly exposing NodeKeywords.
|
||||
#: Keywords/markers collected from all scopes.
|
||||
|
@ -573,7 +589,7 @@ class FSCollector(Collector):
|
|||
assert path is None
|
||||
path = path_or_parent
|
||||
|
||||
path, fspath = _imply_path(path, fspath=fspath)
|
||||
path = _imply_path_only(path, fspath=fspath)
|
||||
if name is None:
|
||||
name = path.name
|
||||
if parent is not None and parent.path != path:
|
||||
|
|
|
@ -639,7 +639,6 @@ class Package(Module):
|
|||
) -> None:
|
||||
# NOTE: Could be just the following, but kept as-is for compat.
|
||||
# nodes.FSCollector.__init__(self, fspath, parent=parent)
|
||||
path, fspath = nodes._imply_path(path, fspath=fspath)
|
||||
session = parent.session
|
||||
nodes.FSCollector.__init__(
|
||||
self,
|
||||
|
@ -650,7 +649,7 @@ class Package(Module):
|
|||
session=session,
|
||||
nodeid=nodeid,
|
||||
)
|
||||
self.name = path.parent.name
|
||||
self.name = self.path.parent.name
|
||||
|
||||
def setup(self) -> None:
|
||||
# Not using fixtures to call setup_module here because autouse fixtures
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
@ -179,6 +180,13 @@ def test_hookproxy_warnings_for_fspath(tmp_path, hooktype, request):
|
|||
|
||||
hooks.pytest_ignore_collect(config=request.config, fspath=tmp_path)
|
||||
|
||||
# Passing entirely *different* paths is an outright error.
|
||||
with pytest.raises(ValueError, match=r"path.*fspath.*need to be equal"):
|
||||
with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r:
|
||||
hooks.pytest_ignore_collect(
|
||||
config=request.config, path=path, fspath=Path("/bla/bla")
|
||||
)
|
||||
|
||||
|
||||
def test_warns_none_is_deprecated():
|
||||
with pytest.warns(
|
||||
|
|
Loading…
Reference in New Issue