Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 86b7afd

Browse files
bpo-28411: Remove "modules" field from Py_InterpreterState. (#1638)
sys.modules is the one true source.
1 parent f5ea83f commit 86b7afd

18 files changed

+261
-111
lines changed

Doc/c-api/import.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ Importing Modules
204204
Return the dictionary used for the module administration (a.k.a.
205205
``sys.modules``). Note that this is a per-interpreter variable.
206206
207+
.. c:function:: PyObject* PyImport_GetModule(PyObject *name)
208+
209+
Return the already imported module with the given name. If the
210+
module has not been imported yet then returns NULL but does not set
211+
an error. Returns NULL and sets an error if the lookup failed.
212+
213+
.. versionadded:: 3.7
207214
208215
.. c:function:: PyObject* PyImport_GetImporter(PyObject *path)
209216

Doc/whatsnew/3.7.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ Changes in the Python API
456456
and module are affected by this change. (Contributed by INADA Naoki and
457457
Eugene Toder in :issue:`29463`.)
458458

459+
* ``PyInterpreterState`` no longer has a ``modules`` field. Instead use
460+
``sys.modules``.
461+
459462
* The *mode* argument of :func:`os.makedirs` no longer affects the file
460463
permission bits of newly-created intermediate-level directories.
461464
To set their file permission bits you can set the umask before invoking

Include/import.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,25 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject(
3838
);
3939
#endif
4040
PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void);
41+
#ifndef Py_LIMITED_API
42+
PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *);
43+
#endif
44+
PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name);
45+
#ifndef Py_LIMITED_API
46+
PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name);
47+
PyAPI_FUNC(PyObject *) _PyImport_GetModuleWithError(PyObject *name);
48+
PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name);
49+
PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module);
50+
PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module);
51+
#endif
4152
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000
4253
PyAPI_FUNC(PyObject *) PyImport_AddModuleObject(
4354
PyObject *name
4455
);
4556
#endif
57+
#ifndef Py_LIMITED_API
58+
PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *, PyObject *);
59+
#endif
4660
PyAPI_FUNC(PyObject *) PyImport_AddModule(
4761
const char *name /* UTF-8 encoded string */
4862
);
@@ -97,14 +111,19 @@ PyAPI_FUNC(int) _PyImport_ReleaseLock(void);
97111
PyAPI_FUNC(void) _PyImport_ReInitLock(void);
98112

99113
PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin(
100-
const char *name /* UTF-8 encoded string */
114+
const char *name, /* UTF-8 encoded string */
115+
PyObject *modules
101116
);
102117
PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *);
118+
PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObjectEx(PyObject *, PyObject *,
119+
PyObject *);
103120
PyAPI_FUNC(int) _PyImport_FixupBuiltin(
104121
PyObject *mod,
105-
const char *name /* UTF-8 encoded string */
122+
const char *name, /* UTF-8 encoded string */
123+
PyObject *modules
106124
);
107-
PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *, PyObject *);
125+
PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *,
126+
PyObject *, PyObject *);
108127

109128
struct _inittab {
110129
const char *name; /* ASCII encoded string */

Include/modsupport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def);
191191

192192
PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*,
193193
int apiver);
194+
#ifndef Py_LIMITED_API
195+
PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(struct PyModuleDef*,
196+
int apiver);
197+
#endif
194198

195199
#ifdef Py_LIMITED_API
196200
#define PyModule_Create(module) \

Include/pystate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ typedef struct _is {
5252

5353
int64_t id;
5454

55-
PyObject *modules;
5655
PyObject *modules_by_index;
5756
PyObject *sysdict;
5857
PyObject *builtins;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``PyInterpreterState`` has a "modules" field that is copied into
2+
``sys.modules`` during interpreter startup. This causes problems if a
3+
program replaces ``sys.modules`` with something else. To solve this we
4+
eliminate ``PyInterpreterState.modules``.

Modules/_pickle.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6418,9 +6418,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
64186418
/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/
64196419
{
64206420
PyObject *global;
6421-
PyObject *modules_dict;
64226421
PyObject *module;
6423-
_Py_IDENTIFIER(modules);
64246422

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

6480-
modules_dict = _PySys_GetObjectId(&PyId_modules);
6481-
if (modules_dict == NULL) {
6482-
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
6483-
return NULL;
6484-
}
6485-
6486-
module = PyDict_GetItemWithError(modules_dict, module_name);
6478+
module = PyImport_GetModule(module_name);
64876479
if (module == NULL) {
64886480
if (PyErr_Occurred())
64896481
return NULL;
64906482
module = PyImport_Import(module_name);
64916483
if (module == NULL)
64926484
return NULL;
64936485
global = getattribute(module, global_name, self->proto >= 4);
6494-
Py_DECREF(module);
64956486
}
64966487
else {
64976488
global = getattribute(module, global_name, self->proto >= 4);
64986489
}
6490+
Py_DECREF(module);
64996491
return global;
65006492
}
65016493

Modules/pyexpat.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,6 @@ MODULE_INITFUNC(void)
16431643
PyObject *errors_module;
16441644
PyObject *modelmod_name;
16451645
PyObject *model_module;
1646-
PyObject *sys_modules;
16471646
PyObject *tmpnum, *tmpstr;
16481647
PyObject *codes_dict;
16491648
PyObject *rev_codes_dict;
@@ -1693,11 +1692,6 @@ MODULE_INITFUNC(void)
16931692
*/
16941693
PyModule_AddStringConstant(m, "native_encoding", "UTF-8");
16951694

1696-
sys_modules = PySys_GetObject("modules");
1697-
if (sys_modules == NULL) {
1698-
Py_DECREF(m);
1699-
return NULL;
1700-
}
17011695
d = PyModule_GetDict(m);
17021696
if (d == NULL) {
17031697
Py_DECREF(m);
@@ -1707,7 +1701,7 @@ MODULE_INITFUNC(void)
17071701
if (errors_module == NULL) {
17081702
errors_module = PyModule_New(MODULE_NAME ".errors");
17091703
if (errors_module != NULL) {
1710-
PyDict_SetItem(sys_modules, errmod_name, errors_module);
1704+
_PyImport_SetModule(errmod_name, errors_module);
17111705
/* gives away the reference to errors_module */
17121706
PyModule_AddObject(m, "errors", errors_module);
17131707
}
@@ -1717,7 +1711,7 @@ MODULE_INITFUNC(void)
17171711
if (model_module == NULL) {
17181712
model_module = PyModule_New(MODULE_NAME ".model");
17191713
if (model_module != NULL) {
1720-
PyDict_SetItem(sys_modules, modelmod_name, model_module);
1714+
_PyImport_SetModule(modelmod_name, model_module);
17211715
/* gives away the reference to model_module */
17221716
PyModule_AddObject(m, "model", model_module);
17231717
}

Objects/moduleobject.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,18 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions)
160160

161161
PyObject *
162162
PyModule_Create2(struct PyModuleDef* module, int module_api_version)
163+
{
164+
if (!_PyImport_IsInitialized(PyThreadState_GET()->interp))
165+
Py_FatalError("Python import machinery not initialized");
166+
return _PyModule_CreateInitialized(module, module_api_version);
167+
}
168+
169+
PyObject *
170+
_PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version)
163171
{
164172
const char* name;
165173
PyModuleObject *m;
166-
PyInterpreterState *interp = PyThreadState_Get()->interp;
167-
if (interp->modules == NULL)
168-
Py_FatalError("Python import machinery not initialized");
174+
169175
if (!PyModuleDef_Init(module))
170176
return NULL;
171177
name = module->m_name;

Objects/typeobject.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,7 +3901,6 @@ import_copyreg(void)
39013901
{
39023902
PyObject *copyreg_str;
39033903
PyObject *copyreg_module;
3904-
PyInterpreterState *interp = PyThreadState_GET()->interp;
39053904
_Py_IDENTIFIER(copyreg);
39063905

39073906
copyreg_str = _PyUnicode_FromId(&PyId_copyreg);
@@ -3913,7 +3912,7 @@ import_copyreg(void)
39133912
by storing a reference to the cached module in a static variable, but
39143913
this broke when multiple embedded interpreters were in use (see issue
39153914
#17408 and #19088). */
3916-
copyreg_module = PyDict_GetItemWithError(interp->modules, copyreg_str);
3915+
copyreg_module = _PyImport_GetModuleWithError(copyreg_str);
39173916
if (copyreg_module != NULL) {
39183917
Py_INCREF(copyreg_module);
39193918
return copyreg_module;

Python/_warnings.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ static PyObject *
4444
get_warnings_attr(const char *attr, int try_import)
4545
{
4646
static PyObject *warnings_str = NULL;
47-
PyObject *all_modules;
4847
PyObject *warnings_module, *obj;
4948

5049
if (warnings_str == NULL) {
@@ -64,9 +63,7 @@ get_warnings_attr(const char *attr, int try_import)
6463
}
6564
}
6665
else {
67-
all_modules = PyImport_GetModuleDict();
68-
69-
warnings_module = PyDict_GetItem(all_modules, warnings_str);
66+
warnings_module = _PyImport_GetModule(warnings_str);
7067
if (warnings_module == NULL)
7168
return NULL;
7269

Python/bltinmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2685,7 +2685,7 @@ _PyBuiltin_Init(void)
26852685
PyType_Ready(&PyZip_Type) < 0)
26862686
return NULL;
26872687

2688-
mod = PyModule_Create(&builtinsmodule);
2688+
mod = _PyModule_CreateInitialized(&builtinsmodule, PYTHON_API_VERSION);
26892689
if (mod == NULL)
26902690
return NULL;
26912691
dict = PyModule_GetDict(mod);

Python/ceval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5054,7 +5054,7 @@ import_from(PyObject *v, PyObject *name)
50545054
Py_DECREF(pkgname);
50555055
return NULL;
50565056
}
5057-
x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname);
5057+
x = _PyImport_GetModule(fullmodname);
50585058
Py_DECREF(fullmodname);
50595059
if (x == NULL) {
50605060
goto error;

0 commit comments

Comments
 (0)