Index: Python/import.c =================================================================== --- Python/import.c (revision 54326) +++ Python/import.c (working copy) @@ -2423,35 +2423,47 @@ PyObject *modules_reloading = PyImport_GetModulesReloading(); PyObject *modules = PyImport_GetModuleDict(); PyObject *path = NULL, *loader = NULL, *existing_m = NULL; + PyObject *nameobj; char *name, *subname; char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp = NULL; PyObject *newm; - if (m == NULL || !PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "reload() argument must be module"); + if (m == NULL) { + PyErr_SetString(PyExc_SystemError, + "null argument to internal routine"); return NULL; + } + nameobj = PyObject_GetAttrString(m, "__name__"); + if (nameobj == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_SetString(PyExc_TypeError, + "reload(): module requires __name__ attribute"); + return NULL; } - name = PyModule_GetName(m); - if (name == NULL) - return NULL; + if (!PyString_Check(nameobj)) { + PyErr_SetString(PyExc_TypeError, + "module name must be string"); + goto error; + } + name = PyString_AS_STRING(nameobj); if (m != PyDict_GetItemString(modules, name)) { PyErr_Format(PyExc_ImportError, "reload(): module %.200s not in sys.modules", name); - return NULL; + goto error; } existing_m = PyDict_GetItemString(modules_reloading, name); if (existing_m != NULL) { /* Due to a recursive reload, this module is already being reloaded. */ Py_INCREF(existing_m); + Py_DECREF(nameobj); return existing_m; } if (PyDict_SetItemString(modules_reloading, name, m) < 0) - return NULL; + goto error; subname = strrchr(name, '.'); if (subname == NULL) @@ -2461,7 +2473,7 @@ parentname = PyString_FromStringAndSize(name, (subname-name)); if (parentname == NULL) { imp_modules_reloading_clear(); - return NULL; + goto error; } parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { @@ -2469,8 +2481,8 @@ "reload(): parent %.200s not in sys.modules", PyString_AS_STRING(parentname)); Py_DECREF(parentname); - imp_modules_reloading_clear(); - return NULL; + imp_modules_reloading_clear(); + goto error; } Py_DECREF(parentname); subname++; @@ -2502,7 +2514,12 @@ PyDict_SetItemString(modules, name, m); } imp_modules_reloading_clear(); + Py_DECREF(nameobj); return newm; + + error: + Py_DECREF(nameobj); + return NULL; } Index: Lib/test/test_import.py =================================================================== --- Lib/test/test_import.py (revision 54326) +++ Lib/test/test_import.py (working copy) @@ -221,6 +221,17 @@ warnings.simplefilter('error', ImportWarning) self.assertRaises(ImportWarning, __import__, "site-packages") + def test_reloading_nonmodule(self): + class FakeMod: + def __init__(self, n): + self.__name__ = n + def foo(self): + pass + sys.modules['fake'] = FakeMod('fake') + import fake + reload(fake) + fake.foo() + def test_main(verbose=None): run_unittest(ImportTest)