summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Python/import.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/import.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (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.c653
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;
}