From 8a33284d191025bc387644666807311eb7d60384 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 8 Jul 2016 11:00:00 -0700 Subject: Issue #26896: Disambiguate uses of "importer" with "finder". Thanks to Oren Milman for the patch. --- Python/import.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Python/import.c') diff --git a/Python/import.c b/Python/import.c index d791624481..bdc7e4cfa7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -950,12 +950,13 @@ is_builtin(PyObject *name) } -/* Return an importer object for a sys.path/pkg.__path__ item 'p', +/* Return a finder object for a sys.path/pkg.__path__ item 'p', possibly by fetching it from the path_importer_cache dict. If it wasn't yet cached, traverse path_hooks until a hook is found that can handle the path item. Return None if no hook could; - this tells our caller it should fall back to the builtin - import mechanism. Cache the result in path_importer_cache. + this tells our caller that the path based finder could not find + a finder for this path item. Cache the result in + path_importer_cache. Returns a borrowed reference. */ static PyObject * -- cgit v1.2.1 From 47f7f2f22d067813b1406f7aa9328b53f264aa6a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 2 Aug 2016 22:51:21 +0300 Subject: Issue #22557: Now importing already imported modules is up to 2.5 times faster. --- Python/import.c | 395 +++++++++++++++++++++++++------------------------------- 1 file changed, 177 insertions(+), 218 deletions(-) (limited to 'Python/import.c') diff --git a/Python/import.c b/Python/import.c index ebad07b2cf..f3aa9d4397 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1336,61 +1336,170 @@ done: } -PyObject * -PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, - PyObject *locals, PyObject *given_fromlist, - int level) +static PyObject * +resolve_name(PyObject *name, PyObject *globals, int level) { - _Py_IDENTIFIER(__import__); _Py_IDENTIFIER(__spec__); - _Py_IDENTIFIER(_initializing); _Py_IDENTIFIER(__package__); _Py_IDENTIFIER(__path__); _Py_IDENTIFIER(__name__); - _Py_IDENTIFIER(_find_and_load); - _Py_IDENTIFIER(_handle_fromlist); - _Py_IDENTIFIER(_lock_unlock_module); - PyObject *abs_name = NULL; - PyObject *builtins_import = NULL; - PyObject *final_mod = NULL; - PyObject *mod = NULL; + _Py_IDENTIFIER(parent); + PyObject *abs_name; PyObject *package = NULL; - PyObject *spec = NULL; - PyObject *globals = NULL; - PyObject *fromlist = NULL; + PyObject *spec; PyInterpreterState *interp = PyThreadState_GET()->interp; - int has_from; + Py_ssize_t last_dot; + PyObject *base; + int level_up; + + if (globals == NULL) { + PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); + goto error; + } + if (!PyDict_Check(globals)) { + PyErr_SetString(PyExc_TypeError, "globals must be a dict"); + goto error; + } + package = _PyDict_GetItemId(globals, &PyId___package__); + if (package == Py_None) { + package = NULL; + } + spec = _PyDict_GetItemId(globals, &PyId___spec__); - /* 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 (package != NULL) { + Py_INCREF(package); + if (!PyUnicode_Check(package)) { + PyErr_SetString(PyExc_TypeError, "package must be a string"); + goto error; + } + else if (spec != NULL && spec != Py_None) { + int equal; + PyObject *parent = _PyObject_GetAttrId(spec, &PyId_parent); + if (parent == NULL) { + goto error; + } + + equal = PyObject_RichCompareBool(package, parent, Py_EQ); + Py_DECREF(parent); + if (equal < 0) { + goto error; + } + else if (equal == 0) { + if (PyErr_WarnEx(PyExc_ImportWarning, + "__package__ != __spec__.parent", 1) < 0) { + goto error; + } + } + } + } + else if (spec != NULL && spec != Py_None) { + package = _PyObject_GetAttrId(spec, &PyId_parent); + if (package == NULL) { + goto error; + } + else if (!PyUnicode_Check(package)) { + PyErr_SetString(PyExc_TypeError, + "__spec__.parent must be a string"); goto error; } } 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"); + if (PyErr_WarnEx(PyExc_ImportWarning, + "can't resolve package from __spec__ or __package__, " + "falling back on __name__ and __path__", 1) < 0) { goto error; } - globals = given_globals; - Py_INCREF(globals); + + package = _PyDict_GetItemId(globals, &PyId___name__); + if (package == NULL) { + PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); + goto error; + } + + Py_INCREF(package); + if (!PyUnicode_Check(package)) { + PyErr_SetString(PyExc_TypeError, "__name__ must be a string"); + goto error; + } + + if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) { + Py_ssize_t dot; + + if (PyUnicode_READY(package) < 0) { + goto error; + } + + dot = PyUnicode_FindChar(package, '.', + 0, PyUnicode_GET_LENGTH(package), -1); + if (dot == -2) { + goto error; + } + + if (dot >= 0) { + PyObject *substr = PyUnicode_Substring(package, 0, dot); + if (substr == NULL) { + goto error; + } + Py_SETREF(package, substr); + } + } } - if (given_fromlist == NULL) { - fromlist = PyList_New(0); - if (fromlist == NULL) { + last_dot = PyUnicode_GET_LENGTH(package); + if (last_dot == 0) { + PyErr_SetString(PyExc_ImportError, + "attempted relative import with no known parent package"); + goto error; + } + else if (PyDict_GetItem(interp->modules, package) == NULL) { + PyErr_Format(PyExc_SystemError, + "Parent module %R not loaded, cannot perform relative " + "import", package); + goto error; + } + + for (level_up = 1; level_up < level; level_up += 1) { + last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); + if (last_dot == -2) { + goto error; + } + else if (last_dot == -1) { + PyErr_SetString(PyExc_ValueError, + "attempted relative import beyond top-level " + "package"); goto error; } } - else { - fromlist = given_fromlist; - Py_INCREF(fromlist); + + base = PyUnicode_Substring(package, 0, last_dot); + Py_DECREF(package); + if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) { + return base; } + + abs_name = PyUnicode_FromFormat("%U.%U", base, name); + Py_DECREF(base); + 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; @@ -1403,170 +1512,28 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, PyErr_SetString(PyExc_TypeError, "module name must be a string"); goto error; } - else if (PyUnicode_READY(name) < 0) { + 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__); - spec = _PyDict_GetItemId(globals, &PyId___spec__); - - if (package != NULL && package != Py_None) { - Py_INCREF(package); - if (!PyUnicode_Check(package)) { - PyErr_SetString(PyExc_TypeError, "package must be a string"); - goto error; - } - else if (spec != NULL && spec != Py_None) { - int equal; - PyObject *parent = PyObject_GetAttrString(spec, "parent"); - if (parent == NULL) { - goto error; - } - - equal = PyObject_RichCompareBool(package, parent, Py_EQ); - Py_DECREF(parent); - if (equal < 0) { - goto error; - } - else if (equal == 0) { - if (PyErr_WarnEx(PyExc_ImportWarning, - "__package__ != __spec__.parent", 1) < 0) { - goto error; - } - } - } - } - else if (spec != NULL && spec != Py_None) { - package = PyObject_GetAttrString(spec, "parent"); - if (package == NULL) { - goto error; - } - else if (!PyUnicode_Check(package)) { - PyErr_SetString(PyExc_TypeError, - "__spec__.parent must be a string"); - goto error; - } - } - else { - package = NULL; - if (PyErr_WarnEx(PyExc_ImportWarning, - "can't resolve package from __spec__ or __package__, " - "falling back on __name__ and __path__", 1) < 0) { - goto error; - } - - package = _PyDict_GetItemId(globals, &PyId___name__); - if (package == NULL) { - PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); - goto error; - } - - Py_INCREF(package); - if (!PyUnicode_Check(package)) { - PyErr_SetString(PyExc_TypeError, "__name__ must be a string"); - goto error; - } - if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) { - Py_ssize_t dot; - - if (PyUnicode_READY(package) < 0) { - goto error; - } - - dot = PyUnicode_FindChar(package, '.', - 0, PyUnicode_GET_LENGTH(package), -1); - if (dot == -2) { - goto error; - } - - if (dot >= 0) { - PyObject *substr = PyUnicode_Substring(package, 0, dot); - if (substr == NULL) { - goto error; - } - Py_SETREF(package, substr); - } - } - } - - if (PyUnicode_CompareWithASCIIString(package, "") == 0) { - PyErr_SetString(PyExc_ImportError, - "attempted relative import with no known parent package"); - goto error; - } - else if (PyDict_GetItem(interp->modules, package) == NULL) { - PyErr_Format(PyExc_SystemError, - "Parent module %R not loaded, cannot perform relative " - "import", package); + 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; } - 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) { - last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); - if (last_dot == -2) { - goto error; - } - else if (last_dot == -1) { - PyErr_SetString(PyExc_ValueError, - "attempted relative import beyond top-level " - "package"); - goto error; - } - } - - base = PyUnicode_Substring(package, 0, last_dot); - if (base == NULL) - goto error; - - if (PyUnicode_GET_LENGTH(name) > 0) { - abs_name = PyUnicode_FromFormat("%U.%U", base, name); - Py_DECREF(base); - if (abs_name == NULL) { - goto error; - } - } - else { - abs_name = base; - } - } - else { abs_name = 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); if (mod == Py_None) { PyObject *msg = PyUnicode_FromFormat("import of %R halted; " @@ -1576,9 +1543,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, Py_DECREF(msg); } mod = NULL; - goto error_with_unlock; + goto error; } else if (mod != NULL) { + _Py_IDENTIFIER(__spec__); + _Py_IDENTIFIER(_initializing); + _Py_IDENTIFIER(_lock_unlock_module); PyObject *value = NULL; PyObject *spec; int initializing = 0; @@ -1601,39 +1571,39 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, Py_DECREF(value); if (initializing == -1) PyErr_Clear(); - } - if (initializing > 0) { - /* _bootstrap._lock_unlock_module() releases the import lock */ - value = _PyObject_CallMethodIdObjArgs(interp->importlib, - &PyId__lock_unlock_module, abs_name, - NULL); - if (value == NULL) - goto error; - Py_DECREF(value); - } - else { + if (initializing > 0) { #ifdef WITH_THREAD - if (_PyImport_ReleaseLock() < 0) { - PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); - goto error; - } + _PyImport_AcquireLock(); #endif + /* _bootstrap._lock_unlock_module() releases the import lock */ + value = _PyObject_CallMethodIdObjArgs(interp->importlib, + &PyId__lock_unlock_module, abs_name, + NULL); + if (value == NULL) + goto error; + Py_DECREF(value); + } } } else { +#ifdef WITH_THREAD + _PyImport_AcquireLock(); +#endif /* _bootstrap._find_and_load() releases the import lock */ mod = _PyObject_CallMethodIdObjArgs(interp->importlib, &PyId__find_and_load, abs_name, - builtins_import, NULL); + interp->import_func, NULL); if (mod == NULL) { goto error; } } - /* From now on we don't hold the import lock anymore. */ - has_from = PyObject_IsTrue(fromlist); - if (has_from < 0) - goto error; + has_from = 0; + if (fromlist != NULL && fromlist != Py_None) { + has_from = PyObject_IsTrue(fromlist); + if (has_from < 0) + goto error; + } if (!has_from) { Py_ssize_t len = PyUnicode_GET_LENGTH(name); if (level == 0 || len > 0) { @@ -1657,7 +1627,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, goto error; } - final_mod = PyObject_CallFunctionObjArgs(builtins_import, front, NULL); + final_mod = PyImport_ImportModuleLevelObject(front, NULL, NULL, NULL, 0); Py_DECREF(front); } else { @@ -1670,15 +1640,14 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, } final_mod = PyDict_GetItem(interp->modules, to_return); + Py_DECREF(to_return); if (final_mod == NULL) { PyErr_Format(PyExc_KeyError, "%R not in sys.modules as expected", to_return); + goto error; } - else { - Py_INCREF(final_mod); - } - Py_DECREF(to_return); + Py_INCREF(final_mod); } } else { @@ -1689,24 +1658,14 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, else { final_mod = _PyObject_CallMethodIdObjArgs(interp->importlib, &PyId__handle_fromlist, mod, - fromlist, builtins_import, + fromlist, interp->import_func, NULL); } - goto error; - error_with_unlock: -#ifdef WITH_THREAD - if (_PyImport_ReleaseLock() < 0) { - PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); - } -#endif error: Py_XDECREF(abs_name); - Py_XDECREF(builtins_import); Py_XDECREF(mod); Py_XDECREF(package); - Py_XDECREF(globals); - Py_XDECREF(fromlist); if (final_mod == NULL) remove_importlib_frames(); return final_mod; -- cgit v1.2.1 From 54dc09e399e40109e5b61f0ed2e94558cc07aaa8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 7 Sep 2016 16:56:15 -0700 Subject: Issue #15767: Use ModuleNotFoundError. --- Python/import.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/import.c') diff --git a/Python/import.c b/Python/import.c index 3bac5b8e41..c780fe2976 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1539,7 +1539,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject *msg = PyUnicode_FromFormat("import of %R halted; " "None in sys.modules", abs_name); if (msg != NULL) { - PyErr_SetImportError(msg, abs_name, NULL); + PyErr_SetImportErrorSubclass(PyExc_ModuleNotFoundError, msg, + abs_name, NULL); Py_DECREF(msg); } mod = NULL; -- cgit v1.2.1 From ff13bdffd9670a5c815804cf39bb4db2b168b943 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 7 Sep 2016 17:00:43 -0700 Subject: Issue #27911: Remove some unnecessary error checks in import.c. Thanks to Xiang Zhang for the patch. --- Python/import.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'Python/import.c') diff --git a/Python/import.c b/Python/import.c index c780fe2976..17188c275a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1942,19 +1942,15 @@ exec_builtin_or_dynamic(PyObject *mod) { def = PyModule_GetDef(mod); if (def == NULL) { - if (PyErr_Occurred()) { - return -1; - } return 0; } + state = PyModule_GetState(mod); - if (PyErr_Occurred()) { - return -1; - } if (state) { /* Already initialized; skip reload */ return 0; } + return PyModule_ExecDef(mod, def); } -- cgit v1.2.1 From b2329bd37e66414113382ba205d3f0a8d18c4d71 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 9 Sep 2016 00:25:03 +0200 Subject: Fix potential NULL pointer dereference in _imp_create_builtin PyModule_GetDef() can return NULL. Let's check the return value properly like in the other five cases. CID 1299590 --- Python/import.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python/import.c') diff --git a/Python/import.c b/Python/import.c index 17188c275a..dfdd9409e5 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1077,6 +1077,10 @@ _imp_create_builtin(PyObject *module, PyObject *spec) } else { /* Remember pointer to module init function. */ def = PyModule_GetDef(mod); + if (def == NULL) { + Py_DECREF(name); + return NULL; + } def->m_base.m_init = p->initfunc; if (_PyImport_FixupExtensionObject(mod, name, name) < 0) { Py_DECREF(name); -- cgit v1.2.1