[Python-checkins] cpython: Issues #13959, 14647: Re-implement imp.reload() in Lib/imp.py.

brett.cannon python-checkins at python.org
Sun Apr 29 20:40:50 CEST 2012


http://hg.python.org/cpython/rev/eb68502731dd
changeset:   76640:eb68502731dd
parent:      76637:1255cac63dfc
user:        Brett Cannon <brett at python.org>
date:        Sun Apr 29 14:38:11 2012 -0400
summary:
  Issues #13959, 14647: Re-implement imp.reload() in Lib/imp.py.

Thanks to Eric Snow for the patch.

files:
  Include/pystate.h      |    1 -
  Lib/imp.py             |   33 ++++++++-
  Objects/moduleobject.c |    2 +-
  Python/import.c        |  113 +++-------------------------
  Python/pystate.c       |    2 -
  Python/pythonrun.c     |    4 -
  6 files changed, 47 insertions(+), 108 deletions(-)


diff --git a/Include/pystate.h b/Include/pystate.h
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -26,7 +26,6 @@
     PyObject *sysdict;
     PyObject *builtins;
     PyObject *importlib;
-    PyObject *modules_reloading;
 
     PyObject *codec_search_path;
     PyObject *codec_search_cache;
diff --git a/Lib/imp.py b/Lib/imp.py
--- a/Lib/imp.py
+++ b/Lib/imp.py
@@ -6,7 +6,7 @@
 
 """
 # (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 @@
             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
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -285,7 +285,7 @@
     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
--- a/Python/import.c
+++ b/Python/import.c
@@ -410,14 +410,6 @@
 #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 @@
     PyDict_Clear(modules);
     interp->modules = NULL;
     Py_DECREF(modules);
-    Py_CLEAR(interp->modules_reloading);
 }
 
 
@@ -1783,87 +1774,23 @@
 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;
+    PyObject *imp = PyDict_GetItemString(modules, "imp");
+    if (imp == NULL) {
+        imp = PyImport_ImportModule("imp");
+        if (imp == NULL) {
+            return NULL;
+        }
+    }
+    else {
+        Py_INCREF(imp);
     }
 
-    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;
-        }
-    }
-
-    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);
-    }
-
-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 @@
 
 #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 @@
     {"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
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -69,7 +69,6 @@
             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 @@
     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
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -314,9 +314,6 @@
     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 @@
     /* XXX The following is lax in error checking */
 
     interp->modules = PyDict_New();
-    interp->modules_reloading = PyDict_New();
 
     bimod = _PyImport_FindBuiltin("builtins");
     if (bimod != NULL) {

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list