From 51e8df2ea682aeaef4ee42871c09479d699fa2de Mon Sep 17 00:00:00 2001 From: Eyal Achimeir Date: Wed, 3 Aug 2022 09:40:52 +0300 Subject: [PATCH 1/4] proposed fix for issue #358 --- src/pluggy/_hooks.py | 22 ++++++++++++++++++++-- testing/test_helpers.py | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/pluggy/_hooks.py b/src/pluggy/_hooks.py index 8316115e..d376eca4 100644 --- a/src/pluggy/_hooks.py +++ b/src/pluggy/_hooks.py @@ -245,11 +245,29 @@ def varnames(func: object) -> Tuple[Tuple[str, ...], Tuple[str, ...]]: return (), () try: # func MUST be a function or method here or we won't parse any args - spec = inspect.getfullargspec(func) + sig = inspect.signature(func.__func__ if inspect.ismethod(func) else func) except TypeError: return (), () - args, defaults = tuple(spec.args), spec.defaults + _valid_param_kinds = ( + inspect.Parameter.POSITIONAL_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD, + ) + _valid_params = { + name: param + for name, param in sig.parameters.items() + if param.kind in _valid_param_kinds + } + args = tuple(_valid_params) + defaults = ( + tuple( + param.default + for param in _valid_params.values() + if param.default is not param.empty + ) + or None + ) + if defaults: index = -len(defaults) args, kwargs = args[:index], tuple(args[index:]) diff --git a/testing/test_helpers.py b/testing/test_helpers.py index cf3f6d7e..0b24a0e2 100644 --- a/testing/test_helpers.py +++ b/testing/test_helpers.py @@ -1,3 +1,5 @@ +from functools import wraps +from typing import Callable from pluggy._hooks import varnames from pluggy._manager import _formatdef @@ -82,3 +84,17 @@ def function4(arg1, *args, **kwargs): pass assert _formatdef(function4) == "function4(arg1, *args, **kwargs)" + + +def test_varnames_decorator() -> None: + def my_decorator(func: Callable) -> Callable: + @wraps(func) + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + return wrapper + + @my_decorator + def example(a, b=123) -> None: + pass + + assert varnames(example) == (("a",), ("b",)) From d32e6c9c04f8793387a5b5811509e3abe0b53668 Mon Sep 17 00:00:00 2001 From: Eyal Achimeir Date: Wed, 3 Aug 2022 10:12:54 +0300 Subject: [PATCH 2/4] fixed type annotations --- testing/test_helpers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testing/test_helpers.py b/testing/test_helpers.py index 0b24a0e2..dfffa5be 100644 --- a/testing/test_helpers.py +++ b/testing/test_helpers.py @@ -1,5 +1,5 @@ from functools import wraps -from typing import Callable +from typing import Any, Callable, TypeVar, cast from pluggy._hooks import varnames from pluggy._manager import _formatdef @@ -87,11 +87,13 @@ def function4(arg1, *args, **kwargs): def test_varnames_decorator() -> None: - def my_decorator(func: Callable) -> Callable: + F = TypeVar('F', bound=Callable[..., Any]) + + def my_decorator(func: F) -> F: @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) - return wrapper + return cast(F, wrapper) @my_decorator def example(a, b=123) -> None: From 11443b4007895d7d9d560a7aa6bdbe8b6cda243b Mon Sep 17 00:00:00 2001 From: Eyal Achimeir Date: Wed, 3 Aug 2022 11:35:51 +0300 Subject: [PATCH 3/4] Added method decorator cases to `varnames` test. --- testing/test_helpers.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/testing/test_helpers.py b/testing/test_helpers.py index dfffa5be..d7ec6cea 100644 --- a/testing/test_helpers.py +++ b/testing/test_helpers.py @@ -99,4 +99,13 @@ def wrapper(*args, **kwargs): def example(a, b=123) -> None: pass + class Example: + @my_decorator + def example_method(self, x, y=1) -> None: + pass + + ex_inst = Example() + assert varnames(example) == (("a",), ("b",)) + assert varnames(Example.example_method) == (("x",), ("y",)) + assert varnames(ex_inst.example_method) == (("x",), ("y",)) From 7372a055bf5752297d35262be62e568aa98b5c31 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 6 Nov 2022 11:58:31 -0300 Subject: [PATCH 4/4] Fix linting --- src/pluggy/_hooks.py | 7 +++++-- testing/test_helpers.py | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pluggy/_hooks.py b/src/pluggy/_hooks.py index d376eca4..73f0e807 100644 --- a/src/pluggy/_hooks.py +++ b/src/pluggy/_hooks.py @@ -244,8 +244,11 @@ def varnames(func: object) -> Tuple[Tuple[str, ...], Tuple[str, ...]]: except Exception: return (), () - try: # func MUST be a function or method here or we won't parse any args - sig = inspect.signature(func.__func__ if inspect.ismethod(func) else func) + try: + # func MUST be a function or method here or we won't parse any args. + sig = inspect.signature( + func.__func__ if inspect.ismethod(func) else func # type:ignore[arg-type] + ) except TypeError: return (), () diff --git a/testing/test_helpers.py b/testing/test_helpers.py index d7ec6cea..4ddd945a 100644 --- a/testing/test_helpers.py +++ b/testing/test_helpers.py @@ -87,12 +87,13 @@ def function4(arg1, *args, **kwargs): def test_varnames_decorator() -> None: - F = TypeVar('F', bound=Callable[..., Any]) + F = TypeVar("F", bound=Callable[..., Any]) def my_decorator(func: F) -> F: @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) + return cast(F, wrapper) @my_decorator