diff options
author | Brett Cannon <brett@python.org> | 2012-04-29 18:38:11 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2012-04-29 18:38:11 (GMT) |
commit | 62228dbd6c3b7be4199756c42a21429664c053e6 (patch) | |
tree | 3d63ba456c809bd1f0eae2d9dee4bf8ae7dad31b | |
parent | 1fc3ec91cc3e86035179db3e476ae7cd36ca6716 (diff) | |
download | cpython-62228dbd6c3b7be4199756c42a21429664c053e6.zip cpython-62228dbd6c3b7be4199756c42a21429664c053e6.tar.gz cpython-62228dbd6c3b7be4199756c42a21429664c053e6.tar.bz2 |
Issues #13959, 14647: Re-implement imp.reload() in Lib/imp.py.
Thanks to Eric Snow for the patch.
-rw-r--r-- | Include/pystate.h | 1 | ||||
-rw-r--r-- | Lib/imp.py | 33 | ||||
-rw-r--r-- | Objects/moduleobject.c | 2 | ||||
-rw-r--r-- | Python/import.c | 109 | ||||
-rw-r--r-- | Python/pystate.c | 2 | ||||
-rw-r--r-- | Python/pythonrun.c | 4 |
6 files changed, 45 insertions, 106 deletions
diff --git a/Include/pystate.h b/Include/pystate.h index 68d512b..6272492 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -26,7 +26,6 @@ typedef struct _is { PyObject *sysdict; PyObject *builtins; PyObject *importlib; - PyObject *modules_reloading; PyObject *codec_search_path; PyObject *codec_search_cache; @@ -6,7 +6,7 @@ functionality over this module. """ # (Probably) need to stay in _imp -from _imp import (lock_held, acquire_lock, release_lock, reload, +from _imp import (lock_held, acquire_lock, release_lock, load_dynamic, get_frozen_object, is_frozen_package, init_builtin, init_frozen, is_builtin, is_frozen, _fix_co_filename) @@ -207,3 +207,34 @@ def find_module(name, path=None): encoding = tokenize.detect_encoding(file.readline)[0] file = open(file_path, mode, encoding=encoding) return file, file_path, (suffix, mode, type_) + + +_RELOADING = {} + +def reload(module): + """Reload the module and return it. + + The module must have been successfully imported before. + + """ + if not module or type(module) != type(sys): + raise TypeError("reload() argument must be module") + name = module.__name__ + if name not in sys.modules: + msg = "module {} not in sys.modules" + raise ImportError(msg.format(name), name=name) + if name in _RELOADING: + return _RELOADING[name] + _RELOADING[name] = module + try: + parent_name = name.rpartition('.')[0] + if parent_name and parent_name not in sys.modules: + msg = "parent {!r} not in sys.modules" + raise ImportError(msg.format(parentname), name=parent_name) + return module.__loader__.load_module(name) + finally: + try: + del _RELOADING[name] + except KeyError: + pass + diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index b69bce6..7655f15 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -285,7 +285,7 @@ _PyModule_Clear(PyObject *m) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - if (PyUnicode_READ_CHAR(key, 0) == '_' && + if (PyUnicode_READ_CHAR(key, 0) == '_' && PyUnicode_READ_CHAR(key, 1) != '_') { if (Py_VerboseFlag > 1) { const char *s = _PyUnicode_AsString(key); diff --git a/Python/import.c b/Python/import.c index 0580f60..71485bd 100644 --- a/Python/import.c +++ b/Python/import.c @@ -410,14 +410,6 @@ _PyImport_Fini(void) #endif } -static void -imp_modules_reloading_clear(void) -{ - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules_reloading != NULL) - PyDict_Clear(interp->modules_reloading); -} - /* Helper for sys */ PyObject * @@ -575,7 +567,6 @@ PyImport_Cleanup(void) PyDict_Clear(modules); interp->modules = NULL; Py_DECREF(modules); - Py_CLEAR(interp->modules_reloading); } @@ -1783,87 +1774,23 @@ PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals PyObject * PyImport_ReloadModule(PyObject *m) { - PyInterpreterState *interp = PyThreadState_Get()->interp; - PyObject *modules_reloading = interp->modules_reloading; + _Py_IDENTIFIER(reload); + PyObject *reloaded_module = NULL; PyObject *modules = PyImport_GetModuleDict(); - PyObject *loader = NULL, *existing_m = NULL; - PyObject *name; - Py_ssize_t subname_start; - PyObject *newm = NULL; - _Py_IDENTIFIER(__loader__); - _Py_IDENTIFIER(load_module); - - if (modules_reloading == NULL) { - Py_FatalError("PyImport_ReloadModule: " - "no modules_reloading dictionary!"); - return NULL; - } - - if (m == NULL || !PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "reload() argument must be module"); - return NULL; - } - name = PyModule_GetNameObject(m); - if (name == NULL || PyUnicode_READY(name) == -1) - return NULL; - if (m != PyDict_GetItem(modules, name)) { - PyErr_Format(PyExc_ImportError, - "reload(): module %R not in sys.modules", - name); - Py_DECREF(name); - return NULL; - } - existing_m = PyDict_GetItem(modules_reloading, name); - if (existing_m != NULL) { - /* Due to a recursive reload, this module is already - being reloaded. */ - Py_DECREF(name); - Py_INCREF(existing_m); - return existing_m; - } - if (PyDict_SetItem(modules_reloading, name, m) < 0) { - Py_DECREF(name); - return NULL; - } - - subname_start = PyUnicode_FindChar(name, '.', 0, - PyUnicode_GET_LENGTH(name), -1); - if (subname_start != -1) { - PyObject *parentname, *parent; - parentname = PyUnicode_Substring(name, 0, subname_start); - if (parentname == NULL) { - goto error; - } - parent = PyDict_GetItem(modules, parentname); - Py_XDECREF(parent); - if (parent == NULL) { - PyErr_Format(PyExc_ImportError, - "reload(): parent %R not in sys.modules", - parentname); - goto error; + PyObject *imp = PyDict_GetItemString(modules, "imp"); + if (imp == NULL) { + imp = PyImport_ImportModule("imp"); + if (imp == NULL) { + return NULL; } } - - loader = _PyObject_GetAttrId(m, &PyId___loader__); - if (loader == NULL) { - goto error; - } - newm = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name); - Py_DECREF(loader); - if (newm == NULL) { - /* load_module probably removed name from modules because of - * the error. Put back the original module object. We're - * going to return NULL in this case regardless of whether - * replacing name succeeds, so the return value is ignored. - */ - PyDict_SetItem(modules, name, m); + else { + Py_INCREF(imp); } -error: - imp_modules_reloading_clear(); - Py_DECREF(name); - return newm; + reloaded_module = _PyObject_CallMethodId(imp, &PyId_reload, "O", m); + Py_DECREF(imp); + return reloaded_module; } @@ -2160,17 +2087,6 @@ imp_load_dynamic(PyObject *self, PyObject *args) #endif /* HAVE_DYNAMIC_LOADING */ -static PyObject * -imp_reload(PyObject *self, PyObject *v) -{ - return PyImport_ReloadModule(v); -} - -PyDoc_STRVAR(doc_reload, -"reload(module) -> module\n\ -\n\ -Reload the module. The module must have been successfully imported before."); - /* Doc strings */ @@ -2214,7 +2130,6 @@ static PyMethodDef imp_methods[] = { {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, - {"reload", imp_reload, METH_O, doc_reload}, {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, {"init_builtin", imp_init_builtin, METH_VARARGS}, diff --git a/Python/pystate.c b/Python/pystate.c index fdcbbce..a0489ad 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -69,7 +69,6 @@ PyInterpreterState_New(void) Py_FatalError("Can't initialize threads for interpreter"); #endif interp->modules = NULL; - interp->modules_reloading = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; @@ -114,7 +113,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->codec_error_registry); Py_CLEAR(interp->modules); Py_CLEAR(interp->modules_by_index); - Py_CLEAR(interp->modules_reloading); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); Py_CLEAR(interp->importlib); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 9e20e4a..cd3cf5c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -314,9 +314,6 @@ Py_InitializeEx(int install_sigs) interp->modules = PyDict_New(); if (interp->modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); - interp->modules_reloading = PyDict_New(); - if (interp->modules_reloading == NULL) - Py_FatalError("Py_Initialize: can't make modules_reloading dictionary"); /* Init Unicode implementation; relies on the codec registry */ if (_PyUnicode_Init() < 0) @@ -680,7 +677,6 @@ Py_NewInterpreter(void) /* XXX The following is lax in error checking */ interp->modules = PyDict_New(); - interp->modules_reloading = PyDict_New(); bimod = _PyImport_FindBuiltin("builtins"); if (bimod != NULL) { |