Skip to content

Commit 3b2a8cc

Browse files
[3.11] pythongh-105080: Fixed inconsistent signature on derived classes (pythonGH-105217).
(cherry picked from commit 9ad199b) Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
1 parent c5dafea commit 3b2a8cc

3 files changed

Lines changed: 31 additions & 11 deletions

File tree

Lib/inspect.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,17 +2536,18 @@ def _signature_from_callable(obj, *,
25362536
factory_method = None
25372537
new = _signature_get_user_defined_method(obj, '__new__')
25382538
init = _signature_get_user_defined_method(obj, '__init__')
2539-
# Now we check if the 'obj' class has an own '__new__' method
2540-
if '__new__' in obj.__dict__:
2541-
factory_method = new
2542-
# or an own '__init__' method
2543-
elif '__init__' in obj.__dict__:
2544-
factory_method = init
2545-
# If not, we take inherited '__new__' or '__init__', if present
2546-
elif new is not None:
2547-
factory_method = new
2548-
elif init is not None:
2549-
factory_method = init
2539+
2540+
# Go through the MRO and see if any class has user-defined
2541+
# pure Python __new__ or __init__ method
2542+
for base in obj.__mro__:
2543+
# Now we check if the 'obj' class has an own '__new__' method
2544+
if new is not None and '__new__' in base.__dict__:
2545+
factory_method = new
2546+
break
2547+
# or an own '__init__' method
2548+
elif init is not None and '__init__' in base.__dict__:
2549+
factory_method = init
2550+
break
25502551

25512552
if factory_method is not None:
25522553
sig = _get_signature_of(factory_method)

Lib/test/test_inspect.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3656,6 +3656,24 @@ def foo(): pass
36563656
self.assertEqual(signature_func(foo), inspect.Signature())
36573657
self.assertEqual(inspect.get_annotations(foo), {})
36583658

3659+
def test_signature_on_derived_classes(self):
3660+
# gh-105080: Make sure that signatures are consistent on derived classes
3661+
3662+
class B:
3663+
def __new__(self, *args, **kwargs):
3664+
return super().__new__(self)
3665+
def __init__(self, value):
3666+
self.value = value
3667+
3668+
class D1(B):
3669+
def __init__(self, value):
3670+
super().__init__(value)
3671+
3672+
class D2(D1):
3673+
pass
3674+
3675+
self.assertEqual(inspect.signature(D2), inspect.signature(D1))
3676+
36593677

36603678
class TestParameterObject(unittest.TestCase):
36613679
def test_signature_parameter_kinds(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed inconsistent signature on derived classes for :func:`inspect.signature`

0 commit comments

Comments
 (0)