diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 870ca066923521..e4b7e0d897de55 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -485,6 +485,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 diff --git a/Include/pystate.h b/Include/pystate.h index 507a598297e1f7..5b75bb080fe8ec 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -53,7 +53,6 @@ typedef struct _is { int64_t id; - PyObject *modules; PyObject *modules_by_index; PyObject *sysdict; PyObject *builtins; diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst new file mode 100644 index 00000000000000..2417f781276c75 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst @@ -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``. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index d531dee2565fc2..cf396bfb2aa78e 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1684,7 +1684,6 @@ whichmodule(PyObject *global, PyObject *dotted_path) Py_ssize_t i; PyObject *modules; _Py_IDENTIFIER(__module__); - _Py_IDENTIFIER(modules); _Py_IDENTIFIER(__main__); module_name = _PyObject_GetAttrId(global, &PyId___module__); @@ -1705,7 +1704,7 @@ whichmodule(PyObject *global, PyObject *dotted_path) assert(module_name == NULL); /* Fallback on walking sys.modules */ - modules = _PySys_GetObjectId(&PyId_modules); + modules = PyImport_GetModuleDict(); if (modules == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); return NULL; diff --git a/Python/import.c b/Python/import.c index 5e841ca782d2bc..e23f71e5a3964c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -290,11 +290,17 @@ _PyImport_Fini(void) PyObject * PyImport_GetModuleDict(void) { - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->modules == NULL) { - Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); + PyObject *sysdict = PyThreadState_GET()->interp->sysdict; + if (sysdict == NULL) { + Py_FatalError("PyImport_GetModuleDict: no sys module!"); + } + + _Py_IDENTIFIER(modules); + PyObject *modules = _PyDict_GetItemId(sysdict, &PyId_modules); + if (modules == NULL) { + Py_FatalError("lost sys.modules"); } - return interp->modules; + return modules; } /* In some corner cases it is important to be sure that the import @@ -304,7 +310,11 @@ PyImport_GetModuleDict(void) int _PyImport_IsInitialized(PyInterpreterState *interp) { - if (interp->modules == NULL) + if (interp->sysdict == NULL) + return 0; + _Py_IDENTIFIER(modules); + PyObject *modules = _PyDict_GetItemId(interp->sysdict, &PyId_modules); + if (modules == NULL) return 0; return 1; } @@ -543,7 +553,6 @@ PyImport_Cleanup(void) /* 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 */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7adbc29406e014..eb1612457cc86f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -674,7 +674,6 @@ void _Py_InitializeCore(const _PyCoreConfig *config) PyObject *modules = PyDict_New(); if (modules == NULL) Py_FatalError("Py_InitializeCore: can't make modules dictionary"); - interp->modules = modules; sysmod = _PySys_BeginInit(); if (sysmod == NULL) @@ -1210,7 +1209,6 @@ Py_NewInterpreter(void) PyObject *modules = PyDict_New(); if (modules == NULL) Py_FatalError("Py_NewInterpreter: can't make modules dictionary"); - interp->modules = modules; sysmod = _PyImport_FindBuiltin("sys", modules); if (sysmod != NULL) { diff --git a/Python/pystate.c b/Python/pystate.c index 53c1236145761d..08048428610dfd 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -90,7 +90,6 @@ PyInterpreterState_New(void) PyMem_RawMalloc(sizeof(PyInterpreterState)); if (interp != NULL) { - interp->modules = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; @@ -154,7 +153,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); - Py_CLEAR(interp->modules); Py_CLEAR(interp->modules_by_index); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins);