diff -r bb645cc39e60 Include/pyerrors.h --- a/Include/pyerrors.h Fri Mar 18 13:03:17 2011 -0500 +++ b/Include/pyerrors.h Fri Mar 18 23:53:47 2011 +0100 @@ -47,6 +47,12 @@ PyObject *filename; } PyEnvironmentErrorObject; +typedef struct { + PyException_HEAD + PyObject *msg; + PyObject *module_name; +} PyImportErrorObject; + #ifdef MS_WINDOWS typedef struct { PyException_HEAD diff -r bb645cc39e60 Lib/test/test_import.py --- a/Lib/test/test_import.py Fri Mar 18 13:03:17 2011 -0500 +++ b/Lib/test/test_import.py Fri Mar 18 23:53:47 2011 +0100 @@ -294,6 +294,18 @@ sys.argv.insert(0, C()) """)) script_helper.assert_python_ok(testfn) + + def test_module_name_keyword(self): + try: + raise ImportError('failed to import', module_name='failingmodule') + except ImportError as e: + self.assertEqual(e.module_name, 'failingmodule') + + def test_module_name(self): + try: + import failingmodule + except ImportError as e: + self.assertEqual(e.module_name, 'failingmodule') class PycRewritingTests(unittest.TestCase): diff -r bb645cc39e60 Objects/exceptions.c --- a/Objects/exceptions.c Fri Mar 18 13:03:17 2011 -0500 +++ b/Objects/exceptions.c Fri Mar 18 23:53:47 2011 +0100 @@ -547,9 +547,91 @@ /* * ImportError extends Exception */ -SimpleExtendsException(PyExc_Exception, ImportError, - "Import can't find module, or can't find name in module."); +static int +ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *msg = NULL; + PyObject *module_name = NULL; + + if (kwds){ + module_name = PyDict_GetItemString(kwds, "module_name"); + if (module_name){ + Py_CLEAR(self->module_name); /* replacing */ + self->module_name = module_name; + Py_INCREF(self->module_name); + if (PyDict_DelItemString(kwds, "module_name")) + 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; + + Py_CLEAR(self->msg); /* replacing */ + self->msg = msg; + Py_INCREF(self->msg); + + return 0; +} + +static int +ImportError_clear(PyImportErrorObject *self) +{ + Py_CLEAR(self->msg); + Py_CLEAR(self->module_name); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +ImportError_dealloc(PyImportErrorObject *self) +{ + _PyObject_GC_UNTRACK(self); + ImportError_clear(self); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static int +ImportError_traverse(PyImportErrorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->msg); + Py_VISIT(self->module_name); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyObject * +ImportError_str(PyImportErrorObject *self) +{ + if (self->msg) { + Py_INCREF(self->msg); + return self->msg; + } + else + return BaseException_str((PyBaseExceptionObject *)self); +} + +static PyMemberDef ImportError_members[] = { + {"msg", T_OBJECT, offsetof(PyImportErrorObject, msg), 0, + PyDoc_STR("exception message")}, + {"module_name", T_OBJECT, offsetof(PyImportErrorObject, module_name), 0, + PyDoc_STR("exception module_name")}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef ImportError_methods[] = { + {NULL} +}; + +ComplexExtendsException(PyExc_Exception, ImportError, + ImportError, ImportError_dealloc, + ImportError_methods, ImportError_members, + ImportError_str, + "Import can't find module, or can't find name in " + "module."); /* * EnvironmentError extends Exception diff -r bb645cc39e60 Python/import.c --- a/Python/import.c Fri Mar 18 13:03:17 2011 -0500 +++ b/Python/import.c Fri Mar 18 23:53:47 2011 +0100 @@ -2768,8 +2768,23 @@ if (result == Py_None) { Py_DECREF(result); - PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); + PyObject *message = PyUnicode_FromFormat("No module named %.200s", + name); + if (message == NULL) + return NULL; + PyObject *module = PyUnicode_DecodeASCII(name, strlen(name), "strict"); + if (module == NULL){ + Py_DECREF(message); + return NULL; + } + PyObject *value = Py_BuildValue("O", message); + Py_DECREF(message); + Py_DECREF(module); + if (value == NULL) + return NULL; + + PyErr_SetObject(PyExc_ImportError, value); + Py_DECREF(value); return NULL; }