mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
inspect.signautre: Fix functools.partial support. Issue #21117
This commit is contained in:
parent
1d1d95bf83
commit
3f73ca23cf
3 changed files with 146 additions and 97 deletions
|
@ -1689,13 +1689,11 @@ class TestSignatureObject(unittest.TestCase):
|
|||
foo_partial = functools.partial(foo, a=1)
|
||||
|
||||
sig = inspect.signature(foo_partial)
|
||||
self.assertTrue(sig.parameters['a']._partial_kwarg)
|
||||
|
||||
for ver in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(pickle_ver=ver, subclass=False):
|
||||
sig_pickled = pickle.loads(pickle.dumps(sig, ver))
|
||||
self.assertEqual(sig, sig_pickled)
|
||||
self.assertTrue(sig_pickled.parameters['a']._partial_kwarg)
|
||||
|
||||
# Test that basic sub-classing works
|
||||
sig = inspect.signature(foo)
|
||||
|
@ -2005,6 +2003,8 @@ class TestSignatureObject(unittest.TestCase):
|
|||
def test_signature_on_partial(self):
|
||||
from functools import partial
|
||||
|
||||
Parameter = inspect.Parameter
|
||||
|
||||
def test():
|
||||
pass
|
||||
|
||||
|
@ -2040,15 +2040,22 @@ class TestSignatureObject(unittest.TestCase):
|
|||
|
||||
self.assertEqual(self.signature(partial(test, b=1, c=2)),
|
||||
((('a', ..., ..., "positional_or_keyword"),
|
||||
('b', 1, ..., "positional_or_keyword"),
|
||||
('b', 1, ..., "keyword_only"),
|
||||
('c', 2, ..., "keyword_only"),
|
||||
('d', ..., ..., "keyword_only")),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
|
||||
((('b', 1, ..., "positional_or_keyword"),
|
||||
((('b', 1, ..., "keyword_only"),
|
||||
('c', 2, ..., "keyword_only"),
|
||||
('d', ..., ..., "keyword_only"),),
|
||||
('d', ..., ..., "keyword_only")),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(test, a=1)),
|
||||
((('a', 1, ..., "keyword_only"),
|
||||
('b', ..., ..., "keyword_only"),
|
||||
('c', ..., ..., "keyword_only"),
|
||||
('d', ..., ..., "keyword_only")),
|
||||
...))
|
||||
|
||||
def test(a, *args, b, **kwargs):
|
||||
|
@ -2060,13 +2067,18 @@ class TestSignatureObject(unittest.TestCase):
|
|||
('kwargs', ..., ..., "var_keyword")),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(test, a=1)),
|
||||
((('a', 1, ..., "keyword_only"),
|
||||
('b', ..., ..., "keyword_only"),
|
||||
('kwargs', ..., ..., "var_keyword")),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(test, 1, 2, 3)),
|
||||
((('args', ..., ..., "var_positional"),
|
||||
('b', ..., ..., "keyword_only"),
|
||||
('kwargs', ..., ..., "var_keyword")),
|
||||
...))
|
||||
|
||||
|
||||
self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
|
||||
((('args', ..., ..., "var_positional"),
|
||||
('b', ..., ..., "keyword_only"),
|
||||
|
@ -2113,7 +2125,7 @@ class TestSignatureObject(unittest.TestCase):
|
|||
return a
|
||||
_foo = partial(partial(foo, a=10), a=20)
|
||||
self.assertEqual(self.signature(_foo),
|
||||
((('a', 20, ..., "positional_or_keyword"),),
|
||||
((('a', 20, ..., "keyword_only"),),
|
||||
...))
|
||||
# check that we don't have any side-effects in signature(),
|
||||
# and the partial object is still functioning
|
||||
|
@ -2122,42 +2134,87 @@ class TestSignatureObject(unittest.TestCase):
|
|||
def foo(a, b, c):
|
||||
return a, b, c
|
||||
_foo = partial(partial(foo, 1, b=20), b=30)
|
||||
|
||||
self.assertEqual(self.signature(_foo),
|
||||
((('b', 30, ..., "positional_or_keyword"),
|
||||
('c', ..., ..., "positional_or_keyword")),
|
||||
((('b', 30, ..., "keyword_only"),
|
||||
('c', ..., ..., "keyword_only")),
|
||||
...))
|
||||
self.assertEqual(_foo(c=10), (1, 30, 10))
|
||||
_foo = partial(_foo, 2) # now 'b' has two values -
|
||||
# positional and keyword
|
||||
with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
|
||||
inspect.signature(_foo)
|
||||
|
||||
def foo(a, b, c, *, d):
|
||||
return a, b, c, d
|
||||
_foo = partial(partial(foo, d=20, c=20), b=10, d=30)
|
||||
self.assertEqual(self.signature(_foo),
|
||||
((('a', ..., ..., "positional_or_keyword"),
|
||||
('b', 10, ..., "positional_or_keyword"),
|
||||
('c', 20, ..., "positional_or_keyword"),
|
||||
('d', 30, ..., "keyword_only")),
|
||||
('b', 10, ..., "keyword_only"),
|
||||
('c', 20, ..., "keyword_only"),
|
||||
('d', 30, ..., "keyword_only"),
|
||||
),
|
||||
...))
|
||||
ba = inspect.signature(_foo).bind(a=200, b=11)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
|
||||
|
||||
def foo(a=1, b=2, c=3):
|
||||
return a, b, c
|
||||
_foo = partial(foo, a=10, c=13)
|
||||
ba = inspect.signature(_foo).bind(11)
|
||||
_foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
|
||||
|
||||
ba = inspect.signature(_foo).bind(a=11)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
|
||||
|
||||
ba = inspect.signature(_foo).bind(11, 12)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
|
||||
|
||||
ba = inspect.signature(_foo).bind(11, b=12)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
|
||||
|
||||
ba = inspect.signature(_foo).bind(b=12)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
|
||||
_foo = partial(_foo, b=10)
|
||||
ba = inspect.signature(_foo).bind(12, 14)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
|
||||
|
||||
_foo = partial(_foo, b=10, c=20)
|
||||
ba = inspect.signature(_foo).bind(12)
|
||||
self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
|
||||
|
||||
|
||||
def foo(a, b, c, d, **kwargs):
|
||||
pass
|
||||
sig = inspect.signature(foo)
|
||||
params = sig.parameters.copy()
|
||||
params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
|
||||
params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
|
||||
foo.__signature__ = inspect.Signature(params.values())
|
||||
sig = inspect.signature(foo)
|
||||
self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
|
||||
|
||||
self.assertEqual(self.signature(partial(foo, 1)),
|
||||
((('b', ..., ..., 'positional_only'),
|
||||
('c', ..., ..., 'positional_or_keyword'),
|
||||
('d', ..., ..., 'positional_or_keyword'),
|
||||
('kwargs', ..., ..., 'var_keyword')),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(foo, 1, 2)),
|
||||
((('c', ..., ..., 'positional_or_keyword'),
|
||||
('d', ..., ..., 'positional_or_keyword'),
|
||||
('kwargs', ..., ..., 'var_keyword')),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
|
||||
((('d', ..., ..., 'positional_or_keyword'),
|
||||
('kwargs', ..., ..., 'var_keyword')),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
|
||||
((('c', 3, ..., 'keyword_only'),
|
||||
('d', ..., ..., 'keyword_only'),
|
||||
('kwargs', ..., ..., 'var_keyword')),
|
||||
...))
|
||||
|
||||
self.assertEqual(self.signature(partial(foo, 1, c=3)),
|
||||
((('b', ..., ..., 'positional_only'),
|
||||
('c', 3, ..., 'keyword_only'),
|
||||
('d', ..., ..., 'keyword_only'),
|
||||
('kwargs', ..., ..., 'var_keyword')),
|
||||
...))
|
||||
|
||||
def test_signature_on_partialmethod(self):
|
||||
from functools import partialmethod
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue