inspect.Signature.bind: Fix pos-only params with defaults; fix *args in named args #19140
Initial patch by Yann Kaiser (epsy).
This commit is contained in:
parent
8757ead38e
commit
38b0d5a778
|
@ -2258,6 +2258,8 @@ class Signature:
|
|||
parameters_ex = (param,)
|
||||
break
|
||||
else:
|
||||
# No default, not VAR_KEYWORD, not VAR_POSITIONAL,
|
||||
# not in `kwargs`
|
||||
if partial:
|
||||
parameters_ex = (param,)
|
||||
break
|
||||
|
@ -2296,19 +2298,17 @@ class Signature:
|
|||
# keyword arguments
|
||||
kwargs_param = None
|
||||
for param in itertools.chain(parameters_ex, parameters):
|
||||
if param.kind == _POSITIONAL_ONLY:
|
||||
# This should never happen in case of a properly built
|
||||
# Signature object (but let's have this check here
|
||||
# to ensure correct behaviour just in case)
|
||||
raise TypeError('{arg!r} parameter is positional only, '
|
||||
'but was passed as a keyword'. \
|
||||
format(arg=param.name))
|
||||
|
||||
if param.kind == _VAR_KEYWORD:
|
||||
# Memorize that we have a '**kwargs'-like parameter
|
||||
kwargs_param = param
|
||||
continue
|
||||
|
||||
if param.kind == _VAR_POSITIONAL:
|
||||
# Named arguments don't refer to '*args'-like parameters.
|
||||
# We only arrive here if the positional arguments ended
|
||||
# before reaching the last parameter before *args.
|
||||
continue
|
||||
|
||||
param_name = param.name
|
||||
try:
|
||||
arg_val = kwargs.pop(param_name)
|
||||
|
|
|
@ -2516,6 +2516,15 @@ class TestSignatureBind(unittest.TestCase):
|
|||
self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
|
||||
(1, 2, 4, 5, 6, {}))
|
||||
|
||||
self.assertEqual(self.call(test, 1, 2),
|
||||
(1, 2, 3, 42, 50, {}))
|
||||
|
||||
self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
|
||||
(1, 2, 3, 4, 5, {}))
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
|
||||
self.call(test, 1, 2, foo=4, bar=5, c_po=10)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "parameter is positional only"):
|
||||
self.call(test, 1, 2, c_po=4)
|
||||
|
||||
|
@ -2532,6 +2541,22 @@ class TestSignatureBind(unittest.TestCase):
|
|||
ba = sig.bind(1, self=2, b=3)
|
||||
self.assertEqual(ba.args, (1, 2, 3))
|
||||
|
||||
def test_signature_bind_vararg_name(self):
|
||||
def test(a, *args):
|
||||
return a, args
|
||||
sig = inspect.signature(test)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
|
||||
sig.bind(a=0, args=1)
|
||||
|
||||
def test(*args, **kwargs):
|
||||
return args, kwargs
|
||||
self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
|
||||
|
||||
sig = inspect.signature(test)
|
||||
ba = sig.bind(args=1)
|
||||
self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
|
||||
|
||||
|
||||
class TestBoundArguments(unittest.TestCase):
|
||||
def test_signature_bound_arguments_unhashable(self):
|
||||
|
|
Loading…
Reference in New Issue