Skip to content

Commit fb0825c

Browse files
corona10serhiy-storchaka
authored andcommitted
bpo-30149: Fix partialmethod without explicit self parameter (#1308) (#1663)
1 parent c5a6fb6 commit fb0825c

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
@@ -2220,11 +2220,16 @@ def _signature_from_callable(obj, *,
22202220
sigcls=sigcls)
22212221

22222222
sig = _signature_get_partial(wrapped_sig, partialmethod, (None,))
2223-
22242223
first_wrapped_param = tuple(wrapped_sig.parameters.values())[0]
2225-
new_params = (first_wrapped_param,) + tuple(sig.parameters.values())
2226-
2227-
return sig.replace(parameters=new_params)
2224+
if first_wrapped_param.kind is Parameter.VAR_POSITIONAL:
2225+
# First argument of the wrapped callable is `*args`, as in
2226+
# `partialmethod(lambda *args)`.
2227+
return sig
2228+
else:
2229+
sig_params = tuple(sig.parameters.values())
2230+
assert first_wrapped_param is not sig_params[0]
2231+
new_params = (first_wrapped_param,) + sig_params
2232+
return sig.replace(parameters=new_params)
22282233

22292234
if isfunction(obj) or _signature_is_functionlike(obj):
22302235
# 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
@@ -1954,6 +1954,41 @@ def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
19541954
('kwargs', ..., int, "var_keyword")),
19551955
...))
19561956

1957+
def test_signature_without_self(self):
1958+
def test_args_only(*args): # NOQA
1959+
pass
1960+
1961+
def test_args_kwargs_only(*args, **kwargs): # NOQA
1962+
pass
1963+
1964+
class A:
1965+
@classmethod
1966+
def test_classmethod(*args): # NOQA
1967+
pass
1968+
1969+
@staticmethod
1970+
def test_staticmethod(*args): # NOQA
1971+
pass
1972+
1973+
f1 = functools.partialmethod((test_classmethod), 1)
1974+
f2 = functools.partialmethod((test_args_only), 1)
1975+
f3 = functools.partialmethod((test_staticmethod), 1)
1976+
f4 = functools.partialmethod((test_args_kwargs_only),1)
1977+
1978+
self.assertEqual(self.signature(test_args_only),
1979+
((('args', ..., ..., 'var_positional'),), ...))
1980+
self.assertEqual(self.signature(test_args_kwargs_only),
1981+
((('args', ..., ..., 'var_positional'),
1982+
('kwargs', ..., ..., 'var_keyword')), ...))
1983+
self.assertEqual(self.signature(A.f1),
1984+
((('args', ..., ..., 'var_positional'),), ...))
1985+
self.assertEqual(self.signature(A.f2),
1986+
((('args', ..., ..., 'var_positional'),), ...))
1987+
self.assertEqual(self.signature(A.f3),
1988+
((('args', ..., ..., 'var_positional'),), ...))
1989+
self.assertEqual(self.signature(A.f4),
1990+
((('args', ..., ..., 'var_positional'),
1991+
('kwargs', ..., ..., 'var_keyword')), ...))
19571992
@cpython_only
19581993
@unittest.skipIf(MISSING_C_DOCSTRINGS,
19591994
"Signature information for builtins requires docstrings")

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ Extension Modules
5656
Library
5757
-------
5858

59+
- bpo-30149: inspect.signature() now supports callables with
60+
variable-argument parameters wrapped with partialmethod.
61+
Patch by Dong-hee Na.
62+
5963
- bpo-29931: Fixed comparison check for ipaddress.ip_interface objects.
6064
Patch by Sanjay Sundaresan.
6165

0 commit comments

Comments
 (0)