Skip to content

Commit e45ea37

Browse files
corona10serhiy-storchaka
authored andcommitted
bpo-30149: Fix partialmethod without explicit self parameter (#1308) (#1662)
1 parent cf58dfb commit e45ea37

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

Lib/inspect.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,11 +2241,16 @@ def _signature_from_callable(obj, *,
22412241
sigcls=sigcls)
22422242

22432243
sig = _signature_get_partial(wrapped_sig, partialmethod, (None,))
2244-
22452244
first_wrapped_param = tuple(wrapped_sig.parameters.values())[0]
2246-
new_params = (first_wrapped_param,) + tuple(sig.parameters.values())
2247-
2248-
return sig.replace(parameters=new_params)
2245+
if first_wrapped_param.kind is Parameter.VAR_POSITIONAL:
2246+
# First argument of the wrapped callable is `*args`, as in
2247+
# `partialmethod(lambda *args)`.
2248+
return sig
2249+
else:
2250+
sig_params = tuple(sig.parameters.values())
2251+
assert first_wrapped_param is not sig_params[0]
2252+
new_params = (first_wrapped_param,) + sig_params
2253+
return sig.replace(parameters=new_params)
22492254

22502255
if isfunction(obj) or _signature_is_functionlike(obj):
22512256
# If it's a pure Python function, or an object that is duck type

Lib/test/test_inspect.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,6 +1989,41 @@ def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
19891989
('kwargs', ..., int, "var_keyword")),
19901990
...))
19911991

1992+
def test_signature_without_self(self):
1993+
def test_args_only(*args): # NOQA
1994+
pass
1995+
1996+
def test_args_kwargs_only(*args, **kwargs): # NOQA
1997+
pass
1998+
1999+
class A:
2000+
@classmethod
2001+
def test_classmethod(*args): # NOQA
2002+
pass
2003+
2004+
@staticmethod
2005+
def test_staticmethod(*args): # NOQA
2006+
pass
2007+
2008+
f1 = functools.partialmethod((test_classmethod), 1)
2009+
f2 = functools.partialmethod((test_args_only), 1)
2010+
f3 = functools.partialmethod((test_staticmethod), 1)
2011+
f4 = functools.partialmethod((test_args_kwargs_only),1)
2012+
2013+
self.assertEqual(self.signature(test_args_only),
2014+
((('args', ..., ..., 'var_positional'),), ...))
2015+
self.assertEqual(self.signature(test_args_kwargs_only),
2016+
((('args', ..., ..., 'var_positional'),
2017+
('kwargs', ..., ..., 'var_keyword')), ...))
2018+
self.assertEqual(self.signature(A.f1),
2019+
((('args', ..., ..., 'var_positional'),), ...))
2020+
self.assertEqual(self.signature(A.f2),
2021+
((('args', ..., ..., 'var_positional'),), ...))
2022+
self.assertEqual(self.signature(A.f3),
2023+
((('args', ..., ..., 'var_positional'),), ...))
2024+
self.assertEqual(self.signature(A.f4),
2025+
((('args', ..., ..., 'var_positional'),
2026+
('kwargs', ..., ..., 'var_keyword')), ...))
19922027
@cpython_only
19932028
@unittest.skipIf(MISSING_C_DOCSTRINGS,
19942029
"Signature information for builtins requires docstrings")

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ Core and Builtins
5151
Library
5252
-------
5353

54+
- bpo-30149: inspect.signature() now supports callables with
55+
variable-argument parameters wrapped with partialmethod.
56+
Patch by Dong-hee Na.
57+
5458
- bpo-29931: Fixed comparison check for ipaddress.ip_interface objects.
5559
Patch by Sanjay Sundaresan.
5660

0 commit comments

Comments
 (0)