Merge pull request #7648 from bluetech/pylint-abc2
Only define gethookproxy, isinitpath on Session
This commit is contained in:
commit
c98525bd21
|
@ -0,0 +1 @@
|
||||||
|
pylint shouldn't complain anymore about unimplemented abstract methods when inheriting from :ref:`File <non-python tests>`.
|
|
@ -0,0 +1,3 @@
|
||||||
|
The ``gethookproxy()`` and ``isinitpath()`` methods of ``FSCollector`` and ``Package`` are deprecated;
|
||||||
|
use ``self.session.gethookproxy()`` and ``self.session.isinitpath()`` instead.
|
||||||
|
This should work on all pytest versions.
|
|
@ -84,3 +84,8 @@ WARNING_CAPTURED_HOOK = PytestDeprecationWarning(
|
||||||
"The pytest_warning_captured is deprecated and will be removed in a future release.\n"
|
"The pytest_warning_captured is deprecated and will be removed in a future release.\n"
|
||||||
"Please use pytest_warning_recorded instead."
|
"Please use pytest_warning_recorded instead."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FSCOLLECTOR_GETHOOKPROXY_ISINITPATH = PytestDeprecationWarning(
|
||||||
|
"The gethookproxy() and isinitpath() methods of FSCollector and Package are deprecated; "
|
||||||
|
"use self.session.gethookproxy() and self.session.isinitpath() instead. "
|
||||||
|
)
|
||||||
|
|
|
@ -27,6 +27,7 @@ from _pytest.config import Config
|
||||||
from _pytest.config import directory_arg
|
from _pytest.config import directory_arg
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
|
from _pytest.config import PytestPluginManager
|
||||||
from _pytest.config import UsageError
|
from _pytest.config import UsageError
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.fixtures import FixtureManager
|
from _pytest.fixtures import FixtureManager
|
||||||
|
@ -390,6 +391,17 @@ def pytest_collection_modifyitems(items: List[nodes.Item], config: Config) -> No
|
||||||
items[:] = remaining
|
items[:] = remaining
|
||||||
|
|
||||||
|
|
||||||
|
class FSHookProxy:
|
||||||
|
def __init__(self, pm: PytestPluginManager, remove_mods) -> None:
|
||||||
|
self.pm = pm
|
||||||
|
self.remove_mods = remove_mods
|
||||||
|
|
||||||
|
def __getattr__(self, name: str):
|
||||||
|
x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
|
||||||
|
self.__dict__[name] = x
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
class NoMatch(Exception):
|
class NoMatch(Exception):
|
||||||
"""Matching cannot locate matching names."""
|
"""Matching cannot locate matching names."""
|
||||||
|
|
||||||
|
@ -496,7 +508,20 @@ class Session(nodes.FSCollector):
|
||||||
return path in self._initialpaths
|
return path in self._initialpaths
|
||||||
|
|
||||||
def gethookproxy(self, fspath: py.path.local):
|
def gethookproxy(self, fspath: py.path.local):
|
||||||
return super()._gethookproxy(fspath)
|
# Check if we have the common case of running
|
||||||
|
# hooks with all conftest.py files.
|
||||||
|
pm = self.config.pluginmanager
|
||||||
|
my_conftestmodules = pm._getconftestmodules(
|
||||||
|
fspath, self.config.getoption("importmode")
|
||||||
|
)
|
||||||
|
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
|
||||||
|
if remove_mods:
|
||||||
|
# One or more conftests are not in use at this fspath.
|
||||||
|
proxy = FSHookProxy(pm, remove_mods)
|
||||||
|
else:
|
||||||
|
# All plugins are active for this fspath.
|
||||||
|
proxy = self.config.hook
|
||||||
|
return proxy
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def perform_collect(
|
def perform_collect(
|
||||||
|
|
|
@ -25,7 +25,7 @@ from _pytest.compat import overload
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ConftestImportFailure
|
from _pytest.config import ConftestImportFailure
|
||||||
from _pytest.config import PytestPluginManager
|
from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH
|
||||||
from _pytest.deprecated import NODE_USE_FROM_PARENT
|
from _pytest.deprecated import NODE_USE_FROM_PARENT
|
||||||
from _pytest.fixtures import FixtureDef
|
from _pytest.fixtures import FixtureDef
|
||||||
from _pytest.fixtures import FixtureLookupError
|
from _pytest.fixtures import FixtureLookupError
|
||||||
|
@ -495,17 +495,6 @@ def _check_initialpaths_for_relpath(session, fspath):
|
||||||
return fspath.relto(initial_path)
|
return fspath.relto(initial_path)
|
||||||
|
|
||||||
|
|
||||||
class FSHookProxy:
|
|
||||||
def __init__(self, pm: PytestPluginManager, remove_mods) -> None:
|
|
||||||
self.pm = pm
|
|
||||||
self.remove_mods = remove_mods
|
|
||||||
|
|
||||||
def __getattr__(self, name: str):
|
|
||||||
x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
|
|
||||||
self.__dict__[name] = x
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
class FSCollector(Collector):
|
class FSCollector(Collector):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -542,42 +531,28 @@ class FSCollector(Collector):
|
||||||
"""The public constructor."""
|
"""The public constructor."""
|
||||||
return super().from_parent(parent=parent, fspath=fspath, **kw)
|
return super().from_parent(parent=parent, fspath=fspath, **kw)
|
||||||
|
|
||||||
def _gethookproxy(self, fspath: py.path.local):
|
|
||||||
# Check if we have the common case of running
|
|
||||||
# hooks with all conftest.py files.
|
|
||||||
pm = self.config.pluginmanager
|
|
||||||
my_conftestmodules = pm._getconftestmodules(
|
|
||||||
fspath, self.config.getoption("importmode")
|
|
||||||
)
|
|
||||||
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
|
|
||||||
if remove_mods:
|
|
||||||
# One or more conftests are not in use at this fspath.
|
|
||||||
proxy = FSHookProxy(pm, remove_mods)
|
|
||||||
else:
|
|
||||||
# All plugins are active for this fspath.
|
|
||||||
proxy = self.config.hook
|
|
||||||
return proxy
|
|
||||||
|
|
||||||
def gethookproxy(self, fspath: py.path.local):
|
def gethookproxy(self, fspath: py.path.local):
|
||||||
raise NotImplementedError()
|
warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)
|
||||||
|
return self.session.gethookproxy(fspath)
|
||||||
|
|
||||||
|
def isinitpath(self, path: py.path.local) -> bool:
|
||||||
|
warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)
|
||||||
|
return self.session.isinitpath(path)
|
||||||
|
|
||||||
def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
|
def _recurse(self, direntry: "os.DirEntry[str]") -> bool:
|
||||||
if direntry.name == "__pycache__":
|
if direntry.name == "__pycache__":
|
||||||
return False
|
return False
|
||||||
path = py.path.local(direntry.path)
|
path = py.path.local(direntry.path)
|
||||||
ihook = self._gethookproxy(path.dirpath())
|
ihook = self.session.gethookproxy(path.dirpath())
|
||||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||||
return False
|
return False
|
||||||
for pat in self._norecursepatterns:
|
for pat in self._norecursepatterns:
|
||||||
if path.check(fnmatch=pat):
|
if path.check(fnmatch=pat):
|
||||||
return False
|
return False
|
||||||
ihook = self._gethookproxy(path)
|
ihook = self.session.gethookproxy(path)
|
||||||
ihook.pytest_collect_directory(path=path, parent=self)
|
ihook.pytest_collect_directory(path=path, parent=self)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isinitpath(self, path: py.path.local) -> bool:
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def _collectfile(
|
def _collectfile(
|
||||||
self, path: py.path.local, handle_dupes: bool = True
|
self, path: py.path.local, handle_dupes: bool = True
|
||||||
) -> Sequence[Collector]:
|
) -> Sequence[Collector]:
|
||||||
|
@ -586,8 +561,8 @@ class FSCollector(Collector):
|
||||||
), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(
|
), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(
|
||||||
path, path.isdir(), path.exists(), path.islink()
|
path, path.isdir(), path.exists(), path.islink()
|
||||||
)
|
)
|
||||||
ihook = self.gethookproxy(path)
|
ihook = self.session.gethookproxy(path)
|
||||||
if not self.isinitpath(path):
|
if not self.session.isinitpath(path):
|
||||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ from _pytest.config import Config
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
|
from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH
|
||||||
from _pytest.deprecated import FUNCARGNAMES
|
from _pytest.deprecated import FUNCARGNAMES
|
||||||
from _pytest.fixtures import FuncFixtureInfo
|
from _pytest.fixtures import FuncFixtureInfo
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
|
@ -627,10 +628,12 @@ class Package(Module):
|
||||||
self.addfinalizer(func)
|
self.addfinalizer(func)
|
||||||
|
|
||||||
def gethookproxy(self, fspath: py.path.local):
|
def gethookproxy(self, fspath: py.path.local):
|
||||||
return super()._gethookproxy(fspath)
|
warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)
|
||||||
|
return self.session.gethookproxy(fspath)
|
||||||
|
|
||||||
def isinitpath(self, path: py.path.local) -> bool:
|
def isinitpath(self, path: py.path.local) -> bool:
|
||||||
return path in self.session._initialpaths
|
warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)
|
||||||
|
return self.session.isinitpath(path)
|
||||||
|
|
||||||
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:
|
||||||
this_path = self.fspath.dirpath()
|
this_path = self.fspath.dirpath()
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import copy
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
|
import warnings
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import deprecated
|
from _pytest import deprecated
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
from _pytest.pytester import Testdir
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.filterwarnings("default")
|
@pytest.mark.filterwarnings("default")
|
||||||
|
@ -151,3 +153,28 @@ def test_minus_k_colon_is_deprecated(testdir) -> None:
|
||||||
)
|
)
|
||||||
result = testdir.runpytest("-k", "test_two:", threepass)
|
result = testdir.runpytest("-k", "test_two:", threepass)
|
||||||
result.stdout.fnmatch_lines(["*The `-k 'expr:'` syntax*deprecated*"])
|
result.stdout.fnmatch_lines(["*The `-k 'expr:'` syntax*deprecated*"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_fscollector_gethookproxy_isinitpath(testdir: Testdir) -> None:
|
||||||
|
module = testdir.getmodulecol(
|
||||||
|
"""
|
||||||
|
def test_foo(): pass
|
||||||
|
""",
|
||||||
|
withinit=True,
|
||||||
|
)
|
||||||
|
assert isinstance(module, pytest.Module)
|
||||||
|
package = module.parent
|
||||||
|
assert isinstance(package, pytest.Package)
|
||||||
|
|
||||||
|
with pytest.warns(pytest.PytestDeprecationWarning, match="gethookproxy"):
|
||||||
|
package.gethookproxy(testdir.tmpdir)
|
||||||
|
|
||||||
|
with pytest.warns(pytest.PytestDeprecationWarning, match="isinitpath"):
|
||||||
|
package.isinitpath(testdir.tmpdir)
|
||||||
|
|
||||||
|
# The methods on Session are *not* deprecated.
|
||||||
|
session = module.session
|
||||||
|
with warnings.catch_warnings(record=True) as rec:
|
||||||
|
session.gethookproxy(testdir.tmpdir)
|
||||||
|
session.isinitpath(testdir.tmpdir)
|
||||||
|
assert len(rec) == 0
|
||||||
|
|
Loading…
Reference in New Issue