Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.4.x] Fixes for typed pluggy #11355

Merged
merged 1 commit into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -978,10 +978,10 @@ TestShortLogReport
.. autoclass:: pytest.TestShortLogReport()
: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
~~~~~
Expand Down
13 changes: 7 additions & 6 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,10 @@
# so we avoid accessing possibly non-readable attributes
# (see issue #1073).
if not name.startswith("pytest_"):
return
return None
# Ignore names which can not be hooks.
if name == "pytest_plugins":
return
return None

opts = super().parse_hookimpl_opts(plugin, name)
if opts is not None:
Expand All @@ -456,9 +456,9 @@
method = getattr(plugin, name)
# Consider only actual functions for hooks (#3775).
if not inspect.isroutine(method):
return
return None

Check warning on line 459 in src/_pytest/config/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/config/__init__.py#L459

Added line #L459 was not covered by tests
# 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")
)

Expand All @@ -467,7 +467,7 @@
if opts is None:
method = getattr(module_or_class, name)
if name.startswith("pytest_"):
opts = _get_legacy_hook_marks(
opts = _get_legacy_hook_marks( # type: ignore[assignment]
method,
"spec",
("firstresult", "historic"),
Expand Down Expand Up @@ -1065,9 +1065,10 @@
fin()

def get_terminal_writer(self) -> TerminalWriter:
terminalreporter: TerminalReporter = self.pluginmanager.get_plugin(
terminalreporter: Optional[TerminalReporter] = self.pluginmanager.get_plugin(

Check warning on line 1068 in src/_pytest/config/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/config/__init__.py#L1068

Added line #L1068 was not covered by tests
"terminalreporter"
)
assert terminalreporter is not None

Check warning on line 1071 in src/_pytest/config/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/config/__init__.py#L1071

Added line #L1071 was not covered by tests
return terminalreporter._tw

def pytest_cmdline_parse(
Expand Down
6 changes: 5 additions & 1 deletion src/_pytest/helpconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from _pytest.config import ExitCode
from _pytest.config import PrintHelp
from _pytest.config.argparsing import Parser
from _pytest.terminal import TerminalReporter


class HelpAction(Action):
Expand Down Expand Up @@ -159,7 +160,10 @@
def showhelp(config: Config) -> None:
import textwrap

reporter = config.pluginmanager.get_plugin("terminalreporter")
reporter: Optional[TerminalReporter] = config.pluginmanager.get_plugin(

Check warning on line 163 in src/_pytest/helpconfig.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/helpconfig.py#L163

Added line #L163 was not covered by tests
"terminalreporter"
)
assert reporter is not None

Check warning on line 166 in src/_pytest/helpconfig.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/helpconfig.py#L166

Added line #L166 was not covered by tests
tw = reporter._tw
tw.write(config._parser.optparser.format_help())
tw.line()
Expand Down
2 changes: 2 additions & 0 deletions src/_pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,8 @@
)
if self._log_cli_enabled():
terminal_reporter = config.pluginmanager.get_plugin("terminalreporter")
# Guaranteed by `_log_cli_enabled()`.
assert terminal_reporter is not None

Check warning on line 664 in src/_pytest/logging.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/logging.py#L664

Added line #L664 was not covered by tests
capture_manager = config.pluginmanager.get_plugin("capturemanager")
# if capturemanager plugin is disabled, live logging still works.
self.log_cli_handler: Union[
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ def preserve_module(name):

def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder:
"""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)
return reprec

Expand Down
10 changes: 8 additions & 2 deletions testing/test_pluginmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,12 @@ def test_consider_module(
mod = types.ModuleType("temp")
mod.__dict__["pytest_plugins"] = ["pytest_p1", "pytest_p2"]
pytestpm.consider_module(mod)
assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1"
assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2"
p1 = pytestpm.get_plugin("pytest_p1")
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(
self, pytester: Pytester, _config_for_test: Config
Expand Down Expand Up @@ -336,6 +340,7 @@ def test_import_plugin_importname(
len2 = len(pytestpm.get_plugins())
assert len1 == len2
plugin1 = pytestpm.get_plugin("pytest_hello")
assert plugin1 is not None
assert plugin1.__name__.endswith("pytest_hello")
plugin2 = pytestpm.get_plugin("pytest_hello")
assert plugin2 is plugin1
Expand All @@ -351,6 +356,7 @@ def test_import_plugin_dotted_name(
pluginname = "pkg.plug"
pytestpm.import_plugin(pluginname)
mod = pytestpm.get_plugin("pkg.plug")
assert mod is not None
assert mod.x == 3

def test_consider_conftest_deps(
Expand Down