[7.4.x] Fixes for typed pluggy (#11355)

Since version 1.3 pluggy added typing, which requires some fixes to
please mypy.
This commit is contained in:
Ran Benita 2023-08-27 01:15:32 +03:00 committed by GitHub
parent 69140717d4
commit 7a5f2feefb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 25 additions and 12 deletions

View File

@ -978,10 +978,10 @@ TestShortLogReport
.. autoclass:: pytest.TestShortLogReport() .. autoclass:: pytest.TestShortLogReport()
:members: :members:
_Result Result
~~~~~~~ ~~~~~~~
Result object used within :ref:`hook wrappers <hookwrapper>`, see :py:class:`_Result in the pluggy documentation <pluggy._callers._Result>` for more information. Result object used within :ref:`hook wrappers <hookwrapper>`, see :py:class:`Result in the pluggy documentation <pluggy.Result>` for more information.
Stash Stash
~~~~~ ~~~~~

View File

@ -444,10 +444,10 @@ class PytestPluginManager(PluginManager):
# so we avoid accessing possibly non-readable attributes # so we avoid accessing possibly non-readable attributes
# (see issue #1073). # (see issue #1073).
if not name.startswith("pytest_"): if not name.startswith("pytest_"):
return return None
# Ignore names which can not be hooks. # Ignore names which can not be hooks.
if name == "pytest_plugins": if name == "pytest_plugins":
return return None
opts = super().parse_hookimpl_opts(plugin, name) opts = super().parse_hookimpl_opts(plugin, name)
if opts is not None: if opts is not None:
@ -456,9 +456,9 @@ class PytestPluginManager(PluginManager):
method = getattr(plugin, name) method = getattr(plugin, name)
# Consider only actual functions for hooks (#3775). # Consider only actual functions for hooks (#3775).
if not inspect.isroutine(method): if not inspect.isroutine(method):
return return None
# Collect unmarked hooks as long as they have the `pytest_' prefix. # Collect unmarked hooks as long as they have the `pytest_' prefix.
return _get_legacy_hook_marks( return _get_legacy_hook_marks( # type: ignore[return-value]
method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper") method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper")
) )
@ -467,7 +467,7 @@ class PytestPluginManager(PluginManager):
if opts is None: if opts is None:
method = getattr(module_or_class, name) method = getattr(module_or_class, name)
if name.startswith("pytest_"): if name.startswith("pytest_"):
opts = _get_legacy_hook_marks( opts = _get_legacy_hook_marks( # type: ignore[assignment]
method, method,
"spec", "spec",
("firstresult", "historic"), ("firstresult", "historic"),
@ -1065,9 +1065,10 @@ class Config:
fin() fin()
def get_terminal_writer(self) -> TerminalWriter: def get_terminal_writer(self) -> TerminalWriter:
terminalreporter: TerminalReporter = self.pluginmanager.get_plugin( terminalreporter: Optional[TerminalReporter] = self.pluginmanager.get_plugin(
"terminalreporter" "terminalreporter"
) )
assert terminalreporter is not None
return terminalreporter._tw return terminalreporter._tw
def pytest_cmdline_parse( def pytest_cmdline_parse(

View File

@ -11,6 +11,7 @@ from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config import PrintHelp from _pytest.config import PrintHelp
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.terminal import TerminalReporter
class HelpAction(Action): class HelpAction(Action):
@ -159,7 +160,10 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
def showhelp(config: Config) -> None: def showhelp(config: Config) -> None:
import textwrap import textwrap
reporter = config.pluginmanager.get_plugin("terminalreporter") reporter: Optional[TerminalReporter] = config.pluginmanager.get_plugin(
"terminalreporter"
)
assert reporter is not None
tw = reporter._tw tw = reporter._tw
tw.write(config._parser.optparser.format_help()) tw.write(config._parser.optparser.format_help())
tw.line() tw.line()

View File

@ -660,6 +660,8 @@ class LoggingPlugin:
) )
if self._log_cli_enabled(): if self._log_cli_enabled():
terminal_reporter = config.pluginmanager.get_plugin("terminalreporter") terminal_reporter = config.pluginmanager.get_plugin("terminalreporter")
# Guaranteed by `_log_cli_enabled()`.
assert terminal_reporter is not None
capture_manager = config.pluginmanager.get_plugin("capturemanager") capture_manager = config.pluginmanager.get_plugin("capturemanager")
# if capturemanager plugin is disabled, live logging still works. # if capturemanager plugin is disabled, live logging still works.
self.log_cli_handler: Union[ self.log_cli_handler: Union[

View File

@ -752,7 +752,7 @@ class Pytester:
def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder: def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder:
"""Create a new :class:`HookRecorder` for a :class:`PytestPluginManager`.""" """Create a new :class:`HookRecorder` for a :class:`PytestPluginManager`."""
pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) # type: ignore[attr-defined]
self._request.addfinalizer(reprec.finish_recording) self._request.addfinalizer(reprec.finish_recording)
return reprec return reprec

View File

@ -242,8 +242,12 @@ class TestPytestPluginManager:
mod = types.ModuleType("temp") mod = types.ModuleType("temp")
mod.__dict__["pytest_plugins"] = ["pytest_p1", "pytest_p2"] mod.__dict__["pytest_plugins"] = ["pytest_p1", "pytest_p2"]
pytestpm.consider_module(mod) pytestpm.consider_module(mod)
assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1" p1 = pytestpm.get_plugin("pytest_p1")
assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2" assert p1 is not None
assert p1.__name__ == "pytest_p1"
p2 = pytestpm.get_plugin("pytest_p2")
assert p2 is not None
assert p2.__name__ == "pytest_p2"
def test_consider_module_import_module( def test_consider_module_import_module(
self, pytester: Pytester, _config_for_test: Config self, pytester: Pytester, _config_for_test: Config
@ -336,6 +340,7 @@ class TestPytestPluginManager:
len2 = len(pytestpm.get_plugins()) len2 = len(pytestpm.get_plugins())
assert len1 == len2 assert len1 == len2
plugin1 = pytestpm.get_plugin("pytest_hello") plugin1 = pytestpm.get_plugin("pytest_hello")
assert plugin1 is not None
assert plugin1.__name__.endswith("pytest_hello") assert plugin1.__name__.endswith("pytest_hello")
plugin2 = pytestpm.get_plugin("pytest_hello") plugin2 = pytestpm.get_plugin("pytest_hello")
assert plugin2 is plugin1 assert plugin2 is plugin1
@ -351,6 +356,7 @@ class TestPytestPluginManager:
pluginname = "pkg.plug" pluginname = "pkg.plug"
pytestpm.import_plugin(pluginname) pytestpm.import_plugin(pluginname)
mod = pytestpm.get_plugin("pkg.plug") mod = pytestpm.get_plugin("pkg.plug")
assert mod is not None
assert mod.x == 3 assert mod.x == 3
def test_consider_conftest_deps( def test_consider_conftest_deps(