Issue #22557: Now importing already imported modules is up to 2.5 times faster.
This commit is contained in:
parent
cde03fa038
commit
133138a284
|
@ -41,6 +41,7 @@ typedef struct _is {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyObject *builtins_copy;
|
PyObject *builtins_copy;
|
||||||
|
PyObject *import_func;
|
||||||
} PyInterpreterState;
|
} PyInterpreterState;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ What's New in Python 3.6.0 alpha 4
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #22557: Now importing already imported modules is up to 2.5 times faster.
|
||||||
|
|
||||||
- Issue #17596: Include <wincrypt.h> to help with Min GW building.
|
- Issue #17596: Include <wincrypt.h> to help with Min GW building.
|
||||||
|
|
||||||
- Issue #27507: Add integer overflow check in bytearray.extend(). Patch by
|
- Issue #27507: Add integer overflow check in bytearray.extend(). Patch by
|
||||||
|
|
|
@ -139,6 +139,7 @@ static int maybe_call_line_trace(Py_tracefunc, PyObject *,
|
||||||
PyThreadState *, PyFrameObject *, int *, int *, int *);
|
PyThreadState *, PyFrameObject *, int *, int *, int *);
|
||||||
|
|
||||||
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
|
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
|
||||||
|
static PyObject * import_name(PyFrameObject *, PyObject *, PyObject *, PyObject *);
|
||||||
static PyObject * import_from(PyObject *, PyObject *);
|
static PyObject * import_from(PyObject *, PyObject *);
|
||||||
static int import_all_from(PyObject *, PyObject *);
|
static int import_all_from(PyObject *, PyObject *);
|
||||||
static void format_exc_check_arg(PyObject *, const char *, PyObject *);
|
static void format_exc_check_arg(PyObject *, const char *, PyObject *);
|
||||||
|
@ -2808,37 +2809,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(IMPORT_NAME) {
|
TARGET(IMPORT_NAME) {
|
||||||
_Py_IDENTIFIER(__import__);
|
|
||||||
PyObject *name = GETITEM(names, oparg);
|
PyObject *name = GETITEM(names, oparg);
|
||||||
PyObject *func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
|
PyObject *fromlist = POP();
|
||||||
PyObject *from, *level, *args, *res;
|
PyObject *level = TOP();
|
||||||
if (func == NULL) {
|
PyObject *res;
|
||||||
PyErr_SetString(PyExc_ImportError,
|
|
||||||
"__import__ not found");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Py_INCREF(func);
|
|
||||||
from = POP();
|
|
||||||
level = TOP();
|
|
||||||
args = PyTuple_Pack(5,
|
|
||||||
name,
|
|
||||||
f->f_globals,
|
|
||||||
f->f_locals == NULL ?
|
|
||||||
Py_None : f->f_locals,
|
|
||||||
from,
|
|
||||||
level);
|
|
||||||
Py_DECREF(level);
|
|
||||||
Py_DECREF(from);
|
|
||||||
if (args == NULL) {
|
|
||||||
Py_DECREF(func);
|
|
||||||
STACKADJ(-1);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
READ_TIMESTAMP(intr0);
|
READ_TIMESTAMP(intr0);
|
||||||
res = PyEval_CallObject(func, args);
|
res = import_name(f, name, fromlist, level);
|
||||||
|
Py_DECREF(level);
|
||||||
|
Py_DECREF(fromlist);
|
||||||
READ_TIMESTAMP(intr1);
|
READ_TIMESTAMP(intr1);
|
||||||
Py_DECREF(args);
|
|
||||||
Py_DECREF(func);
|
|
||||||
SET_TOP(res);
|
SET_TOP(res);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -5158,6 +5137,50 @@ cmp_outcome(int op, PyObject *v, PyObject *w)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *level)
|
||||||
|
{
|
||||||
|
_Py_IDENTIFIER(__import__);
|
||||||
|
PyObject *import_func, *args, *res;
|
||||||
|
|
||||||
|
import_func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
|
||||||
|
if (import_func == NULL) {
|
||||||
|
PyErr_SetString(PyExc_ImportError, "__import__ not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fast path for not overloaded __import__. */
|
||||||
|
if (import_func == PyThreadState_GET()->interp->import_func) {
|
||||||
|
int ilevel = _PyLong_AsInt(level);
|
||||||
|
if (ilevel == -1 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
res = PyImport_ImportModuleLevelObject(
|
||||||
|
name,
|
||||||
|
f->f_globals,
|
||||||
|
f->f_locals == NULL ? Py_None : f->f_locals,
|
||||||
|
fromlist,
|
||||||
|
ilevel);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF(import_func);
|
||||||
|
args = PyTuple_Pack(5,
|
||||||
|
name,
|
||||||
|
f->f_globals,
|
||||||
|
f->f_locals == NULL ? Py_None : f->f_locals,
|
||||||
|
fromlist,
|
||||||
|
level);
|
||||||
|
if (args == NULL) {
|
||||||
|
Py_DECREF(import_func);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
res = PyEval_CallObject(import_func, args);
|
||||||
|
Py_DECREF(args);
|
||||||
|
Py_DECREF(import_func);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
import_from(PyObject *v, PyObject *name)
|
import_from(PyObject *v, PyObject *name)
|
||||||
{
|
{
|
||||||
|
|
213
Python/import.c
213
Python/import.c
|
@ -1336,85 +1336,37 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
static PyObject *
|
||||||
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
resolve_name(PyObject *name, PyObject *globals, int level)
|
||||||
PyObject *locals, PyObject *given_fromlist,
|
|
||||||
int level)
|
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(__import__);
|
|
||||||
_Py_IDENTIFIER(__spec__);
|
_Py_IDENTIFIER(__spec__);
|
||||||
_Py_IDENTIFIER(_initializing);
|
|
||||||
_Py_IDENTIFIER(__package__);
|
_Py_IDENTIFIER(__package__);
|
||||||
_Py_IDENTIFIER(__path__);
|
_Py_IDENTIFIER(__path__);
|
||||||
_Py_IDENTIFIER(__name__);
|
_Py_IDENTIFIER(__name__);
|
||||||
_Py_IDENTIFIER(_find_and_load);
|
_Py_IDENTIFIER(parent);
|
||||||
_Py_IDENTIFIER(_handle_fromlist);
|
PyObject *abs_name;
|
||||||
_Py_IDENTIFIER(_lock_unlock_module);
|
|
||||||
PyObject *abs_name = NULL;
|
|
||||||
PyObject *builtins_import = NULL;
|
|
||||||
PyObject *final_mod = NULL;
|
|
||||||
PyObject *mod = NULL;
|
|
||||||
PyObject *package = NULL;
|
PyObject *package = NULL;
|
||||||
PyObject *spec = NULL;
|
PyObject *spec;
|
||||||
PyObject *globals = NULL;
|
|
||||||
PyObject *fromlist = NULL;
|
|
||||||
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||||
int has_from;
|
Py_ssize_t last_dot;
|
||||||
|
PyObject *base;
|
||||||
|
int level_up;
|
||||||
|
|
||||||
/* Make sure to use default values so as to not have
|
|
||||||
PyObject_CallMethodObjArgs() truncate the parameter list because of a
|
|
||||||
NULL argument. */
|
|
||||||
if (given_globals == NULL) {
|
|
||||||
globals = PyDict_New();
|
|
||||||
if (globals == NULL) {
|
if (globals == NULL) {
|
||||||
|
PyErr_SetString(PyExc_KeyError, "'__name__' not in globals");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
if (!PyDict_Check(globals)) {
|
||||||
else {
|
|
||||||
/* Only have to care what given_globals is if it will be used
|
|
||||||
for something. */
|
|
||||||
if (level > 0 && !PyDict_Check(given_globals)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "globals must be a dict");
|
PyErr_SetString(PyExc_TypeError, "globals must be a dict");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
globals = given_globals;
|
|
||||||
Py_INCREF(globals);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (given_fromlist == NULL) {
|
|
||||||
fromlist = PyList_New(0);
|
|
||||||
if (fromlist == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fromlist = given_fromlist;
|
|
||||||
Py_INCREF(fromlist);
|
|
||||||
}
|
|
||||||
if (name == NULL) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "Empty module name");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The below code is importlib.__import__() & _gcd_import(), ported to C
|
|
||||||
for added performance. */
|
|
||||||
|
|
||||||
if (!PyUnicode_Check(name)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "module name must be a string");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else if (PyUnicode_READY(name) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (level < 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "level must be >= 0");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else if (level > 0) {
|
|
||||||
package = _PyDict_GetItemId(globals, &PyId___package__);
|
package = _PyDict_GetItemId(globals, &PyId___package__);
|
||||||
|
if (package == Py_None) {
|
||||||
|
package = NULL;
|
||||||
|
}
|
||||||
spec = _PyDict_GetItemId(globals, &PyId___spec__);
|
spec = _PyDict_GetItemId(globals, &PyId___spec__);
|
||||||
|
|
||||||
if (package != NULL && package != Py_None) {
|
if (package != NULL) {
|
||||||
Py_INCREF(package);
|
Py_INCREF(package);
|
||||||
if (!PyUnicode_Check(package)) {
|
if (!PyUnicode_Check(package)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "package must be a string");
|
PyErr_SetString(PyExc_TypeError, "package must be a string");
|
||||||
|
@ -1422,7 +1374,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
else if (spec != NULL && spec != Py_None) {
|
else if (spec != NULL && spec != Py_None) {
|
||||||
int equal;
|
int equal;
|
||||||
PyObject *parent = PyObject_GetAttrString(spec, "parent");
|
PyObject *parent = _PyObject_GetAttrId(spec, &PyId_parent);
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1441,7 +1393,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (spec != NULL && spec != Py_None) {
|
else if (spec != NULL && spec != Py_None) {
|
||||||
package = PyObject_GetAttrString(spec, "parent");
|
package = _PyObject_GetAttrId(spec, &PyId_parent);
|
||||||
if (package == NULL) {
|
if (package == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1452,7 +1404,6 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
package = NULL;
|
|
||||||
if (PyErr_WarnEx(PyExc_ImportWarning,
|
if (PyErr_WarnEx(PyExc_ImportWarning,
|
||||||
"can't resolve package from __spec__ or __package__, "
|
"can't resolve package from __spec__ or __package__, "
|
||||||
"falling back on __name__ and __path__", 1) < 0) {
|
"falling back on __name__ and __path__", 1) < 0) {
|
||||||
|
@ -1494,7 +1445,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyUnicode_CompareWithASCIIString(package, "") == 0) {
|
last_dot = PyUnicode_GET_LENGTH(package);
|
||||||
|
if (last_dot == 0) {
|
||||||
PyErr_SetString(PyExc_ImportError,
|
PyErr_SetString(PyExc_ImportError,
|
||||||
"attempted relative import with no known parent package");
|
"attempted relative import with no known parent package");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1505,20 +1457,6 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
"import", package);
|
"import", package);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { /* level == 0 */
|
|
||||||
if (PyUnicode_GET_LENGTH(name) == 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "Empty module name");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
package = Py_None;
|
|
||||||
Py_INCREF(package);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level > 0) {
|
|
||||||
Py_ssize_t last_dot = PyUnicode_GET_LENGTH(package);
|
|
||||||
PyObject *base = NULL;
|
|
||||||
int level_up = 1;
|
|
||||||
|
|
||||||
for (level_up = 1; level_up < level; level_up += 1) {
|
for (level_up = 1; level_up < level; level_up += 1) {
|
||||||
last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1);
|
last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1);
|
||||||
|
@ -1534,39 +1472,68 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
base = PyUnicode_Substring(package, 0, last_dot);
|
base = PyUnicode_Substring(package, 0, last_dot);
|
||||||
if (base == NULL)
|
Py_DECREF(package);
|
||||||
goto error;
|
if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
if (PyUnicode_GET_LENGTH(name) > 0) {
|
|
||||||
abs_name = PyUnicode_FromFormat("%U.%U", base, name);
|
abs_name = PyUnicode_FromFormat("%U.%U", base, name);
|
||||||
Py_DECREF(base);
|
Py_DECREF(base);
|
||||||
if (abs_name == NULL) {
|
return abs_name;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_XDECREF(package);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
|
PyObject *locals, PyObject *fromlist,
|
||||||
|
int level)
|
||||||
|
{
|
||||||
|
_Py_IDENTIFIER(_find_and_load);
|
||||||
|
_Py_IDENTIFIER(_handle_fromlist);
|
||||||
|
PyObject *abs_name = NULL;
|
||||||
|
PyObject *final_mod = NULL;
|
||||||
|
PyObject *mod = NULL;
|
||||||
|
PyObject *package = NULL;
|
||||||
|
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||||
|
int has_from;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Empty module name");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The below code is importlib.__import__() & _gcd_import(), ported to C
|
||||||
|
for added performance. */
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(name)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "module name must be a string");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
else {
|
if (PyUnicode_READY(name) < 0) {
|
||||||
abs_name = base;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (level < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "level must be >= 0");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level > 0) {
|
||||||
|
abs_name = resolve_name(name, globals, level);
|
||||||
|
if (abs_name == NULL)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else { /* level == 0 */
|
||||||
|
if (PyUnicode_GET_LENGTH(name) == 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Empty module name");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
abs_name = name;
|
abs_name = name;
|
||||||
Py_INCREF(abs_name);
|
Py_INCREF(abs_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
|
||||||
_PyImport_AcquireLock();
|
|
||||||
#endif
|
|
||||||
/* From this point forward, goto error_with_unlock! */
|
|
||||||
/* XXX interp->builtins_copy is NULL in subinterpreter! */
|
|
||||||
builtins_import = _PyDict_GetItemId(interp->builtins_copy ?
|
|
||||||
interp->builtins_copy :
|
|
||||||
interp->builtins, &PyId___import__);
|
|
||||||
if (builtins_import == NULL) {
|
|
||||||
PyErr_SetString(PyExc_ImportError, "__import__ not found");
|
|
||||||
goto error_with_unlock;
|
|
||||||
}
|
|
||||||
Py_INCREF(builtins_import);
|
|
||||||
|
|
||||||
mod = PyDict_GetItem(interp->modules, abs_name);
|
mod = PyDict_GetItem(interp->modules, abs_name);
|
||||||
if (mod == Py_None) {
|
if (mod == Py_None) {
|
||||||
PyObject *msg = PyUnicode_FromFormat("import of %R halted; "
|
PyObject *msg = PyUnicode_FromFormat("import of %R halted; "
|
||||||
|
@ -1576,9 +1543,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
Py_DECREF(msg);
|
Py_DECREF(msg);
|
||||||
}
|
}
|
||||||
mod = NULL;
|
mod = NULL;
|
||||||
goto error_with_unlock;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (mod != NULL) {
|
else if (mod != NULL) {
|
||||||
|
_Py_IDENTIFIER(__spec__);
|
||||||
|
_Py_IDENTIFIER(_initializing);
|
||||||
|
_Py_IDENTIFIER(_lock_unlock_module);
|
||||||
PyObject *value = NULL;
|
PyObject *value = NULL;
|
||||||
PyObject *spec;
|
PyObject *spec;
|
||||||
int initializing = 0;
|
int initializing = 0;
|
||||||
|
@ -1601,8 +1571,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
if (initializing == -1)
|
if (initializing == -1)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
|
||||||
if (initializing > 0) {
|
if (initializing > 0) {
|
||||||
|
#ifdef WITH_THREAD
|
||||||
|
_PyImport_AcquireLock();
|
||||||
|
#endif
|
||||||
/* _bootstrap._lock_unlock_module() releases the import lock */
|
/* _bootstrap._lock_unlock_module() releases the import lock */
|
||||||
value = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
value = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
||||||
&PyId__lock_unlock_module, abs_name,
|
&PyId__lock_unlock_module, abs_name,
|
||||||
|
@ -1611,29 +1583,27 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
goto error;
|
goto error;
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
if (_PyImport_ReleaseLock() < 0) {
|
_PyImport_AcquireLock();
|
||||||
PyErr_SetString(PyExc_RuntimeError, "not holding the import lock");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* _bootstrap._find_and_load() releases the import lock */
|
/* _bootstrap._find_and_load() releases the import lock */
|
||||||
mod = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
mod = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
||||||
&PyId__find_and_load, abs_name,
|
&PyId__find_and_load, abs_name,
|
||||||
builtins_import, NULL);
|
interp->import_func, NULL);
|
||||||
if (mod == NULL) {
|
if (mod == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* From now on we don't hold the import lock anymore. */
|
|
||||||
|
|
||||||
|
has_from = 0;
|
||||||
|
if (fromlist != NULL && fromlist != Py_None) {
|
||||||
has_from = PyObject_IsTrue(fromlist);
|
has_from = PyObject_IsTrue(fromlist);
|
||||||
if (has_from < 0)
|
if (has_from < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
if (!has_from) {
|
if (!has_from) {
|
||||||
Py_ssize_t len = PyUnicode_GET_LENGTH(name);
|
Py_ssize_t len = PyUnicode_GET_LENGTH(name);
|
||||||
if (level == 0 || len > 0) {
|
if (level == 0 || len > 0) {
|
||||||
|
@ -1657,7 +1627,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
final_mod = PyObject_CallFunctionObjArgs(builtins_import, front, NULL);
|
final_mod = PyImport_ImportModuleLevelObject(front, NULL, NULL, NULL, 0);
|
||||||
Py_DECREF(front);
|
Py_DECREF(front);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1670,16 +1640,15 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
final_mod = PyDict_GetItem(interp->modules, to_return);
|
final_mod = PyDict_GetItem(interp->modules, to_return);
|
||||||
|
Py_DECREF(to_return);
|
||||||
if (final_mod == NULL) {
|
if (final_mod == NULL) {
|
||||||
PyErr_Format(PyExc_KeyError,
|
PyErr_Format(PyExc_KeyError,
|
||||||
"%R not in sys.modules as expected",
|
"%R not in sys.modules as expected",
|
||||||
to_return);
|
to_return);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Py_INCREF(final_mod);
|
Py_INCREF(final_mod);
|
||||||
}
|
}
|
||||||
Py_DECREF(to_return);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final_mod = mod;
|
final_mod = mod;
|
||||||
|
@ -1689,24 +1658,14 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
||||||
else {
|
else {
|
||||||
final_mod = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
final_mod = _PyObject_CallMethodIdObjArgs(interp->importlib,
|
||||||
&PyId__handle_fromlist, mod,
|
&PyId__handle_fromlist, mod,
|
||||||
fromlist, builtins_import,
|
fromlist, interp->import_func,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
goto error;
|
|
||||||
|
|
||||||
error_with_unlock:
|
|
||||||
#ifdef WITH_THREAD
|
|
||||||
if (_PyImport_ReleaseLock() < 0) {
|
|
||||||
PyErr_SetString(PyExc_RuntimeError, "not holding the import lock");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(abs_name);
|
Py_XDECREF(abs_name);
|
||||||
Py_XDECREF(builtins_import);
|
|
||||||
Py_XDECREF(mod);
|
Py_XDECREF(mod);
|
||||||
Py_XDECREF(package);
|
Py_XDECREF(package);
|
||||||
Py_XDECREF(globals);
|
|
||||||
Py_XDECREF(fromlist);
|
|
||||||
if (final_mod == NULL)
|
if (final_mod == NULL)
|
||||||
remove_importlib_frames();
|
remove_importlib_frames();
|
||||||
return final_mod;
|
return final_mod;
|
||||||
|
|
|
@ -254,6 +254,11 @@ import_init(PyInterpreterState *interp, PyObject *sysmod)
|
||||||
interp->importlib = importlib;
|
interp->importlib = importlib;
|
||||||
Py_INCREF(interp->importlib);
|
Py_INCREF(interp->importlib);
|
||||||
|
|
||||||
|
interp->import_func = PyDict_GetItemString(interp->builtins, "__import__");
|
||||||
|
if (interp->import_func == NULL)
|
||||||
|
Py_FatalError("Py_Initialize: __import__ not found");
|
||||||
|
Py_INCREF(interp->import_func);
|
||||||
|
|
||||||
/* Import the _imp module */
|
/* Import the _imp module */
|
||||||
impmod = PyInit_imp();
|
impmod = PyInit_imp();
|
||||||
if (impmod == NULL) {
|
if (impmod == NULL) {
|
||||||
|
|
|
@ -90,6 +90,7 @@ PyInterpreterState_New(void)
|
||||||
interp->codecs_initialized = 0;
|
interp->codecs_initialized = 0;
|
||||||
interp->fscodec_initialized = 0;
|
interp->fscodec_initialized = 0;
|
||||||
interp->importlib = NULL;
|
interp->importlib = NULL;
|
||||||
|
interp->import_func = NULL;
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
#if HAVE_DECL_RTLD_NOW
|
#if HAVE_DECL_RTLD_NOW
|
||||||
interp->dlopenflags = RTLD_NOW;
|
interp->dlopenflags = RTLD_NOW;
|
||||||
|
@ -128,6 +129,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
||||||
Py_CLEAR(interp->builtins);
|
Py_CLEAR(interp->builtins);
|
||||||
Py_CLEAR(interp->builtins_copy);
|
Py_CLEAR(interp->builtins_copy);
|
||||||
Py_CLEAR(interp->importlib);
|
Py_CLEAR(interp->importlib);
|
||||||
|
Py_CLEAR(interp->import_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue