Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 62228db

Browse files
committed
Issues #13959, 14647: Re-implement imp.reload() in Lib/imp.py.
Thanks to Eric Snow for the patch.
1 parent 1fc3ec9 commit 62228db

6 files changed

Lines changed: 45 additions & 106 deletions

File tree

Include/pystate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ typedef struct _is {
2626
PyObject *sysdict;
2727
PyObject *builtins;
2828
PyObject *importlib;
29-
PyObject *modules_reloading;
3029

3130
PyObject *codec_search_path;
3231
PyObject *codec_search_cache;

Lib/imp.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
"""
88
# (Probably) need to stay in _imp
9-
from _imp import (lock_held, acquire_lock, release_lock, reload,
9+
from _imp import (lock_held, acquire_lock, release_lock,
1010
load_dynamic, get_frozen_object, is_frozen_package,
1111
init_builtin, init_frozen, is_builtin, is_frozen,
1212
_fix_co_filename)
@@ -207,3 +207,34 @@ def find_module(name, path=None):
207207
encoding = tokenize.detect_encoding(file.readline)[0]
208208
file = open(file_path, mode, encoding=encoding)
209209
return file, file_path, (suffix, mode, type_)
210+
211+
212+
_RELOADING = {}
213+
214+
def reload(module):
215+
"""Reload the module and return it.
216+
217+
The module must have been successfully imported before.
218+
219+
"""
220+
if not module or type(module) != type(sys):
221+
raise TypeError("reload() argument must be module")
222+
name = module.__name__
223+
if name not in sys.modules:
224+
msg = "module {} not in sys.modules"
225+
raise ImportError(msg.format(name), name=name)
226+
if name in _RELOADING:
227+
return _RELOADING[name]
228+
_RELOADING[name] = module
229+
try:
230+
parent_name = name.rpartition('.')[0]
231+
if parent_name and parent_name not in sys.modules:
232+
msg = "parent {!r} not in sys.modules"
233+
raise ImportError(msg.format(parentname), name=parent_name)
234+
return module.__loader__.load_module(name)
235+
finally:
236+
try:
237+
del _RELOADING[name]
238+
except KeyError:
239+
pass
240+

Objects/moduleobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ _PyModule_Clear(PyObject *m)
285285
pos = 0;
286286
while (PyDict_Next(d, &pos, &key, &value)) {
287287
if (value != Py_None && PyUnicode_Check(key)) {
288-
if (PyUnicode_READ_CHAR(key, 0) == '_' &&
288+
if (PyUnicode_READ_CHAR(key, 0) == '_' &&
289289
PyUnicode_READ_CHAR(key, 1) != '_') {
290290
if (Py_VerboseFlag > 1) {
291291
const char *s = _PyUnicode_AsString(key);

Python/import.c

Lines changed: 12 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,6 @@ _PyImport_Fini(void)
410410
#endif
411411
}
412412

413-
static void
414-
imp_modules_reloading_clear(void)
415-
{
416-
PyInterpreterState *interp = PyThreadState_Get()->interp;
417-
if (interp->modules_reloading != NULL)
418-
PyDict_Clear(interp->modules_reloading);
419-
}
420-
421413
/* Helper for sys */
422414

423415
PyObject *
@@ -575,7 +567,6 @@ PyImport_Cleanup(void)
575567
PyDict_Clear(modules);
576568
interp->modules = NULL;
577569
Py_DECREF(modules);
578-
Py_CLEAR(interp->modules_reloading);
579570
}
580571

581572

@@ -1783,87 +1774,23 @@ PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals
17831774
PyObject *
17841775
PyImport_ReloadModule(PyObject *m)
17851776
{
1786-
PyInterpreterState *interp = PyThreadState_Get()->interp;
1787-
PyObject *modules_reloading = interp->modules_reloading;
1777+
_Py_IDENTIFIER(reload);
1778+
PyObject *reloaded_module = NULL;
17881779
PyObject *modules = PyImport_GetModuleDict();
1789-
PyObject *loader = NULL, *existing_m = NULL;
1790-
PyObject *name;
1791-
Py_ssize_t subname_start;
1792-
PyObject *newm = NULL;
1793-
_Py_IDENTIFIER(__loader__);
1794-
_Py_IDENTIFIER(load_module);
1795-
1796-
if (modules_reloading == NULL) {
1797-
Py_FatalError("PyImport_ReloadModule: "
1798-
"no modules_reloading dictionary!");
1799-
return NULL;
1800-
}
1801-
1802-
if (m == NULL || !PyModule_Check(m)) {
1803-
PyErr_SetString(PyExc_TypeError,
1804-
"reload() argument must be module");
1805-
return NULL;
1806-
}
1807-
name = PyModule_GetNameObject(m);
1808-
if (name == NULL || PyUnicode_READY(name) == -1)
1809-
return NULL;
1810-
if (m != PyDict_GetItem(modules, name)) {
1811-
PyErr_Format(PyExc_ImportError,
1812-
"reload(): module %R not in sys.modules",
1813-
name);
1814-
Py_DECREF(name);
1815-
return NULL;
1816-
}
1817-
existing_m = PyDict_GetItem(modules_reloading, name);
1818-
if (existing_m != NULL) {
1819-
/* Due to a recursive reload, this module is already
1820-
being reloaded. */
1821-
Py_DECREF(name);
1822-
Py_INCREF(existing_m);
1823-
return existing_m;
1824-
}
1825-
if (PyDict_SetItem(modules_reloading, name, m) < 0) {
1826-
Py_DECREF(name);
1827-
return NULL;
1828-
}
1829-
1830-
subname_start = PyUnicode_FindChar(name, '.', 0,
1831-
PyUnicode_GET_LENGTH(name), -1);
1832-
if (subname_start != -1) {
1833-
PyObject *parentname, *parent;
1834-
parentname = PyUnicode_Substring(name, 0, subname_start);
1835-
if (parentname == NULL) {
1836-
goto error;
1837-
}
1838-
parent = PyDict_GetItem(modules, parentname);
1839-
Py_XDECREF(parent);
1840-
if (parent == NULL) {
1841-
PyErr_Format(PyExc_ImportError,
1842-
"reload(): parent %R not in sys.modules",
1843-
parentname);
1844-
goto error;
1780+
PyObject *imp = PyDict_GetItemString(modules, "imp");
1781+
if (imp == NULL) {
1782+
imp = PyImport_ImportModule("imp");
1783+
if (imp == NULL) {
1784+
return NULL;
18451785
}
18461786
}
1847-
1848-
loader = _PyObject_GetAttrId(m, &PyId___loader__);
1849-
if (loader == NULL) {
1850-
goto error;
1851-
}
1852-
newm = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name);
1853-
Py_DECREF(loader);
1854-
if (newm == NULL) {
1855-
/* load_module probably removed name from modules because of
1856-
* the error. Put back the original module object. We're
1857-
* going to return NULL in this case regardless of whether
1858-
* replacing name succeeds, so the return value is ignored.
1859-
*/
1860-
PyDict_SetItem(modules, name, m);
1787+
else {
1788+
Py_INCREF(imp);
18611789
}
18621790

1863-
error:
1864-
imp_modules_reloading_clear();
1865-
Py_DECREF(name);
1866-
return newm;
1791+
reloaded_module = _PyObject_CallMethodId(imp, &PyId_reload, "O", m);
1792+
Py_DECREF(imp);
1793+
return reloaded_module;
18671794
}
18681795

18691796

@@ -2160,17 +2087,6 @@ imp_load_dynamic(PyObject *self, PyObject *args)
21602087

21612088
#endif /* HAVE_DYNAMIC_LOADING */
21622089

2163-
static PyObject *
2164-
imp_reload(PyObject *self, PyObject *v)
2165-
{
2166-
return PyImport_ReloadModule(v);
2167-
}
2168-
2169-
PyDoc_STRVAR(doc_reload,
2170-
"reload(module) -> module\n\
2171-
\n\
2172-
Reload the module. The module must have been successfully imported before.");
2173-
21742090

21752091
/* Doc strings */
21762092

@@ -2214,7 +2130,6 @@ static PyMethodDef imp_methods[] = {
22142130
{"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held},
22152131
{"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock},
22162132
{"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock},
2217-
{"reload", imp_reload, METH_O, doc_reload},
22182133
{"get_frozen_object", imp_get_frozen_object, METH_VARARGS},
22192134
{"is_frozen_package", imp_is_frozen_package, METH_VARARGS},
22202135
{"init_builtin", imp_init_builtin, METH_VARARGS},

Python/pystate.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ PyInterpreterState_New(void)
6969
Py_FatalError("Can't initialize threads for interpreter");
7070
#endif
7171
interp->modules = NULL;
72-
interp->modules_reloading = NULL;
7372
interp->modules_by_index = NULL;
7473
interp->sysdict = NULL;
7574
interp->builtins = NULL;
@@ -114,7 +113,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
114113
Py_CLEAR(interp->codec_error_registry);
115114
Py_CLEAR(interp->modules);
116115
Py_CLEAR(interp->modules_by_index);
117-
Py_CLEAR(interp->modules_reloading);
118116
Py_CLEAR(interp->sysdict);
119117
Py_CLEAR(interp->builtins);
120118
Py_CLEAR(interp->importlib);

Python/pythonrun.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,6 @@ Py_InitializeEx(int install_sigs)
314314
interp->modules = PyDict_New();
315315
if (interp->modules == NULL)
316316
Py_FatalError("Py_Initialize: can't make modules dictionary");
317-
interp->modules_reloading = PyDict_New();
318-
if (interp->modules_reloading == NULL)
319-
Py_FatalError("Py_Initialize: can't make modules_reloading dictionary");
320317

321318
/* Init Unicode implementation; relies on the codec registry */
322319
if (_PyUnicode_Init() < 0)
@@ -680,7 +677,6 @@ Py_NewInterpreter(void)
680677
/* XXX The following is lax in error checking */
681678

682679
interp->modules = PyDict_New();
683-
interp->modules_reloading = PyDict_New();
684680

685681
bimod = _PyImport_FindBuiltin("builtins");
686682
if (bimod != NULL) {

0 commit comments

Comments
 (0)