Skip to content
Open
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
1 change: 1 addition & 0 deletions changelog/727.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix the warning for hookspec arguments missing from a hook call being attributed to pluggy's own frame instead of to the code making the call. This affected ``HookCaller.__call__``, ``call_historic`` and ``call_extra``.
5 changes: 4 additions & 1 deletion src/pluggy/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,10 @@ def _verify_all_args_are_provided(self, kwargs: Mapping[str, object]) -> None:
warnings.warn(
f"Argument(s) {notincall} which are declared in the hookspec "
"cannot be found in this hook call",
stacklevel=2,
# 3, not 2: the warning is raised in this helper, which
# is called by __call__/call_historic/call_extra, which
# are called by the code making the hook call.
stacklevel=3,
)
break

Expand Down
31 changes: 31 additions & 0 deletions testing/test_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,37 @@ def herstory(self, arg1, arg2):
pm.hook.herstory.call_historic(kwargs={})


def test_not_all_arguments_warning_points_at_the_caller(pm: PluginManager) -> None:
"""The warning must be attributed to the code making the hook call.

It is raised inside a helper two frames below the caller, so a stacklevel
that is off by one blames pluggy's own frame instead.
"""

class Spec:
@hookspec
def hello(self, arg1, arg2):
pass # pragma: no cover

@hookspec(historic=True)
def herstory(self, arg1, arg2):
pass # pragma: no cover

pm.add_hookspecs(Spec)

with pytest.warns(UserWarning) as record:
pm.hook.hello(arg1=1)
assert record[0].filename == __file__

with pytest.warns(UserWarning) as record:
pm.hook.hello.call_extra([], kwargs={})
assert record[0].filename == __file__

with pytest.warns(UserWarning) as record:
pm.hook.herstory.call_historic(kwargs={})
assert record[0].filename == __file__


def test_repr() -> None:
class Plugin:
@hookimpl
Expand Down