diff -r bf9f39e5d672 Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py Thu Aug 04 17:26:00 2016 +0300 +++ b/Lib/test/test_exceptions.py Fri Aug 05 00:27:21 2016 +0800 @@ -1103,6 +1103,10 @@ exc = ImportError(arg) self.assertEqual(str(arg), str(exc)) + def test_invalid_keyword_argument(self): + self.assertRaisesRegex(TypeError, "invalid keyword argument", + ImportError, foo=1) + if __name__ == '__main__': unittest.main() diff -r bf9f39e5d672 Objects/exceptions.c --- a/Objects/exceptions.c Thu Aug 04 17:26:00 2016 +0300 +++ b/Objects/exceptions.c Fri Aug 05 00:27:21 2016 +0800 @@ -613,27 +613,35 @@ ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds) { PyObject *msg = NULL; - PyObject *name = NULL; - PyObject *path = NULL; - -/* Macro replacement doesn't allow ## to start the first line of a macro, - so we move the assignment and NULL check into the if-statement. */ -#define GET_KWD(kwd) { \ - kwd = PyDict_GetItemString(kwds, #kwd); \ - if (kwd) { \ - Py_INCREF(kwd); \ - Py_XSETREF(self->kwd, kwd); \ - if (PyDict_DelItemString(kwds, #kwd)) \ - return -1; \ - } \ + PyObject *key = NULL; + PyObject *value = NULL; + Py_ssize_t pos = 0; + _Py_IDENTIFIER(name); + _Py_IDENTIFIER(path); + + if (kwds) { + if (!PyArg_ValidateKeywordArguments(kwds)) + return -1; + + while (PyDict_Next(kwds, &pos, &key, &value)) { + if (_PyUnicode_CompareWithId(key, &PyId_name) == 0) { + Py_INCREF(value); + Py_XSETREF(self->name, value); + continue; + } + if (_PyUnicode_CompareWithId(key, &PyId_path) == 0) { + Py_INCREF(value); + Py_XSETREF(self->path, value); + continue; + } + PyErr_Format(PyExc_TypeError, + "'%U' is an invalid keyword argument for %.200s", + key, Py_TYPE(self)->tp_name); + return -1; + } } - if (kwds) { - GET_KWD(name); - GET_KWD(path); - } - - if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) return -1; if (PyTuple_GET_SIZE(args) != 1) return 0;