From 9aed4193a27b9f6cd70d33c0545c47f78b9c5c66 Mon Sep 17 00:00:00 2001 From: "shijie.jiao" Date: Thu, 25 Jan 2024 16:58:27 +0800 Subject: [PATCH 1/4] Fix the issue where passing keyword argumentss was not effective, and enhanced the test cases for the _multicall() function --- src/pluggy/_callers.py | 7 ++++--- testing/test_multicall.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pluggy/_callers.py b/src/pluggy/_callers.py index 787f56ba..2c404aaf 100644 --- a/src/pluggy/_callers.py +++ b/src/pluggy/_callers.py @@ -70,6 +70,7 @@ def _multicall( for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] + kwargs = dict((k, v) for k, v in caller_kwargs.items() if k in hook_impl.kwargnames) except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: @@ -82,7 +83,7 @@ def _multicall( try: # If this cast is not valid, a type error is raised below, # which is the desired response. - res = hook_impl.function(*args) + res = hook_impl.function(*args, **kwargs) wrapper_gen = cast(Generator[None, Result[object], None], res) next(wrapper_gen) # first yield teardowns.append((wrapper_gen, hook_impl)) @@ -92,14 +93,14 @@ def _multicall( try: # If this cast is not valid, a type error is raised below, # which is the desired response. - res = hook_impl.function(*args) + res = hook_impl.function(*args, **kwargs) function_gen = cast(Generator[None, object, object], res) next(function_gen) # first yield teardowns.append(function_gen) except StopIteration: _raise_wrapfail(function_gen, "did not yield") else: - res = hook_impl.function(*args) + res = hook_impl.function(*args, **kwargs) if res is not None: results.append(res) if firstresult: # halt further impl calls diff --git a/testing/test_multicall.py b/testing/test_multicall.py index 7d8d8f28..5817e892 100644 --- a/testing/test_multicall.py +++ b/testing/test_multicall.py @@ -50,9 +50,15 @@ def test_keyword_args_with_defaultargs() -> None: def f(x, z=1): return x + z - reslist = MC([f], dict(x=23, y=24)) - assert reslist == [24] + @hookimpl + def f2(x, y=1): + return x + y + + reslist = MC([f, f2], dict(x=23, y=24)) + assert reslist == [23 + 24, 23 + 1] + reslist = MC([f2], dict(x=23)) + assert reslist == [23 + 1] def test_tags_call_error() -> None: @hookimpl From 483f014d8bc9b0301246eea8cdca146394d83cbc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 09:16:04 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pluggy/_callers.py | 6 +++++- testing/test_multicall.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pluggy/_callers.py b/src/pluggy/_callers.py index 2c404aaf..e931e71d 100644 --- a/src/pluggy/_callers.py +++ b/src/pluggy/_callers.py @@ -70,7 +70,11 @@ def _multicall( for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] - kwargs = dict((k, v) for k, v in caller_kwargs.items() if k in hook_impl.kwargnames) + kwargs = { + k: v + for k, v in caller_kwargs.items() + if k in hook_impl.kwargnames + } except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: diff --git a/testing/test_multicall.py b/testing/test_multicall.py index 5817e892..8607efc4 100644 --- a/testing/test_multicall.py +++ b/testing/test_multicall.py @@ -60,6 +60,7 @@ def f2(x, y=1): reslist = MC([f2], dict(x=23)) assert reslist == [23 + 1] + def test_tags_call_error() -> None: @hookimpl def f(x): From 97a4e15a9feb7cb1558a77472c6fd963eb37149f Mon Sep 17 00:00:00 2001 From: "shijie.jiao" Date: Thu, 25 Jan 2024 17:25:06 +0800 Subject: [PATCH 3/4] just format code --- src/pluggy/_callers.py | 51 +++++++++++------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/src/pluggy/_callers.py b/src/pluggy/_callers.py index e931e71d..f26045d1 100644 --- a/src/pluggy/_callers.py +++ b/src/pluggy/_callers.py @@ -4,44 +4,31 @@ from __future__ import annotations import warnings -from typing import cast from typing import Generator from typing import Mapping from typing import NoReturn from typing import Sequence from typing import Tuple from typing import Union +from typing import cast from ._hooks import HookImpl from ._result import HookCallError from ._result import Result from ._warnings import PluggyTeardownRaisedWarning - # Need to distinguish between old- and new-style hook wrappers. # Wrapping with a tuple is the fastest type-safe way I found to do it. -Teardown = Union[ - Tuple[Generator[None, Result[object], None], HookImpl], - Generator[None, object, object], -] - - -def _raise_wrapfail( - wrap_controller: ( - Generator[None, Result[object], None] | Generator[None, object, object] - ), - msg: str, -) -> NoReturn: +Teardown = Union[Tuple[Generator[None, Result[object], None], HookImpl], Generator[None, object, object],] + + +def _raise_wrapfail(wrap_controller: (Generator[None, Result[object], None] | Generator[None, object, object]), + msg: str, ) -> NoReturn: co = wrap_controller.gi_code - raise RuntimeError( - "wrap_controller at %r %s:%d %s" - % (co.co_name, co.co_filename, co.co_firstlineno, msg) - ) + raise RuntimeError("wrap_controller at %r %s:%d %s" % (co.co_name, co.co_filename, co.co_firstlineno, msg)) -def _warn_teardown_exception( - hook_name: str, hook_impl: HookImpl, e: BaseException -) -> None: +def _warn_teardown_exception(hook_name: str, hook_impl: HookImpl, e: BaseException) -> None: msg = "A plugin raised an exception during an old-style hookwrapper teardown.\n" msg += f"Plugin: {hook_impl.plugin_name}, Hook: {hook_name}\n" msg += f"{type(e).__name__}: {e}\n" @@ -49,12 +36,8 @@ def _warn_teardown_exception( warnings.warn(PluggyTeardownRaisedWarning(msg), stacklevel=5) -def _multicall( - hook_name: str, - hook_impls: Sequence[HookImpl], - caller_kwargs: Mapping[str, object], - firstresult: bool, -) -> object | list[object]: +def _multicall(hook_name: str, hook_impls: Sequence[HookImpl], caller_kwargs: Mapping[str, object], + firstresult: bool, ) -> object | list[object]: """Execute a call into multiple python functions/methods and return the result(s). @@ -70,17 +53,11 @@ def _multicall( for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] - kwargs = { - k: v - for k, v in caller_kwargs.items() - if k in hook_impl.kwargnames - } + kwargs = {k: v for k, v in caller_kwargs.items() if k in hook_impl.kwargnames} except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: - raise HookCallError( - f"hook call must provide argument {argname!r}" - ) + raise HookCallError(f"hook call must provide argument {argname!r}") if hook_impl.hookwrapper: only_new_style_wrappers = False @@ -147,9 +124,7 @@ def _multicall( # Slow path - need to support old-style wrappers. else: if firstresult: # first result hooks return a single value - outcome: Result[object | list[object]] = Result( - results[0] if results else None, exception - ) + outcome: Result[object | list[object]] = Result(results[0] if results else None, exception) else: outcome = Result(results, exception) From 3b47b51c8760ae1cd965e1b7017f6910e391522a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 09:26:52 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pluggy/_callers.py | 50 +++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/pluggy/_callers.py b/src/pluggy/_callers.py index f26045d1..3872a32c 100644 --- a/src/pluggy/_callers.py +++ b/src/pluggy/_callers.py @@ -4,13 +4,13 @@ from __future__ import annotations import warnings +from typing import cast from typing import Generator from typing import Mapping from typing import NoReturn from typing import Sequence from typing import Tuple from typing import Union -from typing import cast from ._hooks import HookImpl from ._result import HookCallError @@ -19,16 +19,28 @@ # Need to distinguish between old- and new-style hook wrappers. # Wrapping with a tuple is the fastest type-safe way I found to do it. -Teardown = Union[Tuple[Generator[None, Result[object], None], HookImpl], Generator[None, object, object],] - - -def _raise_wrapfail(wrap_controller: (Generator[None, Result[object], None] | Generator[None, object, object]), - msg: str, ) -> NoReturn: +Teardown = Union[ + Tuple[Generator[None, Result[object], None], HookImpl], + Generator[None, object, object], +] + + +def _raise_wrapfail( + wrap_controller: ( + Generator[None, Result[object], None] | Generator[None, object, object] + ), + msg: str, +) -> NoReturn: co = wrap_controller.gi_code - raise RuntimeError("wrap_controller at %r %s:%d %s" % (co.co_name, co.co_filename, co.co_firstlineno, msg)) + raise RuntimeError( + "wrap_controller at %r %s:%d %s" + % (co.co_name, co.co_filename, co.co_firstlineno, msg) + ) -def _warn_teardown_exception(hook_name: str, hook_impl: HookImpl, e: BaseException) -> None: +def _warn_teardown_exception( + hook_name: str, hook_impl: HookImpl, e: BaseException +) -> None: msg = "A plugin raised an exception during an old-style hookwrapper teardown.\n" msg += f"Plugin: {hook_impl.plugin_name}, Hook: {hook_name}\n" msg += f"{type(e).__name__}: {e}\n" @@ -36,8 +48,12 @@ def _warn_teardown_exception(hook_name: str, hook_impl: HookImpl, e: BaseExcepti warnings.warn(PluggyTeardownRaisedWarning(msg), stacklevel=5) -def _multicall(hook_name: str, hook_impls: Sequence[HookImpl], caller_kwargs: Mapping[str, object], - firstresult: bool, ) -> object | list[object]: +def _multicall( + hook_name: str, + hook_impls: Sequence[HookImpl], + caller_kwargs: Mapping[str, object], + firstresult: bool, +) -> object | list[object]: """Execute a call into multiple python functions/methods and return the result(s). @@ -53,11 +69,17 @@ def _multicall(hook_name: str, hook_impls: Sequence[HookImpl], caller_kwargs: Ma for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] - kwargs = {k: v for k, v in caller_kwargs.items() if k in hook_impl.kwargnames} + kwargs = { + k: v + for k, v in caller_kwargs.items() + if k in hook_impl.kwargnames + } except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: - raise HookCallError(f"hook call must provide argument {argname!r}") + raise HookCallError( + f"hook call must provide argument {argname!r}" + ) if hook_impl.hookwrapper: only_new_style_wrappers = False @@ -124,7 +146,9 @@ def _multicall(hook_name: str, hook_impls: Sequence[HookImpl], caller_kwargs: Ma # Slow path - need to support old-style wrappers. else: if firstresult: # first result hooks return a single value - outcome: Result[object | list[object]] = Result(results[0] if results else None, exception) + outcome: Result[object | list[object]] = Result( + results[0] if results else None, exception + ) else: outcome = Result(results, exception)