Skip to content

Commit

Permalink
Document follow_wrapped case
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Nov 22, 2023
1 parent 9e75439 commit f18f8fc
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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,
... )
<Signature (self, arg: int) -> None>

>>> inspect313.signature(
... func,
... skip_bound_arg=False,
... follow_wrapped=False,
... )
<Signature (*args, **kwargs) -> None>

```

## License
Expand Down
36 changes: 33 additions & 3 deletions tests/test_signature.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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:
...
Expand All @@ -41,6 +58,7 @@ def cl(cls, arg3: int, /, *, arg4: str = "a") -> None:
"obj",
[
_function,
_decorated_function,
_Class,
_Class(),
_Class.method,
Expand All @@ -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"),
Expand All @@ -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
)

0 comments on commit f18f8fc

Please sign in to comment.