diff -r af793c7580f1 Lib/inspect.py --- a/Lib/inspect.py Wed Jun 17 10:09:24 2015 -0500 +++ b/Lib/inspect.py Fri Jun 19 13:56:44 2015 -0400 @@ -2743,7 +2743,7 @@ def __ne__(self, other): return not self.__eq__(other) - def _bind(self, args, kwargs, *, partial=False): + def _bind(self, args, kwargs, *, partial=False, _stop_iter=object()): """Private method. Don't use directly.""" arguments = OrderedDict() @@ -2755,13 +2755,11 @@ while True: # Let's iterate through the positional arguments and corresponding # parameters - try: - arg_val = next(arg_vals) - except StopIteration: + arg_val = next(arg_vals, _stop_iter) + if arg_val is _stop_iter: # No more positional arguments - try: - param = next(parameters) - except StopIteration: + param = next(parameters, _stop_iter) + if param is _stop_iter: # No more parameters. That's it. Just need to check that # we have no `kwargs` after this while loop break @@ -2775,7 +2773,7 @@ msg = '{arg!r} parameter is positional only, ' \ 'but was passed as a keyword' msg = msg.format(arg=param.name) - raise TypeError(msg) from None + raise TypeError(msg) parameters_ex = (param,) break elif (param.kind == _VAR_KEYWORD or @@ -2794,19 +2792,17 @@ else: msg = 'missing a required argument: {arg!r}' msg = msg.format(arg=param.name) - raise TypeError(msg) from None + raise TypeError(msg) else: # We have a positional argument to process - try: - param = next(parameters) - except StopIteration: - raise TypeError('too many positional arguments') from None + param = next(parameters, _stop_iter) + if param is _stop_iter: + raise TypeError('too many positional arguments') else: if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): # Looks like we have no parameter for this positional # argument - raise TypeError( - 'too many positional arguments') from None + raise TypeError('too many positional arguments') if param.kind == _VAR_POSITIONAL: # We have an '*args'-like argument, let's fill it with @@ -2820,7 +2816,7 @@ if param.name in kwargs: raise TypeError( 'multiple values for argument {arg!r}'.format( - arg=param.name)) from None + arg=param.name)) arguments[param.name] = arg_val @@ -2840,9 +2836,8 @@ continue param_name = param.name - try: - arg_val = kwargs.pop(param_name) - except KeyError: + arg_val = kwargs.pop(param_name, _stop_iter) + if arg_val is _stop_iter: # We have no value for this parameter. It's fine though, # if it has a default value, or it is an '*args'-like # parameter, left alone by the processing of positional @@ -2850,7 +2845,7 @@ if (not partial and param.kind != _VAR_POSITIONAL and param.default is _empty): raise TypeError('missing a required argument: {arg!r}'. \ - format(arg=param_name)) from None + format(arg=param_name)) else: if param.kind == _POSITIONAL_ONLY: diff -r af793c7580f1 Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Wed Jun 17 10:09:24 2015 -0500 +++ b/Lib/test/test_inspect.py Fri Jun 19 13:56:44 2015 -0400 @@ -2924,7 +2924,12 @@ self.assertEqual(self.call(test), 42) with self.assertRaisesRegex(TypeError, 'too many positional arguments'): - self.call(test, 1) + try: + self.call(test, 1) + except TypeError as ex: + self.assertIsNone(ex.__cause__) + self.assertIsNone(ex.__context__) + raise with self.assertRaisesRegex(TypeError, 'too many positional arguments'): self.call(test, 1, spam=10) with self.assertRaisesRegex( @@ -2960,7 +2965,12 @@ with self.assertRaisesRegex(TypeError, "missing a required argument: 'a'"): - self.call(test) + try: + self.call(test) + except TypeError as ex: + self.assertIsNone(ex.__context__) + self.assertIsNone(ex.__cause__) + raise def test(a, b, c=10): return a, b, c @@ -2991,7 +3001,12 @@ with self.assertRaisesRegex(TypeError, "multiple values for argument 'c'"): - self.call(test, 1, 2, 3, c=4) + try: + self.call(test, 1, 2, 3, c=4) + except TypeError as ex: + self.assertIsNone(ex.__context__) + self.assertIsNone(ex.__cause__) + raise def test_signature_bind_just_kwargs(self): def test(**kwargs): @@ -3033,7 +3048,12 @@ return foo with self.assertRaisesRegex(TypeError, "missing a required argument: 'bar'"): - self.call(test, 1) + try: + self.call(test, 1) + except TypeError as ex: + self.assertIsNone(ex.__context__) + self.assertIsNone(ex.__cause__) + raise def test(foo, *, bar): return foo, bar