diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -961,16 +961,34 @@ class ImportErrorTests(unittest.TestCase exc = ImportError('test', path='somepath') self.assertEqual(exc.path, 'somepath') self.assertIsNone(exc.name) exc = ImportError('test', path='somepath', name='somename') self.assertEqual(exc.name, 'somename') self.assertEqual(exc.path, 'somepath') + with self.assertRaises(TypeError) as cm: + ImportError('test', invalid='keyword') + self.assertEqual(str(cm.exception), + "ImportError only accepts 'name' and 'path' " + "keyword arguments") + + with self.assertRaises(TypeError) as cm: + ImportError('test', name='name', invalid='keyword') + self.assertEqual(str(cm.exception), + "ImportError only accepts 'name' and 'path' " + "keyword arguments") + + with self.assertRaises(TypeError) as cm: + ImportError(invalid='keyword') + self.assertEqual(str(cm.exception), + "ImportError only accepts 'name' and 'path' " + "keyword arguments") + def test_non_str_argument(self): # Issue #15778 with check_warnings(('', BytesWarning), quiet=True): arg = b'abc' exc = ImportError(arg) self.assertEqual(str(arg), str(exc)) diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -626,16 +626,21 @@ ImportError_init(PyImportErrorObject *se if (PyDict_DelItemString(kwds, #kwd)) \ return -1; \ } \ } if (kwds) { GET_KWD(name); GET_KWD(path); + if (!_PyArg_NoKeywords("ImportError", kwds)) { + PyErr_SetString(PyExc_TypeError, + "ImportError only accepts 'name' and 'path' keyword arguments"); + return -1; + } } if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) return -1; if (PyTuple_GET_SIZE(args) != 1) return 0; if (!PyArg_UnpackTuple(args, "ImportError", 1, 1, &msg)) return -1;