mirror of https://github.com/python/cpython
gh-101758: Clean Up Uses of Import State (gh-101919)
This change is almost entirely moving code around and hiding import state behind internal API. We introduce no changes to behavior, nor to non-internal API. (Since there was already going to be a lot of churn, I took this as an opportunity to re-organize import.c into topically-grouped sections of code.) The motivation is to simplify a number of upcoming changes. Specific changes: * move existing import-related code to import.c, wherever possible * add internal API for interacting with import state (both global and per-interpreter) * use only API outside of import.c (to limit churn there when changing the location, etc.) * consolidate the import-related state of PyInterpreterState into a single struct field (this changes layout slightly) * add macros for import state in import.c (to simplify changing the location) * group code in import.c into sections *remove _PyState_AddModule() https://github.com/python/cpython/issues/101758
This commit is contained in:
parent
c1ce0d178f
commit
b2fc549278
|
@ -36,11 +36,112 @@ struct _import_runtime_state {
|
||||||
const char * pkgcontext;
|
const char * pkgcontext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _import_state {
|
||||||
|
/* cached sys.modules dictionary */
|
||||||
|
PyObject *modules;
|
||||||
|
/* This is the list of module objects for all legacy (single-phase init)
|
||||||
|
extension modules ever loaded in this process (i.e. imported
|
||||||
|
in this interpreter or in any other). Py_None stands in for
|
||||||
|
modules that haven't actually been imported in this interpreter.
|
||||||
|
|
||||||
|
A module's index (PyModuleDef.m_base.m_index) is used to look up
|
||||||
|
the corresponding module object for this interpreter, if any.
|
||||||
|
(See PyState_FindModule().) When any extension module
|
||||||
|
is initialized during import, its moduledef gets initialized by
|
||||||
|
PyModuleDef_Init(), and the first time that happens for each
|
||||||
|
PyModuleDef, its index gets set to the current value of
|
||||||
|
a global counter (see _PyRuntimeState.imports.last_module_index).
|
||||||
|
The entry for that index in this interpreter remains unset until
|
||||||
|
the module is actually imported here. (Py_None is used as
|
||||||
|
a placeholder.) Note that multi-phase init modules always get
|
||||||
|
an index for which there will never be a module set.
|
||||||
|
|
||||||
|
This is initialized lazily in PyState_AddModule(), which is also
|
||||||
|
where modules get added. */
|
||||||
|
PyObject *modules_by_index;
|
||||||
|
/* importlib module._bootstrap */
|
||||||
|
PyObject *importlib;
|
||||||
|
/* override for config->use_frozen_modules (for tests)
|
||||||
|
(-1: "off", 1: "on", 0: no override) */
|
||||||
|
int override_frozen_modules;
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
int dlopenflags;
|
||||||
|
#endif
|
||||||
|
PyObject *import_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# if HAVE_DECL_RTLD_NOW
|
||||||
|
# define _Py_DLOPEN_FLAGS RTLD_NOW
|
||||||
|
# else
|
||||||
|
# define _Py_DLOPEN_FLAGS RTLD_LAZY
|
||||||
|
# endif
|
||||||
|
# define DLOPENFLAGS_INIT .dlopenflags = _Py_DLOPEN_FLAGS,
|
||||||
|
#else
|
||||||
|
# define _Py_DLOPEN_FLAGS 0
|
||||||
|
# define DLOPENFLAGS_INIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IMPORTS_INIT \
|
||||||
|
{ \
|
||||||
|
.override_frozen_modules = 0, \
|
||||||
|
DLOPENFLAGS_INIT \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void _PyImport_ClearCore(PyInterpreterState *interp);
|
||||||
|
|
||||||
|
extern Py_ssize_t _PyImport_GetNextModuleIndex(void);
|
||||||
|
extern const char * _PyImport_ResolveNameWithPackageContext(const char *name);
|
||||||
|
extern const char * _PyImport_SwapPackageContext(const char *newcontext);
|
||||||
|
|
||||||
|
extern int _PyImport_GetDLOpenFlags(PyInterpreterState *interp);
|
||||||
|
extern void _PyImport_SetDLOpenFlags(PyInterpreterState *interp, int new_val);
|
||||||
|
|
||||||
|
extern PyObject * _PyImport_InitModules(PyInterpreterState *interp);
|
||||||
|
extern PyObject * _PyImport_GetModules(PyInterpreterState *interp);
|
||||||
|
extern void _PyImport_ClearModules(PyInterpreterState *interp);
|
||||||
|
|
||||||
|
extern void _PyImport_ClearModulesByIndex(PyInterpreterState *interp);
|
||||||
|
|
||||||
|
extern int _PyImport_InitDefaultImportFunc(PyInterpreterState *interp);
|
||||||
|
extern int _PyImport_IsDefaultImportFunc(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyObject *func);
|
||||||
|
|
||||||
|
extern PyObject * _PyImport_GetImportlibLoader(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
const char *loader_name);
|
||||||
|
extern PyObject * _PyImport_GetImportlibExternalLoader(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
const char *loader_name);
|
||||||
|
extern PyObject * _PyImport_BlessMyLoader(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyObject *module_globals);
|
||||||
|
extern PyObject * _PyImport_ImportlibModuleRepr(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyObject *module);
|
||||||
|
|
||||||
|
|
||||||
|
extern PyStatus _PyImport_Init(void);
|
||||||
|
extern void _PyImport_Fini(void);
|
||||||
|
extern void _PyImport_Fini2(void);
|
||||||
|
|
||||||
|
extern PyStatus _PyImport_InitCore(
|
||||||
|
PyThreadState *tstate,
|
||||||
|
PyObject *sysmod,
|
||||||
|
int importlib);
|
||||||
|
extern PyStatus _PyImport_InitExternal(PyThreadState *tstate);
|
||||||
|
extern void _PyImport_FiniCore(PyInterpreterState *interp);
|
||||||
|
extern void _PyImport_FiniExternal(PyInterpreterState *interp);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
extern PyStatus _PyImport_ReInitLock(void);
|
extern PyStatus _PyImport_ReInitLock(void);
|
||||||
#endif
|
#endif
|
||||||
extern PyObject* _PyImport_BootstrapImp(PyThreadState *tstate);
|
|
||||||
|
|
||||||
|
extern PyObject* _PyImport_GetBuiltinModuleNames(void);
|
||||||
|
|
||||||
struct _module_alias {
|
struct _module_alias {
|
||||||
const char *name; /* ASCII encoded string */
|
const char *name; /* ASCII encoded string */
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C" {
|
||||||
#include "pycore_function.h" // FUNC_MAX_WATCHERS
|
#include "pycore_function.h" // FUNC_MAX_WATCHERS
|
||||||
#include "pycore_genobject.h" // struct _Py_async_gen_state
|
#include "pycore_genobject.h" // struct _Py_async_gen_state
|
||||||
#include "pycore_gc.h" // struct _gc_runtime_state
|
#include "pycore_gc.h" // struct _gc_runtime_state
|
||||||
|
#include "pycore_import.h" // struct _import_state
|
||||||
#include "pycore_list.h" // struct _Py_list_state
|
#include "pycore_list.h" // struct _Py_list_state
|
||||||
#include "pycore_global_objects.h" // struct _Py_interp_static_objects
|
#include "pycore_global_objects.h" // struct _Py_interp_static_objects
|
||||||
#include "pycore_tuple.h" // struct _Py_tuple_state
|
#include "pycore_tuple.h" // struct _Py_tuple_state
|
||||||
|
@ -92,37 +93,12 @@ struct _is {
|
||||||
struct _ceval_state ceval;
|
struct _ceval_state ceval;
|
||||||
struct _gc_runtime_state gc;
|
struct _gc_runtime_state gc;
|
||||||
|
|
||||||
// sys.modules dictionary
|
struct _import_state imports;
|
||||||
PyObject *modules;
|
|
||||||
/* This is the list of module objects for all legacy (single-phase init)
|
|
||||||
extension modules ever loaded in this process (i.e. imported
|
|
||||||
in this interpreter or in any other). Py_None stands in for
|
|
||||||
modules that haven't actually been imported in this interpreter.
|
|
||||||
|
|
||||||
A module's index (PyModuleDef.m_base.m_index) is used to look up
|
|
||||||
the corresponding module object for this interpreter, if any.
|
|
||||||
(See PyState_FindModule().) When any extension module
|
|
||||||
is initialized during import, its moduledef gets initialized by
|
|
||||||
PyModuleDef_Init(), and the first time that happens for each
|
|
||||||
PyModuleDef, its index gets set to the current value of
|
|
||||||
a global counter (see _PyRuntimeState.imports.last_module_index).
|
|
||||||
The entry for that index in this interpreter remains unset until
|
|
||||||
the module is actually imported here. (Py_None is used as
|
|
||||||
a placeholder.) Note that multi-phase init modules always get
|
|
||||||
an index for which there will never be a module set.
|
|
||||||
|
|
||||||
This is initialized lazily in _PyState_AddModule(), which is also
|
|
||||||
where modules get added. */
|
|
||||||
PyObject *modules_by_index;
|
|
||||||
// Dictionary of the sys module
|
// Dictionary of the sys module
|
||||||
PyObject *sysdict;
|
PyObject *sysdict;
|
||||||
// Dictionary of the builtins module
|
// Dictionary of the builtins module
|
||||||
PyObject *builtins;
|
PyObject *builtins;
|
||||||
// importlib module
|
|
||||||
PyObject *importlib;
|
|
||||||
// override for config->use_frozen_modules (for tests)
|
|
||||||
// (-1: "off", 1: "on", 0: no override)
|
|
||||||
int override_frozen_modules;
|
|
||||||
|
|
||||||
PyObject *codec_search_path;
|
PyObject *codec_search_path;
|
||||||
PyObject *codec_search_cache;
|
PyObject *codec_search_cache;
|
||||||
|
@ -130,15 +106,11 @@ struct _is {
|
||||||
int codecs_initialized;
|
int codecs_initialized;
|
||||||
|
|
||||||
PyConfig config;
|
PyConfig config;
|
||||||
#ifdef HAVE_DLOPEN
|
|
||||||
int dlopenflags;
|
|
||||||
#endif
|
|
||||||
unsigned long feature_flags;
|
unsigned long feature_flags;
|
||||||
|
|
||||||
PyObject *dict; /* Stores per-interpreter state */
|
PyObject *dict; /* Stores per-interpreter state */
|
||||||
|
|
||||||
PyObject *builtins_copy;
|
PyObject *builtins_copy;
|
||||||
PyObject *import_func;
|
|
||||||
// Initialized to _PyEval_EvalFrameDefault().
|
// Initialized to _PyEval_EvalFrameDefault().
|
||||||
_PyFrameEvalFunction eval_frame;
|
_PyFrameEvalFunction eval_frame;
|
||||||
|
|
||||||
|
@ -205,7 +177,6 @@ struct _is {
|
||||||
|
|
||||||
/* other API */
|
/* other API */
|
||||||
|
|
||||||
extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
|
|
||||||
extern void _PyInterpreterState_Clear(PyThreadState *tstate);
|
extern void _PyInterpreterState_Clear(PyThreadState *tstate);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
|
||||||
/* Various one-time initializers */
|
/* Various one-time initializers */
|
||||||
|
|
||||||
extern void _Py_InitVersion(void);
|
extern void _Py_InitVersion(void);
|
||||||
extern PyStatus _PyImport_Init(void);
|
|
||||||
extern PyStatus _PyFaulthandler_Init(int enable);
|
extern PyStatus _PyFaulthandler_Init(int enable);
|
||||||
extern int _PyTraceMalloc_Init(int enable);
|
extern int _PyTraceMalloc_Init(int enable);
|
||||||
extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp);
|
extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp);
|
||||||
|
@ -45,7 +44,6 @@ extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
|
||||||
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
|
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
|
||||||
|
|
||||||
extern PyStatus _PyTime_Init(void);
|
extern PyStatus _PyTime_Init(void);
|
||||||
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
|
|
||||||
extern PyStatus _PyGC_Init(PyInterpreterState *interp);
|
extern PyStatus _PyGC_Init(PyInterpreterState *interp);
|
||||||
extern PyStatus _PyAtExit_Init(PyInterpreterState *interp);
|
extern PyStatus _PyAtExit_Init(PyInterpreterState *interp);
|
||||||
extern int _Py_Deepfreeze_Init(void);
|
extern int _Py_Deepfreeze_Init(void);
|
||||||
|
@ -55,8 +53,6 @@ extern int _Py_Deepfreeze_Init(void);
|
||||||
extern int _PySignal_Init(int install_signal_handlers);
|
extern int _PySignal_Init(int install_signal_handlers);
|
||||||
extern void _PySignal_Fini(void);
|
extern void _PySignal_Fini(void);
|
||||||
|
|
||||||
extern void _PyImport_Fini(void);
|
|
||||||
extern void _PyImport_Fini2(void);
|
|
||||||
extern void _PyGC_Fini(PyInterpreterState *interp);
|
extern void _PyGC_Fini(PyInterpreterState *interp);
|
||||||
extern void _Py_HashRandomization_Fini(void);
|
extern void _Py_HashRandomization_Fini(void);
|
||||||
extern void _PyFaulthandler_Fini(void);
|
extern void _PyFaulthandler_Fini(void);
|
||||||
|
|
|
@ -152,12 +152,6 @@ extern void _PySignal_AfterFork(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyState_AddModule(
|
|
||||||
PyThreadState *tstate,
|
|
||||||
PyObject* module,
|
|
||||||
PyModuleDef* def);
|
|
||||||
|
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyOS_InterruptOccurred(PyThreadState *tstate);
|
PyAPI_FUNC(int) _PyOS_InterruptOccurred(PyThreadState *tstate);
|
||||||
|
|
||||||
#define HEAD_LOCK(runtime) \
|
#define HEAD_LOCK(runtime) \
|
||||||
|
|
|
@ -97,23 +97,10 @@ extern "C" {
|
||||||
._main_interpreter = _PyInterpreterState_INIT, \
|
._main_interpreter = _PyInterpreterState_INIT, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
|
||||||
# include <dlfcn.h>
|
|
||||||
# if HAVE_DECL_RTLD_NOW
|
|
||||||
# define _Py_DLOPEN_FLAGS RTLD_NOW
|
|
||||||
# else
|
|
||||||
# define _Py_DLOPEN_FLAGS RTLD_LAZY
|
|
||||||
# endif
|
|
||||||
# define DLOPENFLAGS_INIT .dlopenflags = _Py_DLOPEN_FLAGS,
|
|
||||||
#else
|
|
||||||
# define _Py_DLOPEN_FLAGS 0
|
|
||||||
# define DLOPENFLAGS_INIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _PyInterpreterState_INIT \
|
#define _PyInterpreterState_INIT \
|
||||||
{ \
|
{ \
|
||||||
.id_refcount = -1, \
|
.id_refcount = -1, \
|
||||||
DLOPENFLAGS_INIT \
|
.imports = IMPORTS_INIT, \
|
||||||
.ceval = { \
|
.ceval = { \
|
||||||
.recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \
|
.recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \
|
||||||
}, \
|
}, \
|
||||||
|
|
|
@ -20,6 +20,9 @@ extern void _PySys_ClearAuditHooks(PyThreadState *tstate);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PySys_SetAttr(PyObject *, PyObject *);
|
PyAPI_FUNC(int) _PySys_SetAttr(PyObject *, PyObject *);
|
||||||
|
|
||||||
|
extern int _PySys_ClearAttrString(PyInterpreterState *interp,
|
||||||
|
const char *name, int verbose);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -387,7 +387,7 @@ class ImportTests(unittest.TestCase):
|
||||||
check_basic_reloaded(mod, lookedup, initialized, init_count,
|
check_basic_reloaded(mod, lookedup, initialized, init_count,
|
||||||
before, reloaded)
|
before, reloaded)
|
||||||
|
|
||||||
# Currently _PyState_AddModule() always replaces the cached module.
|
# Currently PyState_AddModule() always replaces the cached module.
|
||||||
self.assertIs(basic.look_up_self(), mod)
|
self.assertIs(basic.look_up_self(), mod)
|
||||||
self.assertEqual(basic.initialized_count(), expected_init_count)
|
self.assertEqual(basic.initialized_count(), expected_init_count)
|
||||||
|
|
||||||
|
|
|
@ -864,7 +864,6 @@ SYMBOL_NAMES = (
|
||||||
"_PyObject_GC_Resize",
|
"_PyObject_GC_Resize",
|
||||||
"_PyObject_New",
|
"_PyObject_New",
|
||||||
"_PyObject_NewVar",
|
"_PyObject_NewVar",
|
||||||
"_PyState_AddModule",
|
|
||||||
"_PyThreadState_Init",
|
"_PyThreadState_Init",
|
||||||
"_PyThreadState_Prealloc",
|
"_PyThreadState_Prealloc",
|
||||||
"_PyWeakref_CallableProxyType",
|
"_PyWeakref_CallableProxyType",
|
||||||
|
|
|
@ -1684,9 +1684,6 @@
|
||||||
[function._PyObject_NewVar]
|
[function._PyObject_NewVar]
|
||||||
added = '3.2'
|
added = '3.2'
|
||||||
abi_only = true
|
abi_only = true
|
||||||
[function._PyState_AddModule]
|
|
||||||
added = '3.2'
|
|
||||||
abi_only = true
|
|
||||||
[function._PyThreadState_Init]
|
[function._PyThreadState_Init]
|
||||||
added = '3.2'
|
added = '3.2'
|
||||||
abi_only = true
|
abi_only = true
|
||||||
|
|
|
@ -42,10 +42,9 @@ PyModuleDef_Init(PyModuleDef* def)
|
||||||
{
|
{
|
||||||
assert(PyModuleDef_Type.tp_flags & Py_TPFLAGS_READY);
|
assert(PyModuleDef_Type.tp_flags & Py_TPFLAGS_READY);
|
||||||
if (def->m_base.m_index == 0) {
|
if (def->m_base.m_index == 0) {
|
||||||
_PyRuntime.imports.last_module_index++;
|
|
||||||
Py_SET_REFCNT(def, 1);
|
Py_SET_REFCNT(def, 1);
|
||||||
Py_SET_TYPE(def, &PyModuleDef_Type);
|
Py_SET_TYPE(def, &PyModuleDef_Type);
|
||||||
def->m_base.m_index = _PyRuntime.imports.last_module_index;
|
def->m_base.m_index = _PyImport_GetNextModuleIndex();
|
||||||
}
|
}
|
||||||
return (PyObject*)def;
|
return (PyObject*)def;
|
||||||
}
|
}
|
||||||
|
@ -209,24 +208,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
|
||||||
"module %s: PyModule_Create is incompatible with m_slots", name);
|
"module %s: PyModule_Create is incompatible with m_slots", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Make sure name is fully qualified.
|
name = _PyImport_ResolveNameWithPackageContext(name);
|
||||||
|
|
||||||
This is a bit of a hack: when the shared library is loaded,
|
|
||||||
the module name is "package.module", but the module calls
|
|
||||||
PyModule_Create*() with just "module" for the name. The shared
|
|
||||||
library loader squirrels away the true name of the module in
|
|
||||||
_Py_PackageContext, and PyModule_Create*() will substitute this
|
|
||||||
(if the name actually matches).
|
|
||||||
*/
|
|
||||||
#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
|
|
||||||
if (_Py_PackageContext != NULL) {
|
|
||||||
const char *p = strrchr(_Py_PackageContext, '.');
|
|
||||||
if (p != NULL && strcmp(module->m_name, p+1) == 0) {
|
|
||||||
name = _Py_PackageContext;
|
|
||||||
_Py_PackageContext = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#undef _Py_PackageContext
|
|
||||||
if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
|
if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -710,8 +692,7 @@ static PyObject *
|
||||||
module_repr(PyModuleObject *m)
|
module_repr(PyModuleObject *m)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
return _PyImport_ImportlibModuleRepr(interp, (PyObject *)m);
|
||||||
return PyObject_CallMethod(interp->importlib, "_module_repr", "O", m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the "_initializing" attribute of the module spec is set to true.
|
/* Check if the "_initializing" attribute of the module spec is set to true.
|
||||||
|
|
|
@ -34,7 +34,6 @@ EXPORT_FUNC(_PyObject_GC_NewVar)
|
||||||
EXPORT_FUNC(_PyObject_GC_Resize)
|
EXPORT_FUNC(_PyObject_GC_Resize)
|
||||||
EXPORT_FUNC(_PyObject_New)
|
EXPORT_FUNC(_PyObject_New)
|
||||||
EXPORT_FUNC(_PyObject_NewVar)
|
EXPORT_FUNC(_PyObject_NewVar)
|
||||||
EXPORT_FUNC(_PyState_AddModule)
|
|
||||||
EXPORT_FUNC(_PyThreadState_Init)
|
EXPORT_FUNC(_PyThreadState_Init)
|
||||||
EXPORT_FUNC(_PyThreadState_Prealloc)
|
EXPORT_FUNC(_PyThreadState_Prealloc)
|
||||||
EXPORT_FUNC(Py_AddPendingCall)
|
EXPORT_FUNC(Py_AddPendingCall)
|
||||||
|
|
|
@ -214,7 +214,7 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
|
||||||
gone, then we can't even use PyImport_GetModule without triggering
|
gone, then we can't even use PyImport_GetModule without triggering
|
||||||
an interpreter abort.
|
an interpreter abort.
|
||||||
*/
|
*/
|
||||||
if (!interp->modules) {
|
if (!_PyImport_GetModules(interp)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
warnings_module = PyImport_GetModule(&_Py_ID(warnings));
|
warnings_module = PyImport_GetModule(&_Py_ID(warnings));
|
||||||
|
@ -1050,7 +1050,6 @@ warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
|
get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
|
||||||
{
|
{
|
||||||
PyObject *external;
|
|
||||||
PyObject *loader;
|
PyObject *loader;
|
||||||
PyObject *module_name;
|
PyObject *module_name;
|
||||||
PyObject *get_source;
|
PyObject *get_source;
|
||||||
|
@ -1059,13 +1058,7 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno
|
||||||
PyObject *source_line;
|
PyObject *source_line;
|
||||||
|
|
||||||
/* stolen from import.c */
|
/* stolen from import.c */
|
||||||
external = PyObject_GetAttrString(interp->importlib, "_bootstrap_external");
|
loader = _PyImport_BlessMyLoader(interp, module_globals);
|
||||||
if (external == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
loader = PyObject_CallMethod(external, "_bless_my_loader", "O", module_globals, NULL);
|
|
||||||
Py_DECREF(external);
|
|
||||||
if (loader == NULL) {
|
if (loader == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2688,7 +2688,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
}
|
}
|
||||||
PyObject *locals = frame->f_locals;
|
PyObject *locals = frame->f_locals;
|
||||||
/* Fast path for not overloaded __import__. */
|
/* Fast path for not overloaded __import__. */
|
||||||
if (import_func == tstate->interp->import_func) {
|
if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) {
|
||||||
int ilevel = _PyLong_AsInt(level);
|
int ilevel = _PyLong_AsInt(level);
|
||||||
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -75,7 +75,7 @@ _PyImport_FindSharedFuncptr(const char *prefix,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dlopenflags = _PyInterpreterState_GET()->dlopenflags;
|
dlopenflags = _PyImport_GetDLOpenFlags(_PyInterpreterState_GET());
|
||||||
|
|
||||||
handle = dlopen(pathname, dlopenflags);
|
handle = dlopen(pathname, dlopenflags);
|
||||||
|
|
||||||
|
|
2012
Python/import.c
2012
Python/import.c
File diff suppressed because it is too large
Load Diff
|
@ -99,7 +99,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
|
||||||
#endif
|
#endif
|
||||||
PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;
|
PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;
|
||||||
const char *name_buf, *hook_prefix;
|
const char *name_buf, *hook_prefix;
|
||||||
const char *oldcontext;
|
const char *oldcontext, *newcontext;
|
||||||
dl_funcptr exportfunc;
|
dl_funcptr exportfunc;
|
||||||
PyModuleDef *def;
|
PyModuleDef *def;
|
||||||
PyModInitFunction p0;
|
PyModInitFunction p0;
|
||||||
|
@ -113,6 +113,10 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
|
||||||
"spec.name must be a string");
|
"spec.name must be a string");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
newcontext = PyUnicode_AsUTF8(name_unicode);
|
||||||
|
if (newcontext == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
name = get_encoded_name(name_unicode, &hook_prefix);
|
name = get_encoded_name(name_unicode, &hook_prefix);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
|
@ -160,16 +164,9 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
|
||||||
p0 = (PyModInitFunction)exportfunc;
|
p0 = (PyModInitFunction)exportfunc;
|
||||||
|
|
||||||
/* Package context is needed for single-phase init */
|
/* Package context is needed for single-phase init */
|
||||||
#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
|
oldcontext = _PyImport_SwapPackageContext(newcontext);
|
||||||
oldcontext = _Py_PackageContext;
|
|
||||||
_Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
|
|
||||||
if (_Py_PackageContext == NULL) {
|
|
||||||
_Py_PackageContext = oldcontext;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
m = _PyImport_InitFunc_TrampolineCall(p0);
|
m = _PyImport_InitFunc_TrampolineCall(p0);
|
||||||
_Py_PackageContext = oldcontext;
|
_PyImport_SwapPackageContext(oldcontext);
|
||||||
#undef _Py_PackageContext
|
|
||||||
|
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
if (!PyErr_Occurred()) {
|
if (!PyErr_Occurred()) {
|
||||||
|
|
|
@ -156,79 +156,6 @@ Py_IsInitialized(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Global initializations. Can be undone by Py_FinalizeEx(). Don't
|
|
||||||
call this twice without an intervening Py_FinalizeEx() call. When
|
|
||||||
initializations fail, a fatal error is issued and the function does
|
|
||||||
not return. On return, the first thread and interpreter state have
|
|
||||||
been created.
|
|
||||||
|
|
||||||
Locking: you must hold the interpreter lock while calling this.
|
|
||||||
(If the lock has not yet been initialized, that's equivalent to
|
|
||||||
having the lock, but you cannot use multiple threads.)
|
|
||||||
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
init_importlib(PyThreadState *tstate, PyObject *sysmod)
|
|
||||||
{
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
|
||||||
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
|
||||||
int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
|
|
||||||
|
|
||||||
// Import _importlib through its frozen version, _frozen_importlib.
|
|
||||||
if (verbose) {
|
|
||||||
PySys_FormatStderr("import _frozen_importlib # frozen\n");
|
|
||||||
}
|
|
||||||
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
|
|
||||||
if (importlib == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
interp->importlib = Py_NewRef(importlib);
|
|
||||||
|
|
||||||
// Import the _imp module
|
|
||||||
if (verbose) {
|
|
||||||
PySys_FormatStderr("import _imp # builtin\n");
|
|
||||||
}
|
|
||||||
PyObject *imp_mod = _PyImport_BootstrapImp(tstate);
|
|
||||||
if (imp_mod == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (_PyImport_SetModuleString("_imp", imp_mod) < 0) {
|
|
||||||
Py_DECREF(imp_mod);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install importlib as the implementation of import
|
|
||||||
PyObject *value = PyObject_CallMethod(importlib, "_install",
|
|
||||||
"OO", sysmod, imp_mod);
|
|
||||||
Py_DECREF(imp_mod);
|
|
||||||
if (value == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(value);
|
|
||||||
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PyStatus
|
|
||||||
init_importlib_external(PyThreadState *tstate)
|
|
||||||
{
|
|
||||||
PyObject *value;
|
|
||||||
value = PyObject_CallMethod(tstate->interp->importlib,
|
|
||||||
"_install_external_importers", "");
|
|
||||||
if (value == NULL) {
|
|
||||||
_PyErr_Print(tstate);
|
|
||||||
return _PyStatus_ERR("external importer setup failed");
|
|
||||||
}
|
|
||||||
Py_DECREF(value);
|
|
||||||
return _PyImportZip_Init(tstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper functions to better handle the legacy C locale
|
/* Helper functions to better handle the legacy C locale
|
||||||
*
|
*
|
||||||
* The legacy C locale assumes ASCII as the default text encoding, which
|
* The legacy C locale assumes ASCII as the default text encoding, which
|
||||||
|
@ -814,7 +741,8 @@ pycore_init_builtins(PyThreadState *tstate)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyImport_FixupBuiltin(bimod, "builtins", interp->modules) < 0) {
|
PyObject *modules = _PyImport_GetModules(interp);
|
||||||
|
if (_PyImport_FixupBuiltin(bimod, "builtins", modules) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,13 +778,9 @@ pycore_init_builtins(PyThreadState *tstate)
|
||||||
}
|
}
|
||||||
Py_DECREF(bimod);
|
Py_DECREF(bimod);
|
||||||
|
|
||||||
// Get the __import__ function
|
if (_PyImport_InitDefaultImportFunc(interp) < 0) {
|
||||||
PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,
|
|
||||||
"__import__");
|
|
||||||
if (import_func == NULL) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
interp->import_func = Py_NewRef(import_func);
|
|
||||||
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
return _PyStatus_OK();
|
return _PyStatus_OK();
|
||||||
|
@ -918,11 +842,10 @@ pycore_interp_init(PyThreadState *tstate)
|
||||||
}
|
}
|
||||||
|
|
||||||
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
|
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
|
||||||
if (config->_install_importlib) {
|
|
||||||
/* This call sets up builtin and frozen import support */
|
status = _PyImport_InitCore(tstate, sysmod, config->_install_importlib);
|
||||||
if (init_importlib(tstate, sysmod) < 0) {
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
return _PyStatus_ERR("failed to initialize importlib");
|
goto done;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -1172,7 +1095,7 @@ init_interp_main(PyThreadState *tstate)
|
||||||
return _PyStatus_ERR("failed to update the Python config");
|
return _PyStatus_ERR("failed to update the Python config");
|
||||||
}
|
}
|
||||||
|
|
||||||
status = init_importlib_external(tstate);
|
status = _PyImport_InitExternal(tstate);
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1379,8 +1302,11 @@ finalize_modules_delete_special(PyThreadState *tstate, int verbose)
|
||||||
static const char * const sys_deletes[] = {
|
static const char * const sys_deletes[] = {
|
||||||
"path", "argv", "ps1", "ps2",
|
"path", "argv", "ps1", "ps2",
|
||||||
"last_type", "last_value", "last_traceback",
|
"last_type", "last_value", "last_traceback",
|
||||||
"path_hooks", "path_importer_cache", "meta_path",
|
|
||||||
"__interactivehook__",
|
"__interactivehook__",
|
||||||
|
// path_hooks and path_importer_cache are cleared
|
||||||
|
// by _PyImport_FiniExternal().
|
||||||
|
// XXX Clear meta_path in _PyImport_FiniCore().
|
||||||
|
"meta_path",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1401,10 +1327,7 @@ finalize_modules_delete_special(PyThreadState *tstate, int verbose)
|
||||||
|
|
||||||
const char * const *p;
|
const char * const *p;
|
||||||
for (p = sys_deletes; *p != NULL; p++) {
|
for (p = sys_deletes; *p != NULL; p++) {
|
||||||
if (verbose) {
|
if (_PySys_ClearAttrString(interp, *p, verbose) < 0) {
|
||||||
PySys_WriteStderr("# clear sys.%s\n", *p);
|
|
||||||
}
|
|
||||||
if (PyDict_SetItemString(interp->sysdict, *p, Py_None) < 0) {
|
|
||||||
PyErr_WriteUnraisable(NULL);
|
PyErr_WriteUnraisable(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1576,11 +1499,12 @@ finalize_clear_sys_builtins_dict(PyInterpreterState *interp, int verbose)
|
||||||
|
|
||||||
|
|
||||||
/* Clear modules, as good as we can */
|
/* Clear modules, as good as we can */
|
||||||
|
// XXX Move most of this to import.c.
|
||||||
static void
|
static void
|
||||||
finalize_modules(PyThreadState *tstate)
|
finalize_modules(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
PyObject *modules = interp->modules;
|
PyObject *modules = _PyImport_GetModules(interp);
|
||||||
if (modules == NULL) {
|
if (modules == NULL) {
|
||||||
// Already done
|
// Already done
|
||||||
return;
|
return;
|
||||||
|
@ -1645,12 +1569,12 @@ finalize_modules(PyThreadState *tstate)
|
||||||
// clear PyInterpreterState.modules_by_index and
|
// clear PyInterpreterState.modules_by_index and
|
||||||
// clear PyModuleDef.m_base.m_copy (of extensions not using the multi-phase
|
// clear PyModuleDef.m_base.m_copy (of extensions not using the multi-phase
|
||||||
// initialization API)
|
// initialization API)
|
||||||
_PyInterpreterState_ClearModules(interp);
|
_PyImport_ClearModulesByIndex(interp);
|
||||||
|
|
||||||
// Clear and delete the modules directory. Actual modules will
|
// Clear and delete the modules directory. Actual modules will
|
||||||
// still be there only if imported during the execution of some
|
// still be there only if imported during the execution of some
|
||||||
// destructor.
|
// destructor.
|
||||||
Py_SETREF(interp->modules, NULL);
|
_PyImport_ClearModules(interp);
|
||||||
|
|
||||||
// Collect garbage once more
|
// Collect garbage once more
|
||||||
_PyGC_CollectNoFail(tstate);
|
_PyGC_CollectNoFail(tstate);
|
||||||
|
@ -1861,6 +1785,8 @@ Py_FinalizeEx(void)
|
||||||
runtime->initialized = 0;
|
runtime->initialized = 0;
|
||||||
runtime->core_initialized = 0;
|
runtime->core_initialized = 0;
|
||||||
|
|
||||||
|
// XXX Call something like _PyImport_Disable() here?
|
||||||
|
|
||||||
/* Destroy the state of all threads of the interpreter, except of the
|
/* Destroy the state of all threads of the interpreter, except of the
|
||||||
current thread. In practice, only daemon threads should still be alive,
|
current thread. In practice, only daemon threads should still be alive,
|
||||||
except if wait_for_thread_shutdown() has been cancelled by CTRL+C.
|
except if wait_for_thread_shutdown() has been cancelled by CTRL+C.
|
||||||
|
@ -1910,6 +1836,7 @@ Py_FinalizeEx(void)
|
||||||
PyGC_Collect();
|
PyGC_Collect();
|
||||||
|
|
||||||
/* Destroy all modules */
|
/* Destroy all modules */
|
||||||
|
_PyImport_FiniExternal(tstate->interp);
|
||||||
finalize_modules(tstate);
|
finalize_modules(tstate);
|
||||||
|
|
||||||
/* Print debug stats if any */
|
/* Print debug stats if any */
|
||||||
|
@ -1943,7 +1870,9 @@ Py_FinalizeEx(void)
|
||||||
so it is possible to use tracemalloc in objects destructor. */
|
so it is possible to use tracemalloc in objects destructor. */
|
||||||
_PyTraceMalloc_Fini();
|
_PyTraceMalloc_Fini();
|
||||||
|
|
||||||
/* Destroy the database used by _PyImport_{Fixup,Find}Extension */
|
/* Finalize any remaining import state */
|
||||||
|
// XXX Move these up to where finalize_modules() is currently.
|
||||||
|
_PyImport_FiniCore(tstate->interp);
|
||||||
_PyImport_Fini();
|
_PyImport_Fini();
|
||||||
|
|
||||||
/* unload faulthandler module */
|
/* unload faulthandler module */
|
||||||
|
@ -2183,7 +2112,11 @@ Py_EndInterpreter(PyThreadState *tstate)
|
||||||
Py_FatalError("not the last thread");
|
Py_FatalError("not the last thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Call something like _PyImport_Disable() here?
|
||||||
|
|
||||||
|
_PyImport_FiniExternal(tstate->interp);
|
||||||
finalize_modules(tstate);
|
finalize_modules(tstate);
|
||||||
|
_PyImport_FiniCore(tstate->interp);
|
||||||
|
|
||||||
finalize_interp_clear(tstate);
|
finalize_interp_clear(tstate);
|
||||||
finalize_interp_delete(tstate->interp);
|
finalize_interp_delete(tstate->interp);
|
||||||
|
@ -2232,7 +2165,7 @@ add_main_module(PyInterpreterState *interp)
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
return _PyStatus_ERR("Failed to test __main__.__loader__");
|
return _PyStatus_ERR("Failed to test __main__.__loader__");
|
||||||
}
|
}
|
||||||
PyObject *loader = PyObject_GetAttrString(interp->importlib,
|
PyObject *loader = _PyImport_GetImportlibLoader(interp,
|
||||||
"BuiltinImporter");
|
"BuiltinImporter");
|
||||||
if (loader == NULL) {
|
if (loader == NULL) {
|
||||||
return _PyStatus_ERR("Failed to retrieve BuiltinImporter");
|
return _PyStatus_ERR("Failed to retrieve BuiltinImporter");
|
||||||
|
@ -2739,7 +2672,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
|
||||||
if (interp == NULL) {
|
if (interp == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyObject *modules = interp->modules;
|
PyObject *modules = _PyImport_GetModules(interp);
|
||||||
if (modules == NULL || !PyDict_Check(modules)) {
|
if (modules == NULL || !PyDict_Check(modules)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
151
Python/pystate.c
151
Python/pystate.c
|
@ -772,11 +772,13 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
|
||||||
Py_CLEAR(interp->codec_search_path);
|
Py_CLEAR(interp->codec_search_path);
|
||||||
Py_CLEAR(interp->codec_search_cache);
|
Py_CLEAR(interp->codec_search_cache);
|
||||||
Py_CLEAR(interp->codec_error_registry);
|
Py_CLEAR(interp->codec_error_registry);
|
||||||
Py_CLEAR(interp->modules);
|
|
||||||
Py_CLEAR(interp->modules_by_index);
|
assert(interp->imports.modules == NULL);
|
||||||
|
assert(interp->imports.modules_by_index == NULL);
|
||||||
|
assert(interp->imports.importlib == NULL);
|
||||||
|
assert(interp->imports.import_func == NULL);
|
||||||
|
|
||||||
Py_CLEAR(interp->builtins_copy);
|
Py_CLEAR(interp->builtins_copy);
|
||||||
Py_CLEAR(interp->importlib);
|
|
||||||
Py_CLEAR(interp->import_func);
|
|
||||||
Py_CLEAR(interp->dict);
|
Py_CLEAR(interp->dict);
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
Py_CLEAR(interp->before_forkers);
|
Py_CLEAR(interp->before_forkers);
|
||||||
|
@ -836,6 +838,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
||||||
// garbage. It can be different than the current Python thread state
|
// garbage. It can be different than the current Python thread state
|
||||||
// of 'interp'.
|
// of 'interp'.
|
||||||
PyThreadState *current_tstate = current_fast_get(interp->runtime);
|
PyThreadState *current_tstate = current_fast_get(interp->runtime);
|
||||||
|
_PyImport_ClearCore(interp);
|
||||||
interpreter_clear(interp, current_tstate);
|
interpreter_clear(interp, current_tstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,6 +846,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
||||||
void
|
void
|
||||||
_PyInterpreterState_Clear(PyThreadState *tstate)
|
_PyInterpreterState_Clear(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
|
_PyImport_ClearCore(tstate->interp);
|
||||||
interpreter_clear(tstate->interp, tstate);
|
interpreter_clear(tstate->interp, tstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,36 +949,6 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Used by finalize_modules()
|
|
||||||
void
|
|
||||||
_PyInterpreterState_ClearModules(PyInterpreterState *interp)
|
|
||||||
{
|
|
||||||
if (!interp->modules_by_index) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_ssize_t i;
|
|
||||||
for (i = 0; i < PyList_GET_SIZE(interp->modules_by_index); i++) {
|
|
||||||
PyObject *m = PyList_GET_ITEM(interp->modules_by_index, i);
|
|
||||||
if (PyModule_Check(m)) {
|
|
||||||
/* cleanup the saved copy of module dicts */
|
|
||||||
PyModuleDef *md = PyModule_GetDef(m);
|
|
||||||
if (md) {
|
|
||||||
Py_CLEAR(md->m_base.m_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setting modules_by_index to NULL could be dangerous, so we
|
|
||||||
clear the list instead. */
|
|
||||||
if (PyList_SetSlice(interp->modules_by_index,
|
|
||||||
0, PyList_GET_SIZE(interp->modules_by_index),
|
|
||||||
NULL)) {
|
|
||||||
PyErr_WriteUnraisable(interp->modules_by_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// accessors
|
// accessors
|
||||||
//----------
|
//----------
|
||||||
|
@ -1058,11 +1032,12 @@ _PyInterpreterState_RequireIDRef(PyInterpreterState *interp, int required)
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyInterpreterState_GetMainModule(PyInterpreterState *interp)
|
_PyInterpreterState_GetMainModule(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
if (interp->modules == NULL) {
|
PyObject *modules = _PyImport_GetModules(interp);
|
||||||
|
if (modules == NULL) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "interpreter not initialized");
|
PyErr_SetString(PyExc_RuntimeError, "interpreter not initialized");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return PyMapping_GetItemString(interp->modules, "__main__");
|
return PyMapping_GetItemString(modules, "__main__");
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -1922,110 +1897,6 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************/
|
|
||||||
/* module state */
|
|
||||||
/****************/
|
|
||||||
|
|
||||||
PyObject*
|
|
||||||
PyState_FindModule(PyModuleDef* module)
|
|
||||||
{
|
|
||||||
Py_ssize_t index = module->m_base.m_index;
|
|
||||||
PyInterpreterState *state = _PyInterpreterState_GET();
|
|
||||||
PyObject *res;
|
|
||||||
if (module->m_slots) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (index == 0)
|
|
||||||
return NULL;
|
|
||||||
if (state->modules_by_index == NULL)
|
|
||||||
return NULL;
|
|
||||||
if (index >= PyList_GET_SIZE(state->modules_by_index))
|
|
||||||
return NULL;
|
|
||||||
res = PyList_GET_ITEM(state->modules_by_index, index);
|
|
||||||
return res==Py_None ? NULL : res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_PyState_AddModule(PyThreadState *tstate, PyObject* module, PyModuleDef* def)
|
|
||||||
{
|
|
||||||
if (!def) {
|
|
||||||
assert(_PyErr_Occurred(tstate));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (def->m_slots) {
|
|
||||||
_PyErr_SetString(tstate,
|
|
||||||
PyExc_SystemError,
|
|
||||||
"PyState_AddModule called on module with slots");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
|
||||||
if (!interp->modules_by_index) {
|
|
||||||
interp->modules_by_index = PyList_New(0);
|
|
||||||
if (!interp->modules_by_index) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (PyList_GET_SIZE(interp->modules_by_index) <= def->m_base.m_index) {
|
|
||||||
if (PyList_Append(interp->modules_by_index, Py_None) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PyList_SetItem(interp->modules_by_index,
|
|
||||||
def->m_base.m_index, Py_NewRef(module));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PyState_AddModule(PyObject* module, PyModuleDef* def)
|
|
||||||
{
|
|
||||||
if (!def) {
|
|
||||||
Py_FatalError("module definition is NULL");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyThreadState *tstate = current_fast_get(&_PyRuntime);
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
|
||||||
Py_ssize_t index = def->m_base.m_index;
|
|
||||||
if (interp->modules_by_index &&
|
|
||||||
index < PyList_GET_SIZE(interp->modules_by_index) &&
|
|
||||||
module == PyList_GET_ITEM(interp->modules_by_index, index))
|
|
||||||
{
|
|
||||||
_Py_FatalErrorFormat(__func__, "module %p already added", module);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return _PyState_AddModule(tstate, module, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PyState_RemoveModule(PyModuleDef* def)
|
|
||||||
{
|
|
||||||
PyThreadState *tstate = current_fast_get(&_PyRuntime);
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
|
||||||
|
|
||||||
if (def->m_slots) {
|
|
||||||
_PyErr_SetString(tstate,
|
|
||||||
PyExc_SystemError,
|
|
||||||
"PyState_RemoveModule called on module with slots");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_ssize_t index = def->m_base.m_index;
|
|
||||||
if (index == 0) {
|
|
||||||
Py_FatalError("invalid module index");
|
|
||||||
}
|
|
||||||
if (interp->modules_by_index == NULL) {
|
|
||||||
Py_FatalError("Interpreters module-list not accessible.");
|
|
||||||
}
|
|
||||||
if (index > PyList_GET_SIZE(interp->modules_by_index)) {
|
|
||||||
Py_FatalError("Module index out of bounds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return PyList_SetItem(interp->modules_by_index, index, Py_NewRef(Py_None));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************/
|
/***********************************/
|
||||||
/* Python "auto thread state" API. */
|
/* Python "auto thread state" API. */
|
||||||
/***********************************/
|
/***********************************/
|
||||||
|
|
|
@ -350,14 +350,8 @@ static int
|
||||||
set_main_loader(PyObject *d, PyObject *filename, const char *loader_name)
|
set_main_loader(PyObject *d, PyObject *filename, const char *loader_name)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
PyObject *bootstrap = PyObject_GetAttrString(interp->importlib,
|
PyObject *loader_type = _PyImport_GetImportlibExternalLoader(interp,
|
||||||
"_bootstrap_external");
|
loader_name);
|
||||||
if (bootstrap == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *loader_type = PyObject_GetAttrString(bootstrap, loader_name);
|
|
||||||
Py_DECREF(bootstrap);
|
|
||||||
if (loader_type == NULL) {
|
if (loader_type == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,20 @@ PySys_SetObject(const char *name, PyObject *v)
|
||||||
return sys_set_object_str(interp, name, v);
|
return sys_set_object_str(interp, name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PySys_ClearAttrString(PyInterpreterState *interp,
|
||||||
|
const char *name, int verbose)
|
||||||
|
{
|
||||||
|
if (verbose) {
|
||||||
|
PySys_WriteStderr("# clear sys.%s\n", name);
|
||||||
|
}
|
||||||
|
/* To play it safe, we set the attr to None instead of deleting it. */
|
||||||
|
if (PyDict_SetItemString(interp->sysdict, name, Py_None) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
should_audit(PyInterpreterState *interp)
|
should_audit(PyInterpreterState *interp)
|
||||||
|
@ -1650,7 +1664,7 @@ sys_setdlopenflags_impl(PyObject *module, int new_val)
|
||||||
/*[clinic end generated code: output=ec918b7fe0a37281 input=4c838211e857a77f]*/
|
/*[clinic end generated code: output=ec918b7fe0a37281 input=4c838211e857a77f]*/
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
interp->dlopenflags = new_val;
|
_PyImport_SetDLOpenFlags(interp, new_val);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1668,7 +1682,8 @@ sys_getdlopenflags_impl(PyObject *module)
|
||||||
/*[clinic end generated code: output=e92cd1bc5005da6e input=dc4ea0899c53b4b6]*/
|
/*[clinic end generated code: output=e92cd1bc5005da6e input=dc4ea0899c53b4b6]*/
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
return PyLong_FromLong(interp->dlopenflags);
|
return PyLong_FromLong(
|
||||||
|
_PyImport_GetDLOpenFlags(interp));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_DLOPEN */
|
#endif /* HAVE_DLOPEN */
|
||||||
|
@ -2279,22 +2294,10 @@ static PyMethodDef sys_methods[] = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
list_builtin_module_names(void)
|
list_builtin_module_names(void)
|
||||||
{
|
{
|
||||||
PyObject *list = PyList_New(0);
|
PyObject *list = _PyImport_GetBuiltinModuleNames();
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct _inittab *inittab = _PyRuntime.imports.inittab;
|
|
||||||
for (Py_ssize_t i = 0; inittab[i].name != NULL; i++) {
|
|
||||||
PyObject *name = PyUnicode_FromString(inittab[i].name);
|
|
||||||
if (name == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (PyList_Append(list, name) < 0) {
|
|
||||||
Py_DECREF(name);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Py_DECREF(name);
|
|
||||||
}
|
|
||||||
if (PyList_Sort(list) != 0) {
|
if (PyList_Sort(list) != 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -3411,11 +3414,10 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
|
||||||
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
|
|
||||||
PyObject *modules = PyDict_New();
|
PyObject *modules = _PyImport_InitModules(interp);
|
||||||
if (modules == NULL) {
|
if (modules == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
interp->modules = modules;
|
|
||||||
|
|
||||||
PyObject *sysmod = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);
|
PyObject *sysmod = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);
|
||||||
if (sysmod == NULL) {
|
if (sysmod == NULL) {
|
||||||
|
@ -3428,7 +3430,7 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
|
||||||
}
|
}
|
||||||
interp->sysdict = Py_NewRef(sysdict);
|
interp->sysdict = Py_NewRef(sysdict);
|
||||||
|
|
||||||
if (PyDict_SetItemString(sysdict, "modules", interp->modules) < 0) {
|
if (PyDict_SetItemString(sysdict, "modules", modules) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3442,7 +3444,7 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyImport_FixupBuiltin(sysmod, "sys", interp->modules) < 0) {
|
if (_PyImport_FixupBuiltin(sysmod, "sys", modules) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue