Skip to content

Commit e6f066a

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 ee405e3 commit e6f066a

File tree

3 files changed

+12
-3
lines changed

3 files changed

+12
-3
lines changed

Lib/inspect.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -2406,7 +2406,10 @@ def _signature_from_callable(obj, *,
24062406

24072407
# Was this function wrapped by a decorator?
24082408
if follow_wrapper_chains:
2409-
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))
2409+
# Unwrap until we find an explicit signature or a MethodType (which will be
2410+
# handled explicitly below).
2411+
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")
2412+
or isinstance(f, types.MethodType)))
24102413
if isinstance(obj, types.MethodType):
24112414
# If the unwrapped object is a *method*, we might want to
24122415
# skip its first parameter (self).

Lib/test/test_inspect.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -2957,8 +2957,6 @@ def foo(a): pass
29572957
self.assertEqual(str(inspect.signature(foo)), '(a)')
29582958

29592959
def test_signature_on_decorated(self):
2960-
import functools
2961-
29622960
def decorator(func):
29632961
@functools.wraps(func)
29642962
def wrapper(*args, **kwargs) -> int:
@@ -2970,6 +2968,8 @@ class Foo:
29702968
def bar(self, a, b):
29712969
pass
29722970

2971+
bar = decorator(Foo().bar)
2972+
29732973
self.assertEqual(self.signature(Foo.bar),
29742974
((('self', ..., ..., "positional_or_keyword"),
29752975
('a', ..., ..., "positional_or_keyword"),
@@ -2988,6 +2988,11 @@ def bar(self, a, b):
29882988
# from "func" to "wrapper", hence no
29892989
# return_annotation
29902990

2991+
self.assertEqual(self.signature(bar),
2992+
((('a', ..., ..., "positional_or_keyword"),
2993+
('b', ..., ..., "positional_or_keyword")),
2994+
...))
2995+
29912996
# Test that we handle method wrappers correctly
29922997
def decorator(func):
29932998
@functools.wraps(func)
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)