diff -r 220b34cbd711 Lib/inspect.py --- a/Lib/inspect.py Sun Sep 29 18:59:27 2013 -0700 +++ b/Lib/inspect.py Tue Oct 01 21:48:01 2013 +0100 @@ -2068,19 +2068,17 @@ # 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) @@ -2095,6 +2093,14 @@ format(arg=param_name)) from None else: + 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)) + arguments[param_name] = arg_val if kwargs: diff -r 220b34cbd711 Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Sun Sep 29 18:59:27 2013 -0700 +++ b/Lib/test/test_inspect.py Tue Oct 01 21:48:01 2013 +0100 @@ -2299,6 +2299,12 @@ 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, "parameter is positional only"): self.call(test, 1, 2, c_po=4) @@ -2315,6 +2321,28 @@ 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(a=0, *args): + return a, args + sig = inspect.signature(test) + with self.assertRaisesRegex(TypeError, "too many keyword arguments"): + sig.bind(a=0, args=1) + with self.assertRaisesRegex(TypeError, "too many keyword arguments"): + sig.bind(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):