diff options
| author | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
| commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
| tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/import.c | |
| parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Python/import.c')
| -rw-r--r-- | contrib/tools/python3/src/Python/import.c | 653 |
1 files changed, 221 insertions, 432 deletions
diff --git a/contrib/tools/python3/src/Python/import.c b/contrib/tools/python3/src/Python/import.c index e4dbf4b0d8c..bd33fa184ab 100644 --- a/contrib/tools/python3/src/Python/import.c +++ b/contrib/tools/python3/src/Python/import.c @@ -2,8 +2,7 @@ #include "Python.h" -#include "Python-ast.h" -#undef Yield /* undefine macro conflicting with <winbase.h> */ +#include "pycore_import.h" // _PyImport_BootstrapImp() #include "pycore_initconfig.h" #include "pycore_pyerrors.h" #include "pycore_pyhash.h" @@ -52,43 +51,6 @@ module _imp /* Initialize things */ PyStatus -_PyImportHooks_Init(PyThreadState *tstate) -{ - PyObject *v, *path_hooks = NULL; - int err = 0; - - /* adding sys.path_hooks and sys.path_importer_cache */ - v = PyList_New(0); - if (v == NULL) - goto error; - err = PySys_SetObject("meta_path", v); - Py_DECREF(v); - if (err) - goto error; - v = PyDict_New(); - if (v == NULL) - goto error; - err = PySys_SetObject("path_importer_cache", v); - Py_DECREF(v); - if (err) - goto error; - path_hooks = PyList_New(0); - if (path_hooks == NULL) - goto error; - err = PySys_SetObject("path_hooks", path_hooks); - if (err) { - goto error; - } - Py_DECREF(path_hooks); - return _PyStatus_OK(); - - error: - _PyErr_Print(tstate); - return _PyStatus_ERR("initializing sys.meta_path, sys.path_hooks, " - "or path_importer_cache failed"); -} - -PyStatus _PyImportZip_Init(PyThreadState *tstate) { PyObject *path_hooks, *zipimport; @@ -148,7 +110,7 @@ _PyImportZip_Init(PyThreadState *tstate) in different threads to return with a partially loaded module. These calls are serialized by the global interpreter lock. */ -static PyThread_type_lock import_lock = 0; +static PyThread_type_lock import_lock = NULL; static unsigned long import_lock_thread = PYTHREAD_INVALID_THREAD_ID; static int import_lock_level = 0; @@ -171,7 +133,7 @@ _PyImport_AcquireLock(void) !PyThread_acquire_lock(import_lock, 0)) { PyThreadState *tstate = PyEval_SaveThread(); - PyThread_acquire_lock(import_lock, 1); + PyThread_acquire_lock(import_lock, WAIT_LOCK); PyEval_RestoreThread(tstate); } assert(import_lock_level == 0); @@ -197,33 +159,30 @@ _PyImport_ReleaseLock(void) } #ifdef HAVE_FORK -/* This function is called from PyOS_AfterFork_Child to ensure that newly +/* This function is called from PyOS_AfterFork_Child() to ensure that newly created child processes do not share locks with the parent. We now acquire the import lock around fork() calls but on some platforms (Solaris 9 and earlier? see isue7242) that still left us with problems. */ - -void +PyStatus _PyImport_ReInitLock(void) { if (import_lock != NULL) { if (_PyThread_at_fork_reinit(&import_lock) < 0) { - _Py_FatalErrorFunc(__func__, "failed to create a new lock"); + return _PyStatus_ERR("failed to create a new lock"); } } + if (import_lock_level > 1) { /* Forked as a side effect of import */ unsigned long me = PyThread_get_thread_ident(); - /* The following could fail if the lock is already held, but forking as - a side-effect of an import is a) rare, b) nuts, and c) difficult to - do thanks to the lock only being held when doing individual module - locks per import. */ - PyThread_acquire_lock(import_lock, NOWAIT_LOCK); + PyThread_acquire_lock(import_lock, WAIT_LOCK); import_lock_thread = me; import_lock_level--; } else { import_lock_thread = PYTHREAD_INVALID_THREAD_ID; import_lock_level = 0; } + return _PyStatus_OK(); } #endif @@ -343,16 +302,16 @@ _PyImport_GetModuleId(struct _Py_Identifier *nameid) int _PyImport_SetModule(PyObject *name, PyObject *m) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *modules = tstate->interp->modules; + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyObject *modules = interp->modules; return PyObject_SetItem(modules, name, m); } int _PyImport_SetModuleString(const char *name, PyObject *m) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *modules = tstate->interp->modules; + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyObject *modules = interp->modules; return PyMapping_SetItemString(modules, name, m); } @@ -384,9 +343,8 @@ import_get_module(PyThreadState *tstate, PyObject *name) static int -import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) +import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *name) { - PyInterpreterState *interp = tstate->interp; PyObject *spec; _Py_IDENTIFIER(_lock_unlock_module); @@ -412,233 +370,6 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) } -/* List of names to clear in sys */ -static const char * const sys_deletes[] = { - "path", "argv", "ps1", "ps2", - "last_type", "last_value", "last_traceback", - "path_hooks", "path_importer_cache", "meta_path", - "__interactivehook__", - NULL -}; - -static const char * const sys_files[] = { - "stdin", "__stdin__", - "stdout", "__stdout__", - "stderr", "__stderr__", - NULL -}; - -/* Un-initialize things, as good as we can */ - -void -_PyImport_Cleanup(PyThreadState *tstate) -{ - PyInterpreterState *interp = tstate->interp; - PyObject *modules = interp->modules; - if (modules == NULL) { - /* Already done */ - return; - } - - /* Delete some special variables first. These are common - places where user values hide and people complain when their - destructors fail. Since the modules containing them are - deleted *last* of all, they would come too late in the normal - destruction order. Sigh. */ - - /* XXX Perhaps these precautions are obsolete. Who knows? */ - - int verbose = _PyInterpreterState_GetConfig(interp)->verbose; - if (verbose) { - PySys_WriteStderr("# clear builtins._\n"); - } - if (PyDict_SetItemString(interp->builtins, "_", Py_None) < 0) { - PyErr_WriteUnraisable(NULL); - } - - const char * const *p; - for (p = sys_deletes; *p != NULL; p++) { - if (verbose) { - PySys_WriteStderr("# clear sys.%s\n", *p); - } - if (PyDict_SetItemString(interp->sysdict, *p, Py_None) < 0) { - PyErr_WriteUnraisable(NULL); - } - } - for (p = sys_files; *p != NULL; p+=2) { - if (verbose) { - PySys_WriteStderr("# restore sys.%s\n", *p); - } - PyObject *value = _PyDict_GetItemStringWithError(interp->sysdict, - *(p+1)); - if (value == NULL) { - if (_PyErr_Occurred(tstate)) { - PyErr_WriteUnraisable(NULL); - } - value = Py_None; - } - if (PyDict_SetItemString(interp->sysdict, *p, value) < 0) { - PyErr_WriteUnraisable(NULL); - } - } - - /* We prepare a list which will receive (name, weakref) tuples of - modules when they are removed from sys.modules. The name is used - for diagnosis messages (in verbose mode), while the weakref helps - detect those modules which have been held alive. */ - PyObject *weaklist = PyList_New(0); - if (weaklist == NULL) { - PyErr_WriteUnraisable(NULL); - } - -#define STORE_MODULE_WEAKREF(name, mod) \ - if (weaklist != NULL) { \ - PyObject *wr = PyWeakref_NewRef(mod, NULL); \ - if (wr) { \ - PyObject *tup = PyTuple_Pack(2, name, wr); \ - if (!tup || PyList_Append(weaklist, tup) < 0) { \ - PyErr_WriteUnraisable(NULL); \ - } \ - Py_XDECREF(tup); \ - Py_DECREF(wr); \ - } \ - else { \ - PyErr_WriteUnraisable(NULL); \ - } \ - } -#define CLEAR_MODULE(name, mod) \ - if (PyModule_Check(mod)) { \ - if (verbose && PyUnicode_Check(name)) { \ - PySys_FormatStderr("# cleanup[2] removing %U\n", name); \ - } \ - STORE_MODULE_WEAKREF(name, mod); \ - if (PyObject_SetItem(modules, name, Py_None) < 0) { \ - PyErr_WriteUnraisable(NULL); \ - } \ - } - - /* Remove all modules from sys.modules, hoping that garbage collection - can reclaim most of them. */ - if (PyDict_CheckExact(modules)) { - Py_ssize_t pos = 0; - PyObject *key, *value; - while (PyDict_Next(modules, &pos, &key, &value)) { - CLEAR_MODULE(key, value); - } - } - else { - PyObject *iterator = PyObject_GetIter(modules); - if (iterator == NULL) { - PyErr_WriteUnraisable(NULL); - } - else { - PyObject *key; - while ((key = PyIter_Next(iterator))) { - PyObject *value = PyObject_GetItem(modules, key); - if (value == NULL) { - PyErr_WriteUnraisable(NULL); - continue; - } - CLEAR_MODULE(key, value); - Py_DECREF(value); - Py_DECREF(key); - } - if (PyErr_Occurred()) { - PyErr_WriteUnraisable(NULL); - } - Py_DECREF(iterator); - } - } - - /* Clear the modules dict. */ - if (PyDict_CheckExact(modules)) { - PyDict_Clear(modules); - } - else { - _Py_IDENTIFIER(clear); - if (_PyObject_CallMethodIdNoArgs(modules, &PyId_clear) == NULL) { - PyErr_WriteUnraisable(NULL); - } - } - /* Restore the original builtins dict, to ensure that any - user data gets cleared. */ - PyObject *dict = PyDict_Copy(interp->builtins); - if (dict == NULL) { - PyErr_WriteUnraisable(NULL); - } - PyDict_Clear(interp->builtins); - if (PyDict_Update(interp->builtins, interp->builtins_copy)) { - _PyErr_Clear(tstate); - } - Py_XDECREF(dict); - /* Collect references */ - _PyGC_CollectNoFail(); - /* Dump GC stats before it's too late, since it uses the warnings - machinery. */ - _PyGC_DumpShutdownStats(tstate); - - /* Now, if there are any modules left alive, clear their globals to - minimize potential leaks. All C extension modules actually end - up here, since they are kept alive in the interpreter state. - - The special treatment of "builtins" here is because even - when it's not referenced as a module, its dictionary is - referenced by almost every module's __builtins__. Since - deleting a module clears its dictionary (even if there are - references left to it), we need to delete the "builtins" - module last. Likewise, we don't delete sys until the very - end because it is implicitly referenced (e.g. by print). */ - if (weaklist != NULL) { - Py_ssize_t i; - /* Since dict is ordered in CPython 3.6+, modules are saved in - importing order. First clear modules imported later. */ - for (i = PyList_GET_SIZE(weaklist) - 1; i >= 0; i--) { - PyObject *tup = PyList_GET_ITEM(weaklist, i); - PyObject *name = PyTuple_GET_ITEM(tup, 0); - PyObject *mod = PyWeakref_GET_OBJECT(PyTuple_GET_ITEM(tup, 1)); - if (mod == Py_None) - continue; - assert(PyModule_Check(mod)); - dict = PyModule_GetDict(mod); - if (dict == interp->builtins || dict == interp->sysdict) - continue; - Py_INCREF(mod); - if (verbose && PyUnicode_Check(name)) { - PySys_FormatStderr("# cleanup[3] wiping %U\n", name); - } - _PyModule_Clear(mod); - Py_DECREF(mod); - } - Py_DECREF(weaklist); - } - - /* Next, delete sys and builtins (in that order) */ - if (verbose) { - PySys_FormatStderr("# cleanup[3] wiping sys\n"); - } - _PyModule_ClearDict(interp->sysdict); - if (verbose) { - PySys_FormatStderr("# cleanup[3] wiping builtins\n"); - } - _PyModule_ClearDict(interp->builtins); - - /* Clear module dict copies stored in the interpreter state */ - _PyInterpreterState_ClearModules(interp); - - /* Clear and delete the modules directory. Actual modules will - still be there only if imported during the execution of some - destructor. */ - interp->modules = NULL; - Py_DECREF(modules); - - /* Once more */ - _PyGC_CollectNoFail(); - -#undef CLEAR_MODULE -#undef STORE_MODULE_WEAKREF -} - - /* Helper for pythonrun.c -- return magic number and tag. */ long @@ -678,7 +409,7 @@ PyImport_GetMagicTag(void) modules. A copy of the module's dictionary is stored by calling _PyImport_FixupExtensionObject() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling - _PyImport_FindExtensionObject(). + import_find_extension(). Modules which do support multiple initialization set their m_size field to a non-negative number (indicating the size of the @@ -712,7 +443,7 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, // bpo-44050: Extensions and def->m_base.m_copy can be updated // when the extension module doesn't support sub-interpreters. - if (_Py_IsMainInterpreter(tstate) || def->m_size == -1) { + if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { if (def->m_size == -1) { if (def->m_base.m_copy) { /* Somebody already imported the module, @@ -793,10 +524,14 @@ import_find_extension(PyThreadState *tstate, PyObject *name, if (mod == NULL) return NULL; mdict = PyModule_GetDict(mod); - if (mdict == NULL) + if (mdict == NULL) { + Py_DECREF(mod); return NULL; - if (PyDict_Update(mdict, def->m_base.m_copy)) + } + if (PyDict_Update(mdict, def->m_base.m_copy)) { + Py_DECREF(mod); return NULL; + } } else { if (def->m_base.m_init == NULL) @@ -808,10 +543,10 @@ import_find_extension(PyThreadState *tstate, PyObject *name, Py_DECREF(mod); return NULL; } - Py_DECREF(mod); } if (_PyState_AddModule(tstate, mod, def) < 0) { PyMapping_DelItem(modules, name); + Py_DECREF(mod); return NULL; } @@ -827,27 +562,23 @@ PyObject * _PyImport_FindExtensionObject(PyObject *name, PyObject *filename) { PyThreadState *tstate = _PyThreadState_GET(); - return import_find_extension(tstate, name, filename); + PyObject *mod = import_find_extension(tstate, name, filename); + if (mod) { + PyObject *ref = PyWeakref_NewRef(mod, NULL); + Py_DECREF(mod); + if (ref == NULL) { + return NULL; + } + mod = PyWeakref_GetObject(ref); + Py_DECREF(ref); + } + return mod; /* borrowed reference */ } -PyObject * -_PyImport_FindBuiltin(PyThreadState *tstate, const char *name) -{ - PyObject *res, *nameobj; - nameobj = PyUnicode_InternFromString(name); - if (nameobj == NULL) - return NULL; - res = import_find_extension(tstate, nameobj, nameobj); - Py_DECREF(nameobj); - return res; -} - /* Get the module object corresponding to a module name. First check the modules dictionary if there's one there, - if not, create a new one and insert it in the modules dictionary. - Because the former action is most common, THIS DOES NOT RETURN A - 'NEW' REFERENCE! */ + if not, create a new one and insert it in the modules dictionary. */ static PyObject * import_add_module(PyThreadState *tstate, PyObject *name) @@ -862,6 +593,7 @@ import_add_module(PyThreadState *tstate, PyObject *name) PyObject *m; if (PyDict_CheckExact(modules)) { m = PyDict_GetItemWithError(modules, name); + Py_XINCREF(m); } else { m = PyObject_GetItem(modules, name); @@ -877,6 +609,7 @@ import_add_module(PyThreadState *tstate, PyObject *name) if (m != NULL && PyModule_Check(m)) { return m; } + Py_XDECREF(m); m = PyModule_NewObject(name); if (m == NULL) return NULL; @@ -884,7 +617,6 @@ import_add_module(PyThreadState *tstate, PyObject *name) Py_DECREF(m); return NULL; } - Py_DECREF(m); /* Yes, it still exists, in modules! */ return m; } @@ -893,7 +625,17 @@ PyObject * PyImport_AddModuleObject(PyObject *name) { PyThreadState *tstate = _PyThreadState_GET(); - return import_add_module(tstate, name); + PyObject *mod = import_add_module(tstate, name); + if (mod) { + PyObject *ref = PyWeakref_NewRef(mod, NULL); + Py_DECREF(mod); + if (ref == NULL) { + return NULL; + } + mod = PyWeakref_GetObject(ref); + Py_DECREF(ref); + } + return mod; /* borrowed reference */ } @@ -1018,7 +760,7 @@ static PyObject * module_dict_for_exec(PyThreadState *tstate, PyObject *name) { _Py_IDENTIFIER(__builtins__); - PyObject *m, *d = NULL; + PyObject *m, *d; m = import_add_module(tstate, name); if (m == NULL) @@ -1026,17 +768,20 @@ module_dict_for_exec(PyThreadState *tstate, PyObject *name) /* If the module is being reloaded, we get the old module back and re-use its dict to exec the new code. */ d = PyModule_GetDict(m); - if (_PyDict_GetItemIdWithError(d, &PyId___builtins__) == NULL) { - if (_PyErr_Occurred(tstate) || - _PyDict_SetItemId(d, &PyId___builtins__, - PyEval_GetBuiltins()) != 0) - { - remove_module(tstate, name); - return NULL; - } + int r = _PyDict_ContainsId(d, &PyId___builtins__); + if (r == 0) { + r = _PyDict_SetItemId(d, &PyId___builtins__, + PyEval_GetBuiltins()); + } + if (r < 0) { + remove_module(tstate, name); + Py_DECREF(m); + return NULL; } - return d; /* Return a borrowed reference. */ + Py_INCREF(d); + Py_DECREF(m); + return d; } static PyObject * @@ -1080,8 +825,10 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, } external = PyObject_GetAttrString(tstate->interp->importlib, "_bootstrap_external"); - if (external == NULL) + if (external == NULL) { + Py_DECREF(d); return NULL; + } res = _PyObject_CallMethodIdObjArgs(external, &PyId__fix_up_module, d, name, pathname, cpathname, NULL); @@ -1090,6 +837,7 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, Py_DECREF(res); res = exec_code_in_module(tstate, name, d, co); } + Py_DECREF(d); return res; } @@ -1183,8 +931,7 @@ is_builtin(PyObject *name) that can handle the path item. Return None if no hook could; 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. */ + path_importer_cache. */ static PyObject * get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, @@ -1202,8 +949,10 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, return NULL; /* Shouldn't happen */ importer = PyDict_GetItemWithError(path_importer_cache, p); - if (importer != NULL || _PyErr_Occurred(tstate)) + if (importer != NULL || _PyErr_Occurred(tstate)) { + Py_XINCREF(importer); return importer; + } /* set path_importer_cache[p] to None to avoid recursion */ if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0) @@ -1223,13 +972,11 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, _PyErr_Clear(tstate); } if (importer == NULL) { - return Py_None; + Py_RETURN_NONE; } - if (importer != NULL) { - int err = PyDict_SetItem(path_importer_cache, p, importer); + if (PyDict_SetItem(path_importer_cache, p, importer) < 0) { Py_DECREF(importer); - if (err != 0) - return NULL; + return NULL; } return importer; } @@ -1238,96 +985,87 @@ PyObject * PyImport_GetImporter(PyObject *path) { PyThreadState *tstate = _PyThreadState_GET(); - PyObject *importer=NULL, *path_importer_cache=NULL, *path_hooks=NULL; - - path_importer_cache = PySys_GetObject("path_importer_cache"); - path_hooks = PySys_GetObject("path_hooks"); - if (path_importer_cache != NULL && path_hooks != NULL) { - importer = get_path_importer(tstate, path_importer_cache, - path_hooks, path); + PyObject *path_importer_cache = PySys_GetObject("path_importer_cache"); + PyObject *path_hooks = PySys_GetObject("path_hooks"); + if (path_importer_cache == NULL || path_hooks == NULL) { + return NULL; } - Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ - return importer; + return get_path_importer(tstate, path_importer_cache, path_hooks, path); } -/*[clinic input] -_imp.create_builtin - - spec: object - / - -Create an extension module. -[clinic start generated code]*/ - -static PyObject * -_imp_create_builtin(PyObject *module, PyObject *spec) -/*[clinic end generated code: output=ace7ff22271e6f39 input=37f966f890384e47]*/ +static PyObject* +create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) { - PyThreadState *tstate = _PyThreadState_GET(); - struct _inittab *p; - PyObject *name; - const char *namestr; - PyObject *mod; - - name = PyObject_GetAttrString(spec, "name"); - if (name == NULL) { - return NULL; - } - - mod = _PyImport_FindExtensionObject(name, name); + PyObject *mod = import_find_extension(tstate, name, name); if (mod || _PyErr_Occurred(tstate)) { - Py_DECREF(name); - Py_XINCREF(mod); return mod; } - namestr = PyUnicode_AsUTF8(name); - if (namestr == NULL) { - Py_DECREF(name); - return NULL; - } - PyObject *modules = tstate->interp->modules; - for (p = PyImport_Inittab; p->name != NULL; p++) { - PyModuleDef *def; + for (struct _inittab *p = PyImport_Inittab; p->name != NULL; p++) { if (_PyUnicode_EqualToASCIIString(name, p->name)) { if (p->initfunc == NULL) { /* Cannot re-init internal module ("sys" or "builtins") */ - mod = PyImport_AddModule(namestr); - Py_DECREF(name); - return mod; + return PyImport_AddModuleObject(name); } + mod = (*p->initfunc)(); if (mod == NULL) { - Py_DECREF(name); return NULL; } + if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { - Py_DECREF(name); return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); - } else { + } + else { /* Remember pointer to module init function. */ - def = PyModule_GetDef(mod); + PyModuleDef *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, modules) < 0) { - Py_DECREF(name); return NULL; } - Py_DECREF(name); return mod; } } } - Py_DECREF(name); + + // not found Py_RETURN_NONE; } + +/*[clinic input] +_imp.create_builtin + + spec: object + / + +Create an extension module. +[clinic start generated code]*/ + +static PyObject * +_imp_create_builtin(PyObject *module, PyObject *spec) +/*[clinic end generated code: output=ace7ff22271e6f39 input=37f966f890384e47]*/ +{ + PyThreadState *tstate = _PyThreadState_GET(); + + PyObject *name = PyObject_GetAttrString(spec, "name"); + if (name == NULL) { + return NULL; + } + + PyObject *mod = create_builtin(tstate, name, spec); + Py_DECREF(name); + return mod; +} + + /* Frozen modules */ static const struct _frozen * @@ -1440,10 +1178,12 @@ PyImport_ImportFrozenModuleObject(PyObject *name) d = PyModule_GetDict(m); l = PyList_New(0); if (l == NULL) { + Py_DECREF(m); goto err_return; } err = PyDict_SetItemString(d, "__path__", l); Py_DECREF(l); + Py_DECREF(m); if (err != 0) goto err_return; } @@ -1452,6 +1192,7 @@ PyImport_ImportFrozenModuleObject(PyObject *name) goto err_return; } m = exec_code_in_module(tstate, name, d, co); + Py_DECREF(d); if (m == NULL) { goto err_return; } @@ -1670,10 +1411,14 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level goto error; } - if (_PyDict_GetItemIdWithError(globals, &PyId___path__) == NULL) { + int haspath = _PyDict_ContainsId(globals, &PyId___path__); + if (haspath < 0) { + goto error; + } + if (!haspath) { Py_ssize_t dot; - if (_PyErr_Occurred(tstate) || PyUnicode_READY(package) < 0) { + if (PyUnicode_READY(package) < 0) { goto error; } @@ -1806,7 +1551,7 @@ PyImport_GetModule(PyObject *name) mod = import_get_module(tstate, name); if (mod != NULL && mod != Py_None) { - if (import_ensure_initialized(tstate, mod, name) < 0) { + if (import_ensure_initialized(tstate->interp, mod, name) < 0) { Py_DECREF(mod); remove_importlib_frames(tstate); return NULL; @@ -1870,7 +1615,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } if (mod != NULL && mod != Py_None) { - if (import_ensure_initialized(tstate, mod, abs_name) < 0) { + if (import_ensure_initialized(tstate->interp, mod, abs_name) < 0) { goto error; } } @@ -2021,26 +1766,29 @@ PyImport_ReloadModule(PyObject *m) PyObject * PyImport_Import(PyObject *module_name) { + _Py_IDENTIFIER(__import__); + _Py_IDENTIFIER(__builtins__); + PyThreadState *tstate = _PyThreadState_GET(); - static PyObject *silly_list = NULL; - static PyObject *builtins_str = NULL; - static PyObject *import_str = NULL; PyObject *globals = NULL; PyObject *import = NULL; PyObject *builtins = NULL; PyObject *r = NULL; /* Initialize constant string objects */ - if (silly_list == NULL) { - import_str = PyUnicode_InternFromString("__import__"); - if (import_str == NULL) - return NULL; - builtins_str = PyUnicode_InternFromString("__builtins__"); - if (builtins_str == NULL) - return NULL; - silly_list = PyList_New(0); - if (silly_list == NULL) - return NULL; + PyObject *import_str = _PyUnicode_FromId(&PyId___import__); // borrowed ref + if (import_str == NULL) { + return NULL; + } + + PyObject *builtins_str = _PyUnicode_FromId(&PyId___builtins__); // borrowed ref + if (builtins_str == NULL) { + return NULL; + } + + PyObject *from_list = PyList_New(0); + if (from_list == NULL) { + goto err; } /* Get the builtins from current globals */ @@ -2055,8 +1803,9 @@ PyImport_Import(PyObject *module_name) /* No globals -- use standard builtins, and fake globals */ builtins = PyImport_ImportModuleLevel("builtins", NULL, NULL, NULL, 0); - if (builtins == NULL) - return NULL; + if (builtins == NULL) { + goto err; + } globals = Py_BuildValue("{OO}", builtins_str, builtins); if (globals == NULL) goto err; @@ -2078,7 +1827,7 @@ PyImport_Import(PyObject *module_name) Always use absolute import here. Calling for side-effect of import. */ r = PyObject_CallFunction(import, "OOOOi", module_name, globals, - globals, silly_list, 0, NULL); + globals, from_list, 0, NULL); if (r == NULL) goto err; Py_DECREF(r); @@ -2092,6 +1841,7 @@ PyImport_Import(PyObject *module_name) Py_XDECREF(globals); Py_XDECREF(builtins); Py_XDECREF(import); + Py_XDECREF(from_list); return r; } @@ -2148,7 +1898,6 @@ _imp_init_frozen_impl(PyObject *module, PyObject *name) { PyThreadState *tstate = _PyThreadState_GET(); int ret; - PyObject *m; ret = PyImport_ImportFrozenModuleObject(name); if (ret < 0) @@ -2156,9 +1905,7 @@ _imp_init_frozen_impl(PyObject *module, PyObject *name) if (ret == 0) { Py_RETURN_NONE; } - m = import_add_module(tstate, name); - Py_XINCREF(m); - return m; + return import_add_module(tstate, name); } /*[clinic input] @@ -2282,11 +2029,11 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) return NULL; } - mod = _PyImport_FindExtensionObject(name, path); + PyThreadState *tstate = _PyThreadState_GET(); + mod = import_find_extension(tstate, name, path); if (mod != NULL || PyErr_Occurred()) { Py_DECREF(name); Py_DECREF(path); - Py_XINCREF(mod); return mod; } @@ -2397,46 +2144,88 @@ static PyMethodDef imp_methods[] = { }; -static struct PyModuleDef impmodule = { +static int +imp_module_exec(PyObject *module) +{ + const wchar_t *mode = _Py_GetConfig()->check_hash_pycs_mode; + PyObject *pyc_mode = PyUnicode_FromWideChar(mode, -1); + if (pyc_mode == NULL) { + return -1; + } + if (PyModule_AddObjectRef(module, "check_hash_based_pycs", pyc_mode) < 0) { + Py_DECREF(pyc_mode); + return -1; + } + Py_DECREF(pyc_mode); + + return 0; +} + + +static PyModuleDef_Slot imp_slots[] = { + {Py_mod_exec, imp_module_exec}, + {0, NULL} +}; + +static struct PyModuleDef imp_module = { PyModuleDef_HEAD_INIT, - "_imp", - doc_imp, - 0, - imp_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "_imp", + .m_doc = doc_imp, + .m_size = 0, + .m_methods = imp_methods, + .m_slots = imp_slots, }; PyMODINIT_FUNC PyInit__imp(void) { - PyObject *m, *d; + return PyModuleDef_Init(&imp_module); +} - m = PyModule_Create(&impmodule); - if (m == NULL) { - goto failure; + +// Import the _imp extension by calling manually _imp.create_builtin() and +// _imp.exec_builtin() since importlib is not initialized yet. Initializing +// importlib requires the _imp module: this function fix the bootstrap issue. +PyObject* +_PyImport_BootstrapImp(PyThreadState *tstate) +{ + PyObject *name = PyUnicode_FromString("_imp"); + if (name == NULL) { + return NULL; } - d = PyModule_GetDict(m); - if (d == NULL) { - goto failure; + + // Mock a ModuleSpec object just good enough for PyModule_FromDefAndSpec(): + // an object with just a name attribute. + // + // _imp.__spec__ is overridden by importlib._bootstrap._instal() anyway. + PyObject *attrs = Py_BuildValue("{sO}", "name", name); + if (attrs == NULL) { + goto error; + } + PyObject *spec = _PyNamespace_New(attrs); + Py_DECREF(attrs); + if (spec == NULL) { + goto error; } - const wchar_t *mode = _Py_GetConfig()->check_hash_pycs_mode; - PyObject *pyc_mode = PyUnicode_FromWideChar(mode, -1); - if (pyc_mode == NULL) { - goto failure; + // Create the _imp module from its definition. + PyObject *mod = create_builtin(tstate, name, spec); + Py_CLEAR(name); + Py_DECREF(spec); + if (mod == NULL) { + goto error; } - if (PyDict_SetItemString(d, "check_hash_based_pycs", pyc_mode) < 0) { - Py_DECREF(pyc_mode); - goto failure; + assert(mod != Py_None); // not found + + // Execute the _imp module: call imp_module_exec(). + if (exec_builtin_or_dynamic(mod) < 0) { + Py_DECREF(mod); + goto error; } - Py_DECREF(pyc_mode); + return mod; - return m; - failure: - Py_XDECREF(m); +error: + Py_XDECREF(name); return NULL; } |
