summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDong-hee Na <donghee.na92@gmail.com>2017-06-15 14:42:01 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2017-06-15 14:42:01 (GMT)
commitfb0825c2784f80689c4c00c3ede22958faaf512c (patch)
treea31eaa48daa4c2fd367f68101542e169d036bdea
parentc5a6fb654a280c7b17f1d348e2e40d62ca04c5d3 (diff)
downloadcpython-fb0825c2784f80689c4c00c3ede22958faaf512c.zip
cpython-fb0825c2784f80689c4c00c3ede22958faaf512c.tar.gz
cpython-fb0825c2784f80689c4c00c3ede22958faaf512c.tar.bz2
bpo-30149: Fix partialmethod without explicit self parameter (#1308) (#1663)
-rw-r--r--Lib/inspect.py13
-rw-r--r--Lib/test/test_inspect.py35
-rw-r--r--Misc/NEWS4
3 files changed, 48 insertions, 4 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 4a11006..424c945 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2220,11 +2220,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
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 2283000..95c5ead 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -1954,6 +1954,41 @@ class TestSignatureObject(unittest.TestCase):
('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")
diff --git a/Misc/NEWS b/Misc/NEWS
index 3fb908a..8b62d79 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -56,6 +56,10 @@ Extension Modules
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.