Skip to content

bpo-28411: Remove "modules" field from Py_InterpreterState. #1638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
70f6e19
Add _PyImport_GetModuleDict().
ericsnowcurrently Oct 7, 2016
10f7443
Import the sys module before any other imports.
ericsnowcurrently Oct 10, 2016
5ea0e3b
Pass the modules dict to _PyImport_FindBuiltin().
ericsnowcurrently Oct 10, 2016
29780ec
Replace usage of interp->modules with PyImport_GetModuleDict().
ericsnowcurrently Oct 7, 2016
e6de215
Add _PyImport_EnsureInitialized().
ericsnowcurrently Oct 10, 2016
29f6b7c
Add _PyModule_Create2().
ericsnowcurrently Oct 10, 2016
b77d73f
Use _PyModule_Create2() for key builtin modules.
ericsnowcurrently Oct 10, 2016
8275633
Check sys.modules in _PyImport_EnsureInitialized().
ericsnowcurrently Oct 10, 2016
7c62114
Drop PyInterpreterState.modules.
ericsnowcurrently Oct 7, 2016
428d223
Pass the modules dict to _PyImport_FixupBuiltin().
ericsnowcurrently Oct 10, 2016
833b00b
Pass PyInterpreterState to _PyImport_GetModuleDict().
ericsnowcurrently Oct 11, 2016
e0e51d2
Drop _PyImport_GetModuleDict().
ericsnowcurrently Oct 11, 2016
88aadeb
_PyModule_Create2 -> _PyModule_CreateInitialized
ericsnowcurrently May 17, 2017
79320bd
_PyImport_EnsureInitialized() -> _PyImport_IsInitialized()
ericsnowcurrently May 18, 2017
6a0215c
Add _PyImport_GetModule*.
ericsnowcurrently May 18, 2017
dabd187
Allow sys.modules to be any mapping.
ericsnowcurrently May 18, 2017
58d9be7
Add _PyImport_SetModule*.
ericsnowcurrently May 18, 2017
e3b0f0c
Add PyImport_GetModule().
ericsnowcurrently May 18, 2017
d9c6b79
Fix ref counts.
ericsnowcurrently May 18, 2017
e3565f9
Look up "new" modules in the given modules dict.
ericsnowcurrently May 18, 2017
9946341
Fix error checking.
ericsnowcurrently May 20, 2017
08e556e
Use PyImport_GetModuleDict() in PyImport_GetModule().
ericsnowcurrently May 23, 2017
f043e47
Decref the module when done.
ericsnowcurrently May 25, 2017
b2edd25
Add a missing incref.
ericsnowcurrently May 25, 2017
0eced28
Fix post-rebase.
ericsnowcurrently Sep 4, 2017
a85a11f
Add a Misc/NEWS entry.
ericsnowcurrently Sep 4, 2017
9ba4c43
Make the docs for PyImport_GetModule() more clear.
ericsnowcurrently Sep 4, 2017
f837a61
Fix style (bracket placement).
ericsnowcurrently Sep 4, 2017
101aa31
Drop _PyImport_GetModuleString().
ericsnowcurrently Sep 4, 2017
8f8a7a2
Use PyDict_CheckExact() for sys.modules in fast case.
ericsnowcurrently Sep 4, 2017
3a56648
Do not use PyMapping_HasKey() with an error set.
ericsnowcurrently Sep 4, 2017
619b0a0
Revert a code order change.
ericsnowcurrently Sep 4, 2017
57eeb5b
Drop _PyImport_FixupExtensionObjectEx().
ericsnowcurrently Sep 4, 2017
6544fa2
Switch the code order back.
ericsnowcurrently Sep 4, 2017
8e86c53
Add a whatsnew entry for porting.
ericsnowcurrently Sep 4, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Doc/c-api/import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ Importing Modules
Return the dictionary used for the module administration (a.k.a.
``sys.modules``). Note that this is a per-interpreter variable.

.. c:function:: PyObject* PyImport_GetModule(PyObject *name)

Return the already imported module with the given name. If the
module has not been imported yet then returns NULL but does not set
an error. Returns NULL and sets an error if the lookup failed.

.. versionadded:: 3.7

.. c:function:: PyObject* PyImport_GetImporter(PyObject *path)

Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ Changes in the Python API
and module are affected by this change. (Contributed by INADA Naoki and
Eugene Toder in :issue:`29463`.)

* ``PyInterpreterState`` no longer has a ``modules`` field. Instead use
``sys.modules``.

* The *mode* argument of :func:`os.makedirs` no longer affects the file
permission bits of newly-created intermediate-level directories.
To set their file permission bits you can set the umask before invoking
Expand Down
25 changes: 22 additions & 3 deletions Include/import.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,25 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject(
);
#endif
PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void);
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *);
#endif
PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name);
PyAPI_FUNC(PyObject *) _PyImport_GetModuleWithError(PyObject *name);
PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name);
PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module);
PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module);
#endif
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000
PyAPI_FUNC(PyObject *) PyImport_AddModuleObject(
PyObject *name
);
#endif
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *, PyObject *);
#endif
PyAPI_FUNC(PyObject *) PyImport_AddModule(
const char *name /* UTF-8 encoded string */
);
Expand Down Expand Up @@ -97,14 +111,19 @@ PyAPI_FUNC(int) _PyImport_ReleaseLock(void);
PyAPI_FUNC(void) _PyImport_ReInitLock(void);

PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin(
const char *name /* UTF-8 encoded string */
const char *name, /* UTF-8 encoded string */
PyObject *modules
);
PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObjectEx(PyObject *, PyObject *,
PyObject *);
PyAPI_FUNC(int) _PyImport_FixupBuiltin(
PyObject *mod,
const char *name /* UTF-8 encoded string */
const char *name, /* UTF-8 encoded string */
PyObject *modules
);
PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *, PyObject *);
PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *,
PyObject *, PyObject *);

struct _inittab {
const char *name; /* ASCII encoded string */
Expand Down
4 changes: 4 additions & 0 deletions Include/modsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def);

PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*,
int apiver);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(struct PyModuleDef*,
int apiver);
#endif

#ifdef Py_LIMITED_API
#define PyModule_Create(module) \
Expand Down
1 change: 0 additions & 1 deletion Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ typedef struct _is {

int64_t id;

PyObject *modules;
PyObject *modules_by_index;
PyObject *sysdict;
PyObject *builtins;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``PyInterpreterState`` has a "modules" field that is copied into
``sys.modules`` during interpreter startup. This causes problems if a
program replaces ``sys.modules`` with something else. To solve this we
eliminate ``PyInterpreterState.modules``.
12 changes: 2 additions & 10 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -6418,9 +6418,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/
{
PyObject *global;
PyObject *modules_dict;
PyObject *module;
_Py_IDENTIFIER(modules);

/* Try to map the old names used in Python 2.x to the new ones used in
Python 3.x. We do this only with old pickle protocols and when the
Expand Down Expand Up @@ -6477,25 +6475,19 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
}
}

modules_dict = _PySys_GetObjectId(&PyId_modules);
if (modules_dict == NULL) {
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
return NULL;
}

module = PyDict_GetItemWithError(modules_dict, module_name);
module = PyImport_GetModule(module_name);
if (module == NULL) {
if (PyErr_Occurred())
return NULL;
module = PyImport_Import(module_name);
if (module == NULL)
return NULL;
global = getattribute(module, global_name, self->proto >= 4);
Py_DECREF(module);
}
else {
global = getattribute(module, global_name, self->proto >= 4);
}
Py_DECREF(module);
return global;
}

Expand Down
10 changes: 2 additions & 8 deletions Modules/pyexpat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,7 +1643,6 @@ MODULE_INITFUNC(void)
PyObject *errors_module;
PyObject *modelmod_name;
PyObject *model_module;
PyObject *sys_modules;
PyObject *tmpnum, *tmpstr;
PyObject *codes_dict;
PyObject *rev_codes_dict;
Expand Down Expand Up @@ -1693,11 +1692,6 @@ MODULE_INITFUNC(void)
*/
PyModule_AddStringConstant(m, "native_encoding", "UTF-8");

sys_modules = PySys_GetObject("modules");
if (sys_modules == NULL) {
Py_DECREF(m);
return NULL;
}
d = PyModule_GetDict(m);
if (d == NULL) {
Py_DECREF(m);
Expand All @@ -1707,7 +1701,7 @@ MODULE_INITFUNC(void)
if (errors_module == NULL) {
errors_module = PyModule_New(MODULE_NAME ".errors");
if (errors_module != NULL) {
PyDict_SetItem(sys_modules, errmod_name, errors_module);
_PyImport_SetModule(errmod_name, errors_module);
/* gives away the reference to errors_module */
PyModule_AddObject(m, "errors", errors_module);
}
Expand All @@ -1717,7 +1711,7 @@ MODULE_INITFUNC(void)
if (model_module == NULL) {
model_module = PyModule_New(MODULE_NAME ".model");
if (model_module != NULL) {
PyDict_SetItem(sys_modules, modelmod_name, model_module);
_PyImport_SetModule(modelmod_name, model_module);
/* gives away the reference to model_module */
PyModule_AddObject(m, "model", model_module);
}
Expand Down
12 changes: 9 additions & 3 deletions Objects/moduleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,18 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions)

PyObject *
PyModule_Create2(struct PyModuleDef* module, int module_api_version)
{
if (!_PyImport_IsInitialized(PyThreadState_GET()->interp))
Py_FatalError("Python import machinery not initialized");
return _PyModule_CreateInitialized(module, module_api_version);
}

PyObject *
_PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version)
{
const char* name;
PyModuleObject *m;
PyInterpreterState *interp = PyThreadState_Get()->interp;
if (interp->modules == NULL)
Py_FatalError("Python import machinery not initialized");

if (!PyModuleDef_Init(module))
return NULL;
name = module->m_name;
Expand Down
3 changes: 1 addition & 2 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3901,7 +3901,6 @@ import_copyreg(void)
{
PyObject *copyreg_str;
PyObject *copyreg_module;
PyInterpreterState *interp = PyThreadState_GET()->interp;
_Py_IDENTIFIER(copyreg);

copyreg_str = _PyUnicode_FromId(&PyId_copyreg);
Expand All @@ -3913,7 +3912,7 @@ import_copyreg(void)
by storing a reference to the cached module in a static variable, but
this broke when multiple embedded interpreters were in use (see issue
#17408 and #19088). */
copyreg_module = PyDict_GetItemWithError(interp->modules, copyreg_str);
copyreg_module = _PyImport_GetModuleWithError(copyreg_str);
if (copyreg_module != NULL) {
Py_INCREF(copyreg_module);
return copyreg_module;
Expand Down
5 changes: 1 addition & 4 deletions Python/_warnings.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ static PyObject *
get_warnings_attr(const char *attr, int try_import)
{
static PyObject *warnings_str = NULL;
PyObject *all_modules;
PyObject *warnings_module, *obj;

if (warnings_str == NULL) {
Expand All @@ -64,9 +63,7 @@ get_warnings_attr(const char *attr, int try_import)
}
}
else {
all_modules = PyImport_GetModuleDict();

warnings_module = PyDict_GetItem(all_modules, warnings_str);
warnings_module = _PyImport_GetModule(warnings_str);
if (warnings_module == NULL)
return NULL;

Expand Down
2 changes: 1 addition & 1 deletion Python/bltinmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2685,7 +2685,7 @@ _PyBuiltin_Init(void)
PyType_Ready(&PyZip_Type) < 0)
return NULL;

mod = PyModule_Create(&builtinsmodule);
mod = _PyModule_CreateInitialized(&builtinsmodule, PYTHON_API_VERSION);
if (mod == NULL)
return NULL;
dict = PyModule_GetDict(mod);
Expand Down
2 changes: 1 addition & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -5054,7 +5054,7 @@ import_from(PyObject *v, PyObject *name)
Py_DECREF(pkgname);
return NULL;
}
x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname);
x = _PyImport_GetModule(fullmodname);
Py_DECREF(fullmodname);
if (x == NULL) {
goto error;
Expand Down
Loading