From a445d0f960285ac635a56517120ab0efc68712a2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 23 Sep 2021 11:12:20 +0200 Subject: [PATCH] rearrange explicit hook warnings to pass in all data needed for warning registries --- pyproject.toml | 3 +++ src/_pytest/config/__init__.py | 21 +++++---------------- src/_pytest/warning_types.py | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bead1ec7fe..7e46767e9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,9 @@ filterwarnings = [ # Those are caught/handled by pyupgrade, and not easy to filter with the # module being the filename (with .py removed). "default:invalid escape sequence:DeprecationWarning", + # ignore not yet fixed warnings for hook markers + "default:.*not marked using pytest.hook.*", + "ignore:.*not marked using pytest.hook.*::xdist.*", # ignore use of unregistered marks, because we use many to test the implementation "ignore::_pytest.warning_types.PytestUnknownMarkWarning", # https://github.com/benjaminp/six/issues/341 diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 566306cbd7..a566c16c88 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -58,6 +58,7 @@ from _pytest.pathlib import resolve_package_path from _pytest.stash import Stash from _pytest.warning_types import PytestConfigWarning +from _pytest.warning_types import warn_explicit_for if TYPE_CHECKING: @@ -407,18 +408,12 @@ def parse_hookimpl_opts(self, plugin: _PluggyPlugin, name: str): name: hasattr(method, name) or name in known_marks for name in ("tryfirst", "trylast", "optionalhook", "hookwrapper") } - if any(opts.values()) and not getattr( - plugin, "__module__", getattr(plugin, "__name__") - ).startswith("xdist."): + if any(opts.values()): message = _pytest.deprecated.HOOK_LEGACY_MARKING.format( type="spec", fullname=method.__qualname__ ) - warnings.warn_explicit( - message, - type(message), - filename=inspect.getfile(method), - lineno=method.__code__.co_firstlineno, - ) + warn_explicit_for(method, message) + return opts def parse_hookspec_opts(self, module_or_class, name: str): @@ -436,16 +431,10 @@ def parse_hookspec_opts(self, module_or_class, name: str): } # hook from xdist, fixing in ... if any(opts.values()) and module_or_class.__name__ != "xdist.newhooks": - message = _pytest.deprecated.HOOK_LEGACY_MARKING.format( type="spec", fullname=method.__qualname__ ) - warnings.warn_explicit( - message, - type(message), - filename=inspect.getfile(method), - lineno=method.__code__.co_firstlineno, - ) + warn_explicit_for(method, message) return opts def register( diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 2eadd9fe4d..d440fd9605 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -1,3 +1,6 @@ +import inspect +import warnings +from types import FunctionType from typing import Any from typing import Generic from typing import Type @@ -130,3 +133,19 @@ class UnformattedWarning(Generic[_W]): def format(self, **kwargs: Any) -> _W: """Return an instance of the warning category, formatted with given kwargs.""" return self.category(self.template.format(**kwargs)) + + +def warn_explicit_for(method: FunctionType, message: PytestWarning) -> None: + lineno = method.__code__.co_firstlineno + filename = inspect.getfile(method) + module = method.__module__ + mod_globals = method.__globals__ + + warnings.warn_explicit( + message, + type(message), + filename=filename, + module=module, + registry=mod_globals.setdefault("__warningregistry__", {}), + lineno=lineno, + )