diff --git a/README.md b/README.md index 12e53f8..2ed1339 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ need this package to have the same functionality. Here's how `getfullargspec` is different from regular `signature` call: +- the `self` / `cls` parameter is always reported, even for bound methods + ```python >>> import inspect @@ -43,13 +45,44 @@ FullArgSpec(args=['self', 'arg'], varargs=None, varkw=None, defaults=None, kwonl ``` +- wrapper chains defined by `__wrapped__` *not* unwrapped automatically + +```python +>>> import functools + +>>> def some_decorator(f): +... @functools.wraps(f) +... def wrapper(*args, **kwargs): +... return f(*args, **kwargs) +... return wrapper + +>>> @some_decorator +... def func(a: int, /, b: str) -> None: ... + +>>> inspect.getfullargspec(func) +FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None}) + +``` + Here's how you can migrate: ```python >>> import inspect313 ->>> inspect313.signature(A().method, skip_bound_arg=False) + +>>> inspect313.signature( +... A().method, +... skip_bound_arg=False, +... follow_wrapped=False, +... ) None> +>>> inspect313.signature( +... func, +... skip_bound_arg=False, +... follow_wrapped=False, +... ) + None> + ``` ## License diff --git a/tests/test_signature.py b/tests/test_signature.py index 228fc0f..ff66945 100644 --- a/tests/test_signature.py +++ b/tests/test_signature.py @@ -1,9 +1,21 @@ +import functools import inspect +from typing import Any, TypeVar, Callable, cast import pytest import inspect313 +_Func = TypeVar("_Func", bound=Callable[..., Any]) + + +def _decorator(func: _Func) -> _Func: + @functools.wraps(func) + def wrapper(*args: Any, **kwargs: Any) -> Any: + return func(*args, **kwargs) + + return cast(_Func, wrapper) + def _function( a: int, @@ -18,6 +30,11 @@ def _function( """Function to test.""" +@_decorator # will have `__wrapped__` set +def _decorated_function(a: int, /, b: str) -> None: + ... + + class _Class: def __init__(self, default: int = 0) -> None: ... @@ -41,6 +58,7 @@ def cl(cls, arg3: int, /, *, arg4: str = "a") -> None: "obj", [ _function, + _decorated_function, _Class, _Class(), _Class.method, @@ -66,6 +84,7 @@ def test_signature_default(obj) -> None: _function, "(a: int, /, b: str, c: int = 0, *d, e: bool, f: bool = True, **kwargs) -> None", ), + (_decorated_function, "(*args, **kwargs) -> None"), (_Class, "(self, default: int = 0) -> None"), (_Class(), "(self, c: int, *, d: str) -> None"), (_Class.method, "(self, e, /, *args, **kwargs) -> None"), @@ -76,10 +95,21 @@ def test_signature_default(obj) -> None: (_Class().cl, "(cls, arg3: int, /, *, arg4: str = 'a') -> None"), ], ) -def test_signature_present_bound_arg(obj, expected: str) -> None: +def test_signature_to_migrate(obj, expected: str) -> None: """Test that you keep bound args.""" - assert str(inspect313.signature(obj, skip_bound_arg=False)) == expected assert ( - str(inspect313.Signature.from_callable(obj, skip_bound_arg=False)) + str( + inspect313.signature( + obj, skip_bound_arg=False, follow_wrapped=False + ) + ) + == expected + ) + assert ( + str( + inspect313.Signature.from_callable( + obj, skip_bound_arg=False, follow_wrapped=False + ) + ) == expected )