Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2241,11 +2241,16 @@ def _signature_from_callable(obj, *,
sigcls=sigcls)

sig = _signature_get_partial(wrapped_sig, partialmethod, (None,))

first_wrapped_param = tuple(wrapped_sig.parameters.values())[0]
new_params = (first_wrapped_param,) + tuple(sig.parameters.values())

return sig.replace(parameters=new_params)
if first_wrapped_param.kind is Parameter.VAR_POSITIONAL:
# First argument of the wrapped callable is `*args`, as in
# `partialmethod(lambda *args)`.
return sig
else:
sig_params = tuple(sig.parameters.values())
assert first_wrapped_param is not sig_params[0]
new_params = (first_wrapped_param,) + sig_params
return sig.replace(parameters=new_params)

if isfunction(obj) or _signature_is_functionlike(obj):
# If it's a pure Python function, or an object that is duck type
Expand Down
35 changes: 35 additions & 0 deletions Lib/test/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,41 @@ def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
('kwargs', ..., int, "var_keyword")),
...))

def test_signature_without_self(self):
def test_args_only(*args): # NOQA
pass

def test_args_kwargs_only(*args, **kwargs): # NOQA
pass

class A:
@classmethod
def test_classmethod(*args): # NOQA
pass

@staticmethod
def test_staticmethod(*args): # NOQA
pass

f1 = functools.partialmethod((test_classmethod), 1)
f2 = functools.partialmethod((test_args_only), 1)
f3 = functools.partialmethod((test_staticmethod), 1)
f4 = functools.partialmethod((test_args_kwargs_only),1)

self.assertEqual(self.signature(test_args_only),
((('args', ..., ..., 'var_positional'),), ...))
self.assertEqual(self.signature(test_args_kwargs_only),
((('args', ..., ..., 'var_positional'),
('kwargs', ..., ..., 'var_keyword')), ...))
self.assertEqual(self.signature(A.f1),
((('args', ..., ..., 'var_positional'),), ...))
self.assertEqual(self.signature(A.f2),
((('args', ..., ..., 'var_positional'),), ...))
self.assertEqual(self.signature(A.f3),
((('args', ..., ..., 'var_positional'),), ...))
self.assertEqual(self.signature(A.f4),
((('args', ..., ..., 'var_positional'),
('kwargs', ..., ..., 'var_keyword')), ...))
@cpython_only
@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
Expand Down
4 changes: 4 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Core and Builtins
Library
-------

- bpo-30149: inspect.signature() now supports callables with
variable-argument parameters wrapped with partialmethod.
Patch by Dong-hee Na.

- bpo-29931: Fixed comparison check for ipaddress.ip_interface objects.
Patch by Sanjay Sundaresan.

Expand Down