diff options
author | Anton Ryzhov <anton@ryzhov.me> | 2022-11-10 12:32:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-10 12:32:01 (GMT) |
commit | dbf2faf579b4094387d65ee41f049456ca67c446 (patch) | |
tree | 779bdc9a67884d980095027bb2a2d6495545ec3c /Lib | |
parent | 9d692841691590c25e6cf5b2250a594d3bf54825 (diff) | |
download | cpython-dbf2faf579b4094387d65ee41f049456ca67c446.zip cpython-dbf2faf579b4094387d65ee41f049456ca67c446.tar.gz cpython-dbf2faf579b4094387d65ee41f049456ca67c446.tar.bz2 |
gh-74044: inspect.signature for wrappers around decorated bound methods (GH-736)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/inspect.py | 5 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 9 |
2 files changed, 11 insertions, 3 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index f6750c3..d0015aa 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2442,7 +2442,10 @@ def _signature_from_callable(obj, *, # Was this function wrapped by a decorator? if follow_wrapper_chains: - obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + # Unwrap until we find an explicit signature or a MethodType (which will be + # handled explicitly below). + obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__") + or isinstance(f, types.MethodType))) if isinstance(obj, types.MethodType): # If the unwrapped object is a *method*, we might want to # skip its first parameter (self). diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index cfc6e41..3f5c299 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2960,8 +2960,6 @@ class TestSignatureObject(unittest.TestCase): self.assertEqual(str(inspect.signature(foo)), '(a)') def test_signature_on_decorated(self): - import functools - def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs) -> int: @@ -2973,6 +2971,8 @@ class TestSignatureObject(unittest.TestCase): def bar(self, a, b): pass + bar = decorator(Foo().bar) + self.assertEqual(self.signature(Foo.bar), ((('self', ..., ..., "positional_or_keyword"), ('a', ..., ..., "positional_or_keyword"), @@ -2991,6 +2991,11 @@ class TestSignatureObject(unittest.TestCase): # from "func" to "wrapper", hence no # return_annotation + self.assertEqual(self.signature(bar), + ((('a', ..., ..., "positional_or_keyword"), + ('b', ..., ..., "positional_or_keyword")), + ...)) + # Test that we handle method wrappers correctly def decorator(func): @functools.wraps(func) |