Skip to content

Commit c0c60d0

Browse files
gaogaotiantianmiss-islington
authored andcommitted
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 72d5dfa commit c0c60d0

File tree

3 files changed

+31
-11
lines changed

3 files changed

+31
-11
lines changed

Lib/inspect.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -2581,17 +2581,18 @@ def _signature_from_callable(obj, *,
25812581
factory_method = None
25822582
new = _signature_get_user_defined_method(obj, '__new__')
25832583
init = _signature_get_user_defined_method(obj, '__init__')
2584-
# Now we check if the 'obj' class has an own '__new__' method
2585-
if '__new__' in obj.__dict__:
2586-
factory_method = new
2587-
# or an own '__init__' method
2588-
elif '__init__' in obj.__dict__:
2589-
factory_method = init
2590-
# If not, we take inherited '__new__' or '__init__', if present
2591-
elif new is not None:
2592-
factory_method = new
2593-
elif init is not None:
2594-
factory_method = init
2584+
2585+
# Go through the MRO and see if any class has user-defined
2586+
# pure Python __new__ or __init__ method
2587+
for base in obj.__mro__:
2588+
# Now we check if the 'obj' class has an own '__new__' method
2589+
if new is not None and '__new__' in base.__dict__:
2590+
factory_method = new
2591+
break
2592+
# or an own '__init__' method
2593+
elif init is not None and '__init__' in base.__dict__:
2594+
factory_method = init
2595+
break
25952596

25962597
if factory_method is not None:
25972598
sig = _get_signature_of(factory_method)

Lib/test/test_inspect.py

+18
Original file line numberDiff line numberDiff line change
@@ -3927,6 +3927,24 @@ def __signature__():
39273927
('b', 2, ..., 'positional_or_keyword')),
39283928
...))
39293929

3930+
def test_signature_on_derived_classes(self):
3931+
# gh-105080: Make sure that signatures are consistent on derived classes
3932+
3933+
class B:
3934+
def __new__(self, *args, **kwargs):
3935+
return super().__new__(self)
3936+
def __init__(self, value):
3937+
self.value = value
3938+
3939+
class D1(B):
3940+
def __init__(self, value):
3941+
super().__init__(value)
3942+
3943+
class D2(D1):
3944+
pass
3945+
3946+
self.assertEqual(inspect.signature(D2), inspect.signature(D1))
3947+
39303948

39313949
class TestParameterObject(unittest.TestCase):
39323950
def test_signature_parameter_kinds(self):
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)