hookspec: add pathlib.Path alternatives to py.path.local parameters in hooks
As part of the ongoing migration for py.path to pathlib, make sure all hooks which take a py.path.local also take an equivalent pathlib.Path.
This commit is contained in:
parent
2cb34a99cb
commit
592b32bd69
|
@ -0,0 +1,7 @@
|
|||
The following hooks now receive an additional ``pathlib.Path`` argument, equivalent to an existing ``py.path.local`` argument:
|
||||
|
||||
- :func:`pytest_ignore_collect <_pytest.hookspec.pytest_ignore_collect>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_collect_file <_pytest.hookspec.pytest_collect_file>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_pycollect_makemodule <_pytest.hookspec.pytest_pycollect_makemodule>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_report_header <_pytest.hookspec.pytest_report_header>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
||||
- :func:`pytest_report_collectionfinish <_pytest.hookspec.pytest_report_collectionfinish>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
|
@ -1,5 +1,6 @@
|
|||
"""Hook specifications for pytest plugins which are invoked by pytest itself
|
||||
and by builtin plugins."""
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
|
@ -261,7 +262,9 @@ def pytest_collection_finish(session: "Session") -> None:
|
|||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_ignore_collect(path: py.path.local, config: "Config") -> Optional[bool]:
|
||||
def pytest_ignore_collect(
|
||||
fspath: Path, path: py.path.local, config: "Config"
|
||||
) -> Optional[bool]:
|
||||
"""Return True to prevent considering this path for collection.
|
||||
|
||||
This hook is consulted for all files and directories prior to calling
|
||||
|
@ -269,19 +272,29 @@ def pytest_ignore_collect(path: py.path.local, config: "Config") -> Optional[boo
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
|
||||
:param pathlib.Path fspath: The path to analyze.
|
||||
:param py.path.local path: The path to analyze.
|
||||
:param _pytest.config.Config config: The pytest config object.
|
||||
|
||||
.. versionchanged:: 6.3.0
|
||||
The ``fspath`` parameter was added as a :class:`pathlib.Path`
|
||||
equivalent of the ``path`` parameter.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_collect_file(
|
||||
path: py.path.local, parent: "Collector"
|
||||
fspath: Path, path: py.path.local, parent: "Collector"
|
||||
) -> "Optional[Collector]":
|
||||
"""Create a Collector for the given path, or None if not relevant.
|
||||
|
||||
The new node needs to have the specified ``parent`` as a parent.
|
||||
|
||||
:param pathlib.Path fspath: The path to analyze.
|
||||
:param py.path.local path: The path to collect.
|
||||
|
||||
.. versionchanged:: 6.3.0
|
||||
The ``fspath`` parameter was added as a :class:`pathlib.Path`
|
||||
equivalent of the ``path`` parameter.
|
||||
"""
|
||||
|
||||
|
||||
|
@ -321,7 +334,9 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor
|
|||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makemodule(path: py.path.local, parent) -> Optional["Module"]:
|
||||
def pytest_pycollect_makemodule(
|
||||
fspath: Path, path: py.path.local, parent
|
||||
) -> Optional["Module"]:
|
||||
"""Return a Module collector or None for the given path.
|
||||
|
||||
This hook will be called for each matching test module path.
|
||||
|
@ -330,7 +345,12 @@ def pytest_pycollect_makemodule(path: py.path.local, parent) -> Optional["Module
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult`.
|
||||
|
||||
:param py.path.local path: The path of module to collect.
|
||||
:param pathlib.Path fspath: The path of the module to collect.
|
||||
:param py.path.local path: The path of the module to collect.
|
||||
|
||||
.. versionchanged:: 6.3.0
|
||||
The ``fspath`` parameter was added as a :class:`pathlib.Path`
|
||||
equivalent of the ``path`` parameter.
|
||||
"""
|
||||
|
||||
|
||||
|
@ -653,11 +673,12 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No
|
|||
|
||||
|
||||
def pytest_report_header(
|
||||
config: "Config", startdir: py.path.local
|
||||
config: "Config", startpath: Path, startdir: py.path.local
|
||||
) -> Union[str, List[str]]:
|
||||
"""Return a string or list of strings to be displayed as header info for terminal reporting.
|
||||
|
||||
:param _pytest.config.Config config: The pytest config object.
|
||||
:param Path startpath: The starting dir.
|
||||
:param py.path.local startdir: The starting dir.
|
||||
|
||||
.. note::
|
||||
|
@ -672,11 +693,15 @@ def pytest_report_header(
|
|||
This function should be implemented only in plugins or ``conftest.py``
|
||||
files situated at the tests root directory due to how pytest
|
||||
:ref:`discovers plugins during startup <pluginorder>`.
|
||||
|
||||
.. versionchanged:: 6.3.0
|
||||
The ``startpath`` parameter was added as a :class:`pathlib.Path`
|
||||
equivalent of the ``startdir`` parameter.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_report_collectionfinish(
|
||||
config: "Config", startdir: py.path.local, items: Sequence["Item"],
|
||||
config: "Config", startpath: Path, startdir: py.path.local, items: Sequence["Item"],
|
||||
) -> Union[str, List[str]]:
|
||||
"""Return a string or list of strings to be displayed after collection
|
||||
has finished successfully.
|
||||
|
@ -686,6 +711,7 @@ def pytest_report_collectionfinish(
|
|||
.. versionadded:: 3.2
|
||||
|
||||
:param _pytest.config.Config config: The pytest config object.
|
||||
:param Path startpath: The starting path.
|
||||
:param py.path.local startdir: The starting dir.
|
||||
:param items: List of pytest items that are going to be executed; this list should not be modified.
|
||||
|
||||
|
@ -695,6 +721,10 @@ def pytest_report_collectionfinish(
|
|||
ran before it.
|
||||
If you want to have your line(s) displayed first, use
|
||||
:ref:`trylast=True <plugin-hookorder>`.
|
||||
|
||||
.. versionchanged:: 6.3.0
|
||||
The ``startpath`` parameter was added as a :class:`pathlib.Path`
|
||||
equivalent of the ``startdir`` parameter.
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -532,9 +532,10 @@ class Session(nodes.FSCollector):
|
|||
def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
|
||||
if direntry.name == "__pycache__":
|
||||
return False
|
||||
path = py.path.local(direntry.path)
|
||||
ihook = self.gethookproxy(path.dirpath())
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
fspath = Path(direntry.path)
|
||||
path = py.path.local(fspath)
|
||||
ihook = self.gethookproxy(fspath.parent)
|
||||
if ihook.pytest_ignore_collect(fspath=fspath, path=path, config=self.config):
|
||||
return False
|
||||
norecursepatterns = self.config.getini("norecursedirs")
|
||||
if any(path.check(fnmatch=pat) for pat in norecursepatterns):
|
||||
|
@ -544,6 +545,7 @@ class Session(nodes.FSCollector):
|
|||
def _collectfile(
|
||||
self, path: py.path.local, handle_dupes: bool = True
|
||||
) -> Sequence[nodes.Collector]:
|
||||
fspath = Path(path)
|
||||
assert (
|
||||
path.isfile()
|
||||
), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(
|
||||
|
@ -551,7 +553,9 @@ class Session(nodes.FSCollector):
|
|||
)
|
||||
ihook = self.gethookproxy(path)
|
||||
if not self.isinitpath(path):
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
if ihook.pytest_ignore_collect(
|
||||
fspath=fspath, path=path, config=self.config
|
||||
):
|
||||
return ()
|
||||
|
||||
if handle_dupes:
|
||||
|
@ -563,7 +567,7 @@ class Session(nodes.FSCollector):
|
|||
else:
|
||||
duplicate_paths.add(path)
|
||||
|
||||
return ihook.pytest_collect_file(path=path, parent=self) # type: ignore[no-any-return]
|
||||
return ihook.pytest_collect_file(fspath=fspath, path=path, parent=self) # type: ignore[no-any-return]
|
||||
|
||||
@overload
|
||||
def perform_collect(
|
||||
|
|
|
@ -10,6 +10,7 @@ import warnings
|
|||
from collections import Counter
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -187,17 +188,19 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]:
|
|||
|
||||
|
||||
def pytest_collect_file(
|
||||
path: py.path.local, parent: nodes.Collector
|
||||
fspath: Path, path: py.path.local, parent: nodes.Collector
|
||||
) -> Optional["Module"]:
|
||||
ext = path.ext
|
||||
if ext == ".py":
|
||||
if not parent.session.isinitpath(path):
|
||||
if not parent.session.isinitpath(fspath):
|
||||
if not path_matches_patterns(
|
||||
path, parent.config.getini("python_files") + ["__init__.py"]
|
||||
):
|
||||
return None
|
||||
ihook = parent.session.gethookproxy(path)
|
||||
module: Module = ihook.pytest_pycollect_makemodule(path=path, parent=parent)
|
||||
ihook = parent.session.gethookproxy(fspath)
|
||||
module: Module = ihook.pytest_pycollect_makemodule(
|
||||
fspath=fspath, path=path, parent=parent
|
||||
)
|
||||
return module
|
||||
return None
|
||||
|
||||
|
@ -664,9 +667,10 @@ class Package(Module):
|
|||
def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
|
||||
if direntry.name == "__pycache__":
|
||||
return False
|
||||
path = py.path.local(direntry.path)
|
||||
ihook = self.session.gethookproxy(path.dirpath())
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
fspath = Path(direntry.path)
|
||||
path = py.path.local(fspath)
|
||||
ihook = self.session.gethookproxy(fspath.parent)
|
||||
if ihook.pytest_ignore_collect(fspath=fspath, path=path, config=self.config):
|
||||
return False
|
||||
norecursepatterns = self.config.getini("norecursedirs")
|
||||
if any(path.check(fnmatch=pat) for pat in norecursepatterns):
|
||||
|
@ -676,6 +680,7 @@ class Package(Module):
|
|||
def _collectfile(
|
||||
self, path: py.path.local, handle_dupes: bool = True
|
||||
) -> Sequence[nodes.Collector]:
|
||||
fspath = Path(path)
|
||||
assert (
|
||||
path.isfile()
|
||||
), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(
|
||||
|
@ -683,7 +688,9 @@ class Package(Module):
|
|||
)
|
||||
ihook = self.session.gethookproxy(path)
|
||||
if not self.session.isinitpath(path):
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
if ihook.pytest_ignore_collect(
|
||||
fspath=fspath, path=path, config=self.config
|
||||
):
|
||||
return ()
|
||||
|
||||
if handle_dupes:
|
||||
|
@ -695,7 +702,7 @@ class Package(Module):
|
|||
else:
|
||||
duplicate_paths.add(path)
|
||||
|
||||
return ihook.pytest_collect_file(path=path, parent=self) # type: ignore[no-any-return]
|
||||
return ihook.pytest_collect_file(fspath=fspath, path=path, parent=self) # type: ignore[no-any-return]
|
||||
|
||||
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
||||
this_path = self.fspath.dirpath()
|
||||
|
|
|
@ -710,7 +710,7 @@ class TerminalReporter:
|
|||
msg += " -- " + str(sys.executable)
|
||||
self.write_line(msg)
|
||||
lines = self.config.hook.pytest_report_header(
|
||||
config=self.config, startdir=self.startdir
|
||||
config=self.config, startpath=self.startpath, startdir=self.startdir
|
||||
)
|
||||
self._write_report_lines_from_hooks(lines)
|
||||
|
||||
|
@ -745,7 +745,10 @@ class TerminalReporter:
|
|||
self.report_collect(True)
|
||||
|
||||
lines = self.config.hook.pytest_report_collectionfinish(
|
||||
config=self.config, startdir=self.startdir, items=session.items
|
||||
config=self.config,
|
||||
startpath=self.startpath,
|
||||
startdir=self.startdir,
|
||||
items=session.items,
|
||||
)
|
||||
self._write_report_lines_from_hooks(lines)
|
||||
|
||||
|
|
|
@ -1010,7 +1010,7 @@ class TestTerminalFunctional:
|
|||
def test_report_collectionfinish_hook(self, pytester: Pytester, params) -> None:
|
||||
pytester.makeconftest(
|
||||
"""
|
||||
def pytest_report_collectionfinish(config, startdir, items):
|
||||
def pytest_report_collectionfinish(config, startpath, startdir, items):
|
||||
return ['hello from hook: {0} items'.format(len(items))]
|
||||
"""
|
||||
)
|
||||
|
@ -1436,8 +1436,8 @@ class TestGenericReporting:
|
|||
)
|
||||
pytester.mkdir("a").joinpath("conftest.py").write_text(
|
||||
"""
|
||||
def pytest_report_header(config, startdir):
|
||||
return ["line1", str(startdir)]
|
||||
def pytest_report_header(config, startdir, startpath):
|
||||
return ["line1", str(startpath)]
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest("a")
|
||||
|
|
Loading…
Reference in New Issue