Skip to content

Commit 1de088c

Browse files
gh-74044: inspect.signature for wrappers around decorated bound methods (GH-736)
(cherry picked from commit dbf2faf) Co-authored-by: Anton Ryzhov <[email protected]>
1 parent 921f235 commit 1de088c

File tree

3 files changed

+12
-3
lines changed

3 files changed

+12
-3
lines changed

Lib/inspect.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,10 @@ def _signature_from_callable(obj, *,
24572457

24582458
# Was this function wrapped by a decorator?
24592459
if follow_wrapper_chains:
2460-
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))
2460+
# Unwrap until we find an explicit signature or a MethodType (which will be
2461+
# handled explicitly below).
2462+
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")
2463+
or isinstance(f, types.MethodType)))
24612464
if isinstance(obj, types.MethodType):
24622465
# If the unwrapped object is a *method*, we might want to
24632466
# skip its first parameter (self).

Lib/test/test_inspect.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,8 +2960,6 @@ def foo(a): pass
29602960
self.assertEqual(str(inspect.signature(foo)), '(a)')
29612961

29622962
def test_signature_on_decorated(self):
2963-
import functools
2964-
29652963
def decorator(func):
29662964
@functools.wraps(func)
29672965
def wrapper(*args, **kwargs) -> int:
@@ -2973,6 +2971,8 @@ class Foo:
29732971
def bar(self, a, b):
29742972
pass
29752973

2974+
bar = decorator(Foo().bar)
2975+
29762976
self.assertEqual(self.signature(Foo.bar),
29772977
((('self', ..., ..., "positional_or_keyword"),
29782978
('a', ..., ..., "positional_or_keyword"),
@@ -2991,6 +2991,11 @@ def bar(self, a, b):
29912991
# from "func" to "wrapper", hence no
29922992
# return_annotation
29932993

2994+
self.assertEqual(self.signature(bar),
2995+
((('a', ..., ..., "positional_or_keyword"),
2996+
('b', ..., ..., "positional_or_keyword")),
2997+
...))
2998+
29942999
# Test that we handle method wrappers correctly
29953000
def decorator(func):
29963001
@functools.wraps(func)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed bug where :func:`inspect.signature` reported incorrect arguments for decorated methods.

0 commit comments

Comments
 (0)