From 8f3ecfc676a6dacf71665fc54509b33a8f868198 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 11:44:25 -0700 Subject: [PATCH 01/30] Add _PyImport_GetModule*. --- Include/import.h | 3 +++ Python/_warnings.c | 5 +---- Python/ceval.c | 2 +- Python/import.c | 38 +++++++++++++++++++++++++++----------- Python/pylifecycle.c | 4 ++-- Python/sysmodule.c | 5 +---- 6 files changed, 35 insertions(+), 22 deletions(-) diff --git a/Include/import.h b/Include/import.h index 95c52b0bfba129..9eace3e6f49add 100644 --- a/Include/import.h +++ b/Include/import.h @@ -40,6 +40,9 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); +PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name); +PyAPI_FUNC(PyObject *) _PyImport_GetModuleString(const char *name); +PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 PyAPI_FUNC(PyObject *) PyImport_AddModuleObject( diff --git a/Python/_warnings.c b/Python/_warnings.c index ba004859df82f7..6dad08068672ee 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -38,7 +38,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) { @@ -58,9 +57,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; diff --git a/Python/ceval.c b/Python/ceval.c index 08533a42bf2b54..5dd7cd9f03e35f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4935,7 +4935,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; diff --git a/Python/import.c b/Python/import.c index 7aa7a1bdf7988e..fa9a09aeb5c8e3 100644 --- a/Python/import.c +++ b/Python/import.c @@ -308,6 +308,27 @@ _PyImport_IsInitialized(PyInterpreterState *interp) return 1; } +PyObject * +_PyImport_GetModule(PyObject *name) +{ + PyObject *modules = PyImport_GetModuleDict(); + return PyDict_GetItem(modules, name); +} + +PyObject * +_PyImport_GetModuleString(const char *name) +{ + PyObject *modules = PyImport_GetModuleDict(); + return PyDict_GetItemString(modules, name); +} + +PyObject * +_PyImport_GetModuleId(struct _Py_Identifier *name) +{ + PyObject *modules = PyImport_GetModuleDict(); + return _PyDict_GetItemId(modules, name); +} + /* List of names to clear in sys */ static const char * const sys_deletes[] = { "path", "argv", "ps1", "ps2", @@ -823,7 +844,6 @@ module_dict_for_exec(PyObject *name) static PyObject * exec_code_in_module(PyObject *name, PyObject *module_dict, PyObject *code_object) { - PyObject *modules = PyImport_GetModuleDict(); PyObject *v, *m; v = PyEval_EvalCode(code_object, module_dict, module_dict); @@ -833,7 +853,8 @@ exec_code_in_module(PyObject *name, PyObject *module_dict, PyObject *code_object } Py_DECREF(v); - if ((m = PyDict_GetItem(modules, name)) == NULL) { + m = _PyImport_GetModule(name); + if (m == NULL) { PyErr_Format(PyExc_ImportError, "Loaded module %R not found in sys.modules", name); @@ -1540,8 +1561,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, Py_INCREF(abs_name); } - PyObject *modules = PyImport_GetModuleDict(); - mod = PyDict_GetItem(modules, abs_name); + mod = _PyImport_GetModule(abs_name); if (mod != NULL && mod != Py_None) { _Py_IDENTIFIER(__spec__); _Py_IDENTIFIER(_initializing); @@ -1628,8 +1648,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, goto error; } - PyObject *modules = PyImport_GetModuleDict(); - final_mod = PyDict_GetItem(modules, to_return); + final_mod = _PyImport_GetModule(to_return); Py_DECREF(to_return); if (final_mod == NULL) { PyErr_Format(PyExc_KeyError, @@ -1684,8 +1703,7 @@ PyImport_ReloadModule(PyObject *m) { _Py_IDENTIFIER(reload); PyObject *reloaded_module = NULL; - PyObject *modules = PyImport_GetModuleDict(); - PyObject *imp = PyDict_GetItemString(modules, "imp"); + PyObject *imp = _PyImport_GetModuleString("imp"); if (imp == NULL) { imp = PyImport_ImportModule("imp"); if (imp == NULL) { @@ -1720,7 +1738,6 @@ PyImport_Import(PyObject *module_name) PyObject *globals = NULL; PyObject *import = NULL; PyObject *builtins = NULL; - PyObject *modules = NULL; PyObject *r = NULL; /* Initialize constant string objects */ @@ -1775,8 +1792,7 @@ PyImport_Import(PyObject *module_name) goto err; Py_DECREF(r); - modules = PyImport_GetModuleDict(); - r = PyDict_GetItemWithError(modules, module_name); + r = _PyImport_GetModule(module_name); if (r != NULL) { Py_INCREF(r); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5c8cf5b9bd5fc0..32bbb07bcc60da 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1916,13 +1916,13 @@ wait_for_thread_shutdown(void) { _Py_IDENTIFIER(_shutdown); PyObject *result; - PyObject *modules = PyImport_GetModuleDict(); - PyObject *threading = PyMapping_GetItemString(modules, "threading"); + PyObject *threading = _PyImport_GetModuleString("threading"); if (threading == NULL) { /* threading not imported */ PyErr_Clear(); return; } + Py_INCREF(threading); result = _PyObject_CallMethodId(threading, &PyId__shutdown, NULL); if (result == NULL) { PyErr_WriteUnraisable(threading); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index d463683df1df07..5bde4b7b7028f7 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -162,14 +162,11 @@ static PyObject * sys_displayhook(PyObject *self, PyObject *o) { PyObject *outf; - PyObject *modules = PyImport_GetModuleDict(); - if (modules == NULL) - return NULL; PyObject *builtins; static PyObject *newline = NULL; int err; - builtins = _PyDict_GetItemId(modules, &PyId_builtins); + builtins = _PyImport_GetModuleId(&PyId_builtins); if (builtins == NULL) { PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); return NULL; From 9dc9dedfb821ee6e7b2d5d976619eccc580e381c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 12:50:48 -0700 Subject: [PATCH 02/30] Allow sys.modules to be any mapping. --- Modules/_pickle.c | 11 ++++++++- Modules/pyexpat.c | 4 ++-- Objects/typeobject.c | 10 +++++++- Python/import.c | 56 ++++++++++++++++++++++++++++++++------------ Python/pylifecycle.c | 2 +- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 3165b4e6d686de..4b7921578f70e6 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -6490,7 +6490,16 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, return NULL; } - module = PyDict_GetItemWithError(modules_dict, module_name); + module = PyObject_GetItem(modules_dict, module_name); + if (PyDict_Check(modules_dict)) { + module = PyDict_GetItemWithError(modules_dict, module_name); + } else { + module = PyObject_GetItem(modules_dict, module_name); + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). + PyErr_Clear(); + } if (module == NULL) { if (PyErr_Occurred()) return NULL; diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index d9cfa3e20859d5..4e80c31d9522a5 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1707,7 +1707,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); + PyObject_SetItem(sys_modules, errmod_name, errors_module); /* gives away the reference to errors_module */ PyModule_AddObject(m, "errors", errors_module); } @@ -1717,7 +1717,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); + PyObject_SetItem(sys_modules, modelmod_name, model_module); /* gives away the reference to model_module */ PyModule_AddObject(m, "model", model_module); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9ebbb21ef8d37d..9502789b50a339 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3914,7 +3914,15 @@ import_copyreg(void) this broke when multiple embedded interpreters were in use (see issue #17408 and #19088). */ PyObject *modules = PyImport_GetModuleDict(); - copyreg_module = PyDict_GetItemWithError(modules, copyreg_str); + if (PyDict_Check(modules)) { + copyreg_module = PyDict_GetItemWithError(modules, copyreg_str); + } else { + copyreg_module = PyObject_GetItem(modules, copyreg_str); + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). + PyErr_Clear(); + } if (copyreg_module != NULL) { Py_INCREF(copyreg_module); return copyreg_module; diff --git a/Python/import.c b/Python/import.c index fa9a09aeb5c8e3..4c272fb3a08ffe 100644 --- a/Python/import.c +++ b/Python/import.c @@ -312,21 +312,39 @@ PyObject * _PyImport_GetModule(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - return PyDict_GetItem(modules, name); + if (PyDict_Check(modules)) + return PyDict_GetItem(modules, name); + + PyObject *mod = PyObject_GetItem(modules, name); + if (mod == NULL && PyErr_Occurred()) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItem(). + PyErr_Clear(); + return mod; } PyObject * _PyImport_GetModuleString(const char *name) { PyObject *modules = PyImport_GetModuleDict(); - return PyDict_GetItemString(modules, name); + if (PyDict_Check(modules)) + return PyDict_GetItemString(modules, name); + + PyObject *mod = PyMapping_GetItemString(modules, name); + if (mod == NULL && PyErr_Occurred()) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemString(). + PyErr_Clear(); + return mod; } PyObject * -_PyImport_GetModuleId(struct _Py_Identifier *name) +_PyImport_GetModuleId(struct _Py_Identifier *nameid) { - PyObject *modules = PyImport_GetModuleDict(); - return _PyDict_GetItemId(modules, name); + PyObject *name = _PyUnicode_FromId(nameid); /* borrowed */ + if (name == NULL) + return NULL; + return _PyImport_GetModule(name); } /* List of names to clear in sys */ @@ -417,7 +435,7 @@ PyImport_Cleanup(void) if (Py_VerboseFlag && PyUnicode_Check(key)) PySys_FormatStderr("# cleanup[2] removing %U\n", key); STORE_MODULE_WEAKREF(key, value); - PyDict_SetItem(modules, key, Py_None); + PyObject_SetItem(modules, key, Py_None); } } @@ -562,10 +580,10 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, PyErr_BadInternalCall(); return -1; } - if (PyDict_SetItem(modules, name, mod) < 0) + if (PyObject_SetItem(modules, name, mod) < 0) return -1; if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItem(modules, name); + PyMapping_DelItem(modules, name); return -1; } if (def->m_size == -1) { @@ -646,14 +664,14 @@ _PyImport_FindExtensionObjectEx(PyObject *name, PyObject *filename, mod = def->m_base.m_init(); if (mod == NULL) return NULL; - if (PyDict_SetItem(modules, name, mod) == -1) { + if (PyObject_SetItem(modules, name, mod) == -1) { Py_DECREF(mod); return NULL; } Py_DECREF(mod); } if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItem(modules, name); + PyMapping_DelItem(modules, name); Py_DECREF(mod); return NULL; } @@ -694,8 +712,16 @@ _PyImport_AddModuleObject(PyObject *name, PyObject *modules) { PyObject *m; - if ((m = PyDict_GetItemWithError(modules, name)) != NULL && - PyModule_Check(m)) { + if (PyDict_Check(modules)) + m = PyDict_GetItemWithError(modules, name); + else { + m = PyObject_GetItem(modules, name); + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). + PyErr_Clear(); + } + if (m != NULL && PyModule_Check(m)) { return m; } if (PyErr_Occurred()) { @@ -704,7 +730,7 @@ _PyImport_AddModuleObject(PyObject *name, PyObject *modules) m = PyModule_NewObject(name); if (m == NULL) return NULL; - if (PyDict_SetItem(modules, name, m) != 0) { + if (PyObject_SetItem(modules, name, m) != 0) { Py_DECREF(m); return NULL; } @@ -731,9 +757,9 @@ static void remove_module(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_GetItem(modules, name) == NULL) + if (!PyMapping_HasKey(modules, name)) return; - if (PyDict_DelItem(modules, name) < 0) + if (PyMapping_DelItem(modules, name) < 0) Py_FatalError("import: deleting existing key in" "sys.modules failed"); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 32bbb07bcc60da..30a3295cc701ee 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -318,7 +318,7 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) if (Py_VerboseFlag) { PySys_FormatStderr("import sys # builtin\n"); } - if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) { + if (PyMapping_SetItemString(sys_modules, "_imp", impmod) < 0) { Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); } From f2a54b1169ad0ff363b438a3c40ece7b45c35446 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 13:50:48 -0700 Subject: [PATCH 03/30] Add _PyImport_SetModule*. --- Include/import.h | 2 ++ Modules/pyexpat.c | 10 ++-------- Python/import.c | 13 +++++++++++++ Python/pylifecycle.c | 7 +------ 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Include/import.h b/Include/import.h index 9eace3e6f49add..8ea0aed0881cdd 100644 --- a/Include/import.h +++ b/Include/import.h @@ -43,6 +43,8 @@ PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name); PyAPI_FUNC(PyObject *) _PyImport_GetModuleString(const char *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( diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 4e80c31d9522a5..c8a01d4e088ece 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -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; @@ -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); @@ -1707,7 +1701,7 @@ MODULE_INITFUNC(void) if (errors_module == NULL) { errors_module = PyModule_New(MODULE_NAME ".errors"); if (errors_module != NULL) { - PyObject_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); } @@ -1717,7 +1711,7 @@ MODULE_INITFUNC(void) if (model_module == NULL) { model_module = PyModule_New(MODULE_NAME ".model"); if (model_module != NULL) { - PyObject_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); } diff --git a/Python/import.c b/Python/import.c index 4c272fb3a08ffe..c30f31c4425b26 100644 --- a/Python/import.c +++ b/Python/import.c @@ -347,6 +347,19 @@ _PyImport_GetModuleId(struct _Py_Identifier *nameid) return _PyImport_GetModule(name); } +int +_PyImport_SetModule(PyObject *name, PyObject *m) { + PyObject *modules = PyImport_GetModuleDict(); + return PyObject_SetItem(modules, name, m); +} + +int +_PyImport_SetModuleString(const char *name, PyObject *m) { + PyObject *modules = PyImport_GetModuleDict(); + return PyMapping_SetItemString(modules, name, m); +} + + /* List of names to clear in sys */ static const char * const sys_deletes[] = { "path", "argv", "ps1", "ps2", diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 30a3295cc701ee..0dba2fd412e67d 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -283,7 +283,6 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) { PyObject *importlib; PyObject *impmod; - PyObject *sys_modules; PyObject *value; /* Import _importlib through its frozen version, _frozen_importlib. */ @@ -314,11 +313,7 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) else if (Py_VerboseFlag) { PySys_FormatStderr("import _imp # builtin\n"); } - sys_modules = PyImport_GetModuleDict(); - if (Py_VerboseFlag) { - PySys_FormatStderr("import sys # builtin\n"); - } - if (PyMapping_SetItemString(sys_modules, "_imp", impmod) < 0) { + if (_PyImport_SetModuleString("_imp", impmod) < 0) { Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); } From 502e1387d0c0a036035bf67924a9e87c80ac3d2e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 14:22:21 -0700 Subject: [PATCH 04/30] Add PyImport_GetModule(). --- Doc/c-api/import.rst | 5 +++++ Include/import.h | 4 ++++ Modules/_pickle.c | 19 +------------------ Objects/typeobject.c | 11 +---------- Python/import.c | 45 +++++++++++++++++++++++++++++++++----------- 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index 7c16ece0586610..a79b4e6dc2dc64 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -204,6 +204,11 @@ 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. + + .. versionadded:: 3.7 .. c:function:: PyObject* PyImport_GetImporter(PyObject *path) diff --git a/Include/import.h b/Include/import.h index 8ea0aed0881cdd..20c4fa009e1320 100644 --- a/Include/import.h +++ b/Include/import.h @@ -38,11 +38,15 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( ); #endif PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); +PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name); +PyAPI_FUNC(PyObject *) _PyImport_GetModuleWithError(PyObject *name); PyAPI_FUNC(PyObject *) _PyImport_GetModuleString(const char *name); PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); +PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *name, + PyObject *modules); PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module); PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module); #endif diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 4b7921578f70e6..766d7a536f74fa 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -6425,9 +6425,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 @@ -6484,22 +6482,7 @@ _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 = PyObject_GetItem(modules_dict, module_name); - if (PyDict_Check(modules_dict)) { - module = PyDict_GetItemWithError(modules_dict, module_name); - } else { - module = PyObject_GetItem(modules_dict, module_name); - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemWithError(). - PyErr_Clear(); - } + module = PyImport_GetModule(module_name); if (module == NULL) { if (PyErr_Occurred()) return NULL; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9502789b50a339..a06cab72e5ce42 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3913,16 +3913,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). */ - PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) { - copyreg_module = PyDict_GetItemWithError(modules, copyreg_str); - } else { - copyreg_module = PyObject_GetItem(modules, copyreg_str); - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemWithError(). - PyErr_Clear(); - } + copyreg_module = _PyImport_GetModuleWithError(copyreg_str); if (copyreg_module != NULL) { Py_INCREF(copyreg_module); return copyreg_module; diff --git a/Python/import.c b/Python/import.c index c30f31c4425b26..61c46b54652482 100644 --- a/Python/import.c +++ b/Python/import.c @@ -323,6 +323,21 @@ _PyImport_GetModule(PyObject *name) return mod; } +PyObject * +_PyImport_GetModuleWithError(PyObject *name) +{ + PyObject *modules = PyImport_GetModuleDict(); + if (PyDict_Check(modules)) + return PyDict_GetItemWithError(modules, name); + + PyObject *mod = PyObject_GetItem(modules, name); + if (mod == NULL && !PyMapping_HasKey(modules, name)) + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). + PyErr_Clear(); + return mod; +} + PyObject * _PyImport_GetModuleString(const char *name) { @@ -359,6 +374,24 @@ _PyImport_SetModuleString(const char *name, PyObject *m) { return PyMapping_SetItemString(modules, name, m); } +PyObject * +PyImport_GetModule(PyObject *name) +{ + _Py_IDENTIFIER(modules); + PyObject *modules = _PySys_GetObjectId(&PyId_modules); + if (modules == NULL) { + PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); + return NULL; + } + if (PyDict_Check(modules)) + return PyDict_GetItemWithError(modules, name); + + PyObject *m = PyObject_GetItem(modules, name); + if (m == NULL && !PyMapping_HasKey(modules, name)) + PyErr_Clear(); + return m; +} + /* List of names to clear in sys */ static const char * const sys_deletes[] = { @@ -723,17 +756,7 @@ PyImport_AddModuleObject(PyObject *name) PyObject * _PyImport_AddModuleObject(PyObject *name, PyObject *modules) { - PyObject *m; - - if (PyDict_Check(modules)) - m = PyDict_GetItemWithError(modules, name); - else { - m = PyObject_GetItem(modules, name); - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_KeyError)) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemWithError(). - PyErr_Clear(); - } + PyObject *m = _PyImport_GetModuleWithError(name); if (m != NULL && PyModule_Check(m)) { return m; } From ec8c5043ef33c56a140aa1272fb85d56ec7e63e6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 25 May 2017 11:17:42 -0700 Subject: [PATCH 05/30] Decref the module when done. --- Modules/_pickle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 766d7a536f74fa..bcbe4ac7945169 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -6490,11 +6490,11 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, 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; } From a1546f6e969afa856c1627c28e11b82025c70486 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 15:12:56 -0700 Subject: [PATCH 06/30] Fix ref counts. --- Python/import.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Python/import.c b/Python/import.c index 61c46b54652482..775053a1370791 100644 --- a/Python/import.c +++ b/Python/import.c @@ -316,10 +316,13 @@ _PyImport_GetModule(PyObject *name) return PyDict_GetItem(modules, name); PyObject *mod = PyObject_GetItem(modules, name); - if (mod == NULL && PyErr_Occurred()) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItem(). - PyErr_Clear(); + // For backward-comaptibility we copy the behavior of PyDict_GetItem(). + if (mod == NULL) { + if (PyErr_Occurred()) + PyErr_Clear(); + } else { + Py_DECREF(mod); + } return mod; } @@ -331,9 +334,9 @@ _PyImport_GetModuleWithError(PyObject *name) return PyDict_GetItemWithError(modules, name); PyObject *mod = PyObject_GetItem(modules, name); + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). if (mod == NULL && !PyMapping_HasKey(modules, name)) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemWithError(). PyErr_Clear(); return mod; } @@ -346,10 +349,14 @@ _PyImport_GetModuleString(const char *name) return PyDict_GetItemString(modules, name); PyObject *mod = PyMapping_GetItemString(modules, name); - if (mod == NULL && PyErr_Occurred()) - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemString(). - PyErr_Clear(); + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemString(). + if (mod == NULL) { + if (PyErr_Occurred()) + PyErr_Clear(); + } else { + Py_DECREF(mod); + } return mod; } From 5a5fad1e01dfd680967d602a495e75d16f8aadd3 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 18 May 2017 16:44:41 -0700 Subject: [PATCH 07/30] Look up "new" modules in the given modules dict. --- Python/import.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Python/import.c b/Python/import.c index 775053a1370791..4c604f7752ac42 100644 --- a/Python/import.c +++ b/Python/import.c @@ -763,7 +763,16 @@ PyImport_AddModuleObject(PyObject *name) PyObject * _PyImport_AddModuleObject(PyObject *name, PyObject *modules) { - PyObject *m = _PyImport_GetModuleWithError(name); + PyObject *m; + if (PyDict_Check(modules)) { + m = PyDict_GetItemWithError(modules, name); + } else { + m = PyObject_GetItem(modules, name); + // For backward-comaptibility we copy the behavior + // of PyDict_GetItemWithError(). + if (m == NULL && !PyMapping_HasKey(modules, name)) + PyErr_Clear(); + } if (m != NULL && PyModule_Check(m)) { return m; } From db0a2471a3f79b1e72ebe8111b06e45fd5bb1590 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 19 May 2017 18:28:43 -0700 Subject: [PATCH 08/30] Fix error checking. --- Python/import.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Python/import.c b/Python/import.c index 4c604f7752ac42..2e49e96ce9a8e6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -317,12 +317,9 @@ _PyImport_GetModule(PyObject *name) PyObject *mod = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior of PyDict_GetItem(). - if (mod == NULL) { - if (PyErr_Occurred()) - PyErr_Clear(); - } else { - Py_DECREF(mod); - } + if (PyErr_Occurred()) + PyErr_Clear(); + Py_XDECREF(mod); return mod; } @@ -336,7 +333,7 @@ _PyImport_GetModuleWithError(PyObject *name) PyObject *mod = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). - if (mod == NULL && !PyMapping_HasKey(modules, name)) + if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) PyErr_Clear(); return mod; } @@ -351,12 +348,9 @@ _PyImport_GetModuleString(const char *name) PyObject *mod = PyMapping_GetItemString(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemString(). - if (mod == NULL) { - if (PyErr_Occurred()) - PyErr_Clear(); - } else { - Py_DECREF(mod); - } + if (PyErr_Occurred()) + PyErr_Clear(); + Py_XDECREF(mod); return mod; } @@ -394,7 +388,7 @@ PyImport_GetModule(PyObject *name) return PyDict_GetItemWithError(modules, name); PyObject *m = PyObject_GetItem(modules, name); - if (m == NULL && !PyMapping_HasKey(modules, name)) + if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) PyErr_Clear(); return m; } @@ -770,15 +764,15 @@ _PyImport_AddModuleObject(PyObject *name, PyObject *modules) m = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). - if (m == NULL && !PyMapping_HasKey(modules, name)) + if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) PyErr_Clear(); } - if (m != NULL && PyModule_Check(m)) { - return m; - } if (PyErr_Occurred()) { return NULL; } + if (m != NULL && PyModule_Check(m)) { + return m; + } m = PyModule_NewObject(name); if (m == NULL) return NULL; @@ -809,11 +803,12 @@ static void remove_module(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (!PyMapping_HasKey(modules, name)) - return; - if (PyMapping_DelItem(modules, name) < 0) + if (PyMapping_DelItem(modules, name) < 0) { + if (!PyMapping_HasKey(modules, name)) + return; Py_FatalError("import: deleting existing key in" "sys.modules failed"); + } } From 7082b475ff5ccaabb756d9d9f7f9a9cf2d4b83c2 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 22 May 2017 17:45:31 -0700 Subject: [PATCH 09/30] Use PyImport_GetModuleDict() in PyImport_GetModule(). --- Python/import.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Python/import.c b/Python/import.c index 2e49e96ce9a8e6..8f2e8c54764abf 100644 --- a/Python/import.c +++ b/Python/import.c @@ -378,18 +378,21 @@ _PyImport_SetModuleString(const char *name, PyObject *m) { PyObject * PyImport_GetModule(PyObject *name) { - _Py_IDENTIFIER(modules); - PyObject *modules = _PySys_GetObjectId(&PyId_modules); + PyObject *m; + PyObject *modules = PyImport_GetModuleDict(); if (modules == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); return NULL; } - if (PyDict_Check(modules)) - return PyDict_GetItemWithError(modules, name); - - PyObject *m = PyObject_GetItem(modules, name); - if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) - PyErr_Clear(); + Py_INCREF(modules); + if (PyDict_Check(modules)) { + m = PyDict_GetItemWithError(modules, name); + } else { + m = PyObject_GetItem(modules, name); + if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) + PyErr_Clear(); + } + Py_DECREF(modules); return m; } From 5082c479790a02c44abb1e7d3c688ad32316db20 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 25 May 2017 11:26:42 -0700 Subject: [PATCH 10/30] Add a missing incref. --- Python/import.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/import.c b/Python/import.c index 8f2e8c54764abf..21af0316c02782 100644 --- a/Python/import.c +++ b/Python/import.c @@ -386,7 +386,8 @@ PyImport_GetModule(PyObject *name) } Py_INCREF(modules); if (PyDict_Check(modules)) { - m = PyDict_GetItemWithError(modules, name); + m = PyDict_GetItemWithError(modules, name); /* borrowed */ + Py_XINCREF(m); } else { m = PyObject_GetItem(modules, name); if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) From bb03872912d62256ce1254a6f6d7d76ecaca9ed8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 10:46:53 -0700 Subject: [PATCH 11/30] Add a Misc/NEWS entry. --- .../Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst 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..9f9c839944f0e4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst @@ -0,0 +1,3 @@ +``PyInterpreterState`` has a "modules" field that is copied into +``sys.modules`` during interpreter startup. Adding support for +other mappings than dict gives us some flexibility. From 2e07296f7853e84b5646a647a30d4882061c0739 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 11:34:31 -0700 Subject: [PATCH 12/30] Make the docs for PyImport_GetModule() more clear. --- Doc/c-api/import.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index a79b4e6dc2dc64..8cdc256e7c9e0e 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -206,7 +206,9 @@ Importing Modules .. c:function:: PyObject* PyImport_GetModule(PyObject *name) - Return the already imported module with the given 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 From 46311635ec97a293ebbbbe3287577e024f8ae1a5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 11:39:41 -0700 Subject: [PATCH 13/30] Fix style (bracket placement). --- Python/import.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Python/import.c b/Python/import.c index 21af0316c02782..e00181cd986b84 100644 --- a/Python/import.c +++ b/Python/import.c @@ -291,8 +291,9 @@ PyObject * PyImport_GetModuleDict(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->modules == NULL) + if (interp->modules == NULL) { Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); + } return interp->modules; } @@ -312,13 +313,15 @@ PyObject * _PyImport_GetModule(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) + if (PyDict_Check(modules)) { return PyDict_GetItem(modules, name); + } PyObject *mod = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior of PyDict_GetItem(). - if (PyErr_Occurred()) + if (PyErr_Occurred()) { PyErr_Clear(); + } Py_XDECREF(mod); return mod; } @@ -327,14 +330,16 @@ PyObject * _PyImport_GetModuleWithError(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) + if (PyDict_Check(modules)) { return PyDict_GetItemWithError(modules, name); + } PyObject *mod = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). - if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) + if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) { PyErr_Clear(); + } return mod; } @@ -342,14 +347,16 @@ PyObject * _PyImport_GetModuleString(const char *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) + if (PyDict_Check(modules)) { return PyDict_GetItemString(modules, name); + } PyObject *mod = PyMapping_GetItemString(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemString(). - if (PyErr_Occurred()) + if (PyErr_Occurred()) { PyErr_Clear(); + } Py_XDECREF(mod); return mod; } @@ -358,19 +365,22 @@ PyObject * _PyImport_GetModuleId(struct _Py_Identifier *nameid) { PyObject *name = _PyUnicode_FromId(nameid); /* borrowed */ - if (name == NULL) + if (name == NULL) { return NULL; + } return _PyImport_GetModule(name); } int -_PyImport_SetModule(PyObject *name, PyObject *m) { +_PyImport_SetModule(PyObject *name, PyObject *m) +{ PyObject *modules = PyImport_GetModuleDict(); return PyObject_SetItem(modules, name, m); } int -_PyImport_SetModuleString(const char *name, PyObject *m) { +_PyImport_SetModuleString(const char *name, PyObject *m) +{ PyObject *modules = PyImport_GetModuleDict(); return PyMapping_SetItemString(modules, name, m); } @@ -388,7 +398,8 @@ PyImport_GetModule(PyObject *name) if (PyDict_Check(modules)) { m = PyDict_GetItemWithError(modules, name); /* borrowed */ Py_XINCREF(m); - } else { + } + else { m = PyObject_GetItem(modules, name); if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) PyErr_Clear(); @@ -764,7 +775,8 @@ _PyImport_AddModuleObject(PyObject *name, PyObject *modules) PyObject *m; if (PyDict_Check(modules)) { m = PyDict_GetItemWithError(modules, name); - } else { + } + else { m = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). From 5b154b3a71998e89c525a6a89186fea9a094f9fe Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 12:13:41 -0700 Subject: [PATCH 14/30] Drop _PyImport_GetModuleString(). --- Include/import.h | 1 - Python/import.c | 21 ++------------------- Python/pylifecycle.c | 3 ++- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/Include/import.h b/Include/import.h index 20c4fa009e1320..f1276648153874 100644 --- a/Include/import.h +++ b/Include/import.h @@ -43,7 +43,6 @@ PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyImport_GetModule(PyObject *name); PyAPI_FUNC(PyObject *) _PyImport_GetModuleWithError(PyObject *name); -PyAPI_FUNC(PyObject *) _PyImport_GetModuleString(const char *name); PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *name, PyObject *modules); diff --git a/Python/import.c b/Python/import.c index e00181cd986b84..a8d9a5522ff4fd 100644 --- a/Python/import.c +++ b/Python/import.c @@ -343,24 +343,6 @@ _PyImport_GetModuleWithError(PyObject *name) return mod; } -PyObject * -_PyImport_GetModuleString(const char *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) { - return PyDict_GetItemString(modules, name); - } - - PyObject *mod = PyMapping_GetItemString(modules, name); - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemString(). - if (PyErr_Occurred()) { - PyErr_Clear(); - } - Py_XDECREF(mod); - return mod; -} - PyObject * _PyImport_GetModuleId(struct _Py_Identifier *nameid) { @@ -1790,9 +1772,10 @@ PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals PyObject * PyImport_ReloadModule(PyObject *m) { + _Py_IDENTIFIER(imp); _Py_IDENTIFIER(reload); PyObject *reloaded_module = NULL; - PyObject *imp = _PyImport_GetModuleString("imp"); + PyObject *imp = _PyImport_GetModuleId(&PyId_imp); if (imp == NULL) { imp = PyImport_ImportModule("imp"); if (imp == NULL) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0dba2fd412e67d..b4bb7b3222ec8c 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -42,6 +42,7 @@ _Py_IDENTIFIER(name); _Py_IDENTIFIER(stdin); _Py_IDENTIFIER(stdout); _Py_IDENTIFIER(stderr); +_Py_IDENTIFIER(threading); #ifdef __cplusplus extern "C" { @@ -1911,7 +1912,7 @@ wait_for_thread_shutdown(void) { _Py_IDENTIFIER(_shutdown); PyObject *result; - PyObject *threading = _PyImport_GetModuleString("threading"); + PyObject *threading = _PyImport_GetModuleId(&PyId_threading); if (threading == NULL) { /* threading not imported */ PyErr_Clear(); From 33174f36d7a097f09b0932b9e5e791793d7cf42c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 12:18:40 -0700 Subject: [PATCH 15/30] Use PyDict_CheckExact() for sys.modules in fast case. --- Python/import.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Python/import.c b/Python/import.c index a8d9a5522ff4fd..beba4416d827e2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -313,7 +313,7 @@ PyObject * _PyImport_GetModule(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) { + if (PyDict_CheckExact(modules)) { return PyDict_GetItem(modules, name); } @@ -330,7 +330,7 @@ PyObject * _PyImport_GetModuleWithError(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_Check(modules)) { + if (PyDict_CheckExact(modules)) { return PyDict_GetItemWithError(modules, name); } @@ -377,7 +377,7 @@ PyImport_GetModule(PyObject *name) return NULL; } Py_INCREF(modules); - if (PyDict_Check(modules)) { + if (PyDict_CheckExact(modules)) { m = PyDict_GetItemWithError(modules, name); /* borrowed */ Py_XINCREF(m); } @@ -755,7 +755,7 @@ PyObject * _PyImport_AddModuleObject(PyObject *name, PyObject *modules) { PyObject *m; - if (PyDict_Check(modules)) { + if (PyDict_CheckExact(modules)) { m = PyDict_GetItemWithError(modules, name); } else { From e50e258496d2dc7c312dea49c7b4ba92020e05b6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 12:48:42 -0700 Subject: [PATCH 16/30] Do not use PyMapping_HasKey() with an error set. --- Python/import.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c index beba4416d827e2..d5a39d1b31be2e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -337,7 +337,7 @@ _PyImport_GetModuleWithError(PyObject *name) PyObject *mod = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). - if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); } return mod; @@ -383,8 +383,9 @@ PyImport_GetModule(PyObject *name) } else { m = PyObject_GetItem(modules, name); - if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) + if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); + } } Py_DECREF(modules); return m; @@ -762,8 +763,9 @@ _PyImport_AddModuleObject(PyObject *name, PyObject *modules) m = PyObject_GetItem(modules, name); // For backward-comaptibility we copy the behavior // of PyDict_GetItemWithError(). - if (PyErr_Occurred() && !PyMapping_HasKey(modules, name)) + if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); + } } if (PyErr_Occurred()) { return NULL; From 23cf4934e57691a92af7dcc52e722516425758f3 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 13:00:34 -0700 Subject: [PATCH 17/30] Revert a code order change. --- Python/import.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c index d5a39d1b31be2e..5ab3d3321b5a95 100644 --- a/Python/import.c +++ b/Python/import.c @@ -803,9 +803,10 @@ static void remove_module(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); + if (!PyMapping_HasKey(modules, name)) { + return; + } if (PyMapping_DelItem(modules, name) < 0) { - if (!PyMapping_HasKey(modules, name)) - return; Py_FatalError("import: deleting existing key in" "sys.modules failed"); } From eed5e24d122263c46b0dbafb59db66bd07e0d966 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 4 Sep 2017 14:00:40 -0700 Subject: [PATCH 18/30] Switch the code order back. --- Python/import.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c index 5ab3d3321b5a95..178fe3f21a443c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -803,10 +803,10 @@ static void remove_module(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (!PyMapping_HasKey(modules, name)) { - return; - } if (PyMapping_DelItem(modules, name) < 0) { + if (!PyMapping_HasKey(modules, name)) { + return; + } Py_FatalError("import: deleting existing key in" "sys.modules failed"); } From bcc72a539c695a34501a581d72df9749db97ffe8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 12 Sep 2017 02:36:59 +0000 Subject: [PATCH 19/30] Only use PyDict_* for dicts. --- Python/import.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/Python/import.c b/Python/import.c index 178fe3f21a443c..e46fa4a56ccf7c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -471,21 +471,43 @@ PyImport_Cleanup(void) if (PyErr_Occurred()) \ PyErr_Clear(); \ } +#define CLEAR_MODULE(name, mod) \ + if (PyModule_Check(mod)) { \ + if (Py_VerboseFlag && PyUnicode_Check(name)) \ + PySys_FormatStderr("# cleanup[2] removing %U\n", name); \ + STORE_MODULE_WEAKREF(name, mod); \ + PyObject_SetItem(modules, name, Py_None); \ + } /* Remove all modules from sys.modules, hoping that garbage collection can reclaim most of them. */ - pos = 0; - while (PyDict_Next(modules, &pos, &key, &value)) { - if (PyModule_Check(value)) { - if (Py_VerboseFlag && PyUnicode_Check(key)) - PySys_FormatStderr("# cleanup[2] removing %U\n", key); - STORE_MODULE_WEAKREF(key, value); - PyObject_SetItem(modules, key, Py_None); + if (PyDict_CheckExact(modules)) { + pos = 0; + while (PyDict_Next(modules, &pos, &key, &value)) { + CLEAR_MODULE(key, value); + } + } + else { + PyObject *iterator = PyObject_GetIter(modules); + if (iterator == NULL) { + PyErr_Clear(); + } + else { + while ((value = PyIter_Next(iterator))) { + CLEAR_MODULE(key, value); + } } } /* Clear the modules dict. */ - PyDict_Clear(modules); + if (PyDict_CheckExact(modules)) { + PyDict_Clear(modules); + } + else { + _Py_IDENTIFIER(clear); + if (_PyObject_CallMethodId(modules, &PyId_clear, "") == NULL) + PyErr_Clear(); + } /* Restore the original builtins dict, to ensure that any user data gets cleared. */ dict = PyDict_Copy(interp->builtins); From 981dbd2cbb8495c9e0d49aa908800b2cd50f6183 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 12 Sep 2017 16:44:09 +0000 Subject: [PATCH 20/30] Add a reference while cleaning up. --- Python/import.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/import.c b/Python/import.c index e46fa4a56ccf7c..75f940e27a7e57 100644 --- a/Python/import.c +++ b/Python/import.c @@ -424,6 +424,7 @@ PyImport_Cleanup(void) if (modules == NULL) return; /* Already done */ + Py_INCREF(modules); /* Delete some special variables first. These are common places where user values hide and people complain when their From 0fe1aff2874f5c2efe59dece058051ceb100265e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 14 Sep 2017 14:57:31 +0000 Subject: [PATCH 21/30] Fix _pickle. --- Modules/_pickle.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index bcbe4ac7945169..f09ac2ca89b13d 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1654,9 +1654,7 @@ static PyObject * whichmodule(PyObject *global, PyObject *dotted_path) { PyObject *module_name; - PyObject *modules_dict; - PyObject *module; - Py_ssize_t i; + PyObject *modules; _Py_IDENTIFIER(__module__); _Py_IDENTIFIER(modules); _Py_IDENTIFIER(__main__); @@ -1679,15 +1677,16 @@ whichmodule(PyObject *global, PyObject *dotted_path) assert(module_name == NULL); /* Fallback on walking sys.modules */ - modules_dict = _PySys_GetObjectId(&PyId_modules); - if (modules_dict == NULL) { + modules = _PySys_GetObjectId(&PyId_modules); + if (modules == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); return NULL; } - i = 0; - while (PyDict_Next(modules_dict, &i, &module_name, &module)) { + PyObject *iterator = PyObject_GetIter(modules); + while ((module_name = PyIter_Next(iterator))) { PyObject *candidate; + PyObject *module = PyObject_GetItem(modules, module_name); if (PyUnicode_Check(module_name) && _PyUnicode_EqualToASCIIString(module_name, "__main__")) continue; From d4d9219d59069af71b6d01d7d8ea32443cc922d8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 14 Sep 2017 15:12:31 +0000 Subject: [PATCH 22/30] Fix the NEWS entry. --- .../2017-09-04-10-46-09.bpo-28411.IU9rQL.rst | 3 --- .../2017-09-11-09-11-20.bpo-28411.Ax91lz.rst | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-11-09-11-20.bpo-28411.Ax91lz.rst 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 deleted file mode 100644 index 9f9c839944f0e4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2017-09-04-10-46-09.bpo-28411.IU9rQL.rst +++ /dev/null @@ -1,3 +0,0 @@ -``PyInterpreterState`` has a "modules" field that is copied into -``sys.modules`` during interpreter startup. Adding support for -other mappings than dict gives us some flexibility. diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-11-09-11-20.bpo-28411.Ax91lz.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-11-09-11-20.bpo-28411.Ax91lz.rst new file mode 100644 index 00000000000000..a45f9d86248ecd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-11-09-11-20.bpo-28411.Ax91lz.rst @@ -0,0 +1,4 @@ +Switch to the abstract API when dealing with ``PyInterpreterState.modules``. +This allows later support for all dict subclasses and other Mapping +implementations. Also add a ``PyImport_GetModule()`` function to reduce +a bunch of duplicated code. From 9c3929574c70f349c0d1029700a8e704064bd762 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 01:45:06 +0000 Subject: [PATCH 23/30] Return a borrowed reference from _PyImport_GetModuleWithError(). --- Python/import.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Python/import.c b/Python/import.c index 75f940e27a7e57..ff117b8d65c16c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -322,6 +322,7 @@ _PyImport_GetModule(PyObject *name) if (PyErr_Occurred()) { PyErr_Clear(); } + /* Return a borrowed reference instead of a new one. */ Py_XDECREF(mod); return mod; } @@ -340,6 +341,8 @@ _PyImport_GetModuleWithError(PyObject *name) if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); } + /* Return a borrowed reference instead of a new one. */ + Py_XDECREF(mod); return mod; } From 446acd530af879b37a5cfc9fa2a98caca43ab3f7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 19:12:24 +0000 Subject: [PATCH 24/30] Fix some ref leaks. --- Modules/_pickle.c | 29 ++++++++++++++++++----------- Python/import.c | 6 +++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index f09ac2ca89b13d..721591be60c44c 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1685,29 +1685,39 @@ whichmodule(PyObject *global, PyObject *dotted_path) PyObject *iterator = PyObject_GetIter(modules); while ((module_name = PyIter_Next(iterator))) { - PyObject *candidate; - PyObject *module = PyObject_GetItem(modules, module_name); if (PyUnicode_Check(module_name) && - _PyUnicode_EqualToASCIIString(module_name, "__main__")) + _PyUnicode_EqualToASCIIString(module_name, "__main__")) { + Py_DECREF(module_name); continue; - if (module == Py_None) + } + + PyObject *module = PyObject_GetItem(modules, module_name); + if (module == Py_None) { + Py_DECREF(module_name); continue; + } - candidate = get_deep_attribute(module, dotted_path, NULL); + PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); if (candidate == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + Py_DECREF(module_name); + Py_DECREF(iterator); return NULL; + } PyErr_Clear(); + Py_DECREF(module_name); continue; } if (candidate == global) { - Py_INCREF(module_name); Py_DECREF(candidate); + Py_DECREF(iterator); return module_name; } Py_DECREF(candidate); + Py_DECREF(module_name); } + Py_DECREF(iterator); /* If no module is found, use __main__. */ module_name = _PyUnicode_FromId(&PyId___main__); @@ -6488,11 +6498,8 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, module = PyImport_Import(module_name); if (module == NULL) return NULL; - global = getattribute(module, global_name, self->proto >= 4); - } - else { - global = getattribute(module, global_name, self->proto >= 4); } + global = getattribute(module, global_name, self->proto >= 4); Py_DECREF(module); return global; } diff --git a/Python/import.c b/Python/import.c index ff117b8d65c16c..bf0f5984ee67ab 100644 --- a/Python/import.c +++ b/Python/import.c @@ -497,9 +497,13 @@ PyImport_Cleanup(void) PyErr_Clear(); } else { - while ((value = PyIter_Next(iterator))) { + while ((key = PyIter_Next(iterator))) { + value = PyObject_GetItem(modules, key); CLEAR_MODULE(key, value); + Py_DECREF(value); + Py_DECREF(key); } + Py_DECREF(iterator); } } From 540b99a38d300443d067b1e18130f386a742478a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 20:51:23 +0000 Subject: [PATCH 25/30] Add a fast path for pickle. --- Modules/_pickle.c | 91 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 721591be60c44c..2518826f66ff75 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1654,6 +1654,8 @@ static PyObject * whichmodule(PyObject *global, PyObject *dotted_path) { PyObject *module_name; + PyObject *module = NULL; + Py_ssize_t i; PyObject *modules; _Py_IDENTIFIER(__module__); _Py_IDENTIFIER(modules); @@ -1682,42 +1684,79 @@ whichmodule(PyObject *global, PyObject *dotted_path) PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); return NULL; } + if (PyDict_CheckExact(modules)) { + i = 0; + while (PyDict_Next(modules, &i, &module_name, &module)) { + PyObject *candidate; + if (PyUnicode_Check(module_name) && + _PyUnicode_EqualToASCIIString(module_name, "__main__")) + continue; + if (module == Py_None) + continue; + + candidate = get_deep_attribute(module, dotted_path, NULL); + if (candidate == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; + PyErr_Clear(); + continue; + } - PyObject *iterator = PyObject_GetIter(modules); - while ((module_name = PyIter_Next(iterator))) { - if (PyUnicode_Check(module_name) && - _PyUnicode_EqualToASCIIString(module_name, "__main__")) { - Py_DECREF(module_name); - continue; - } - - PyObject *module = PyObject_GetItem(modules, module_name); - if (module == Py_None) { - Py_DECREF(module_name); - continue; + if (candidate == global) { + Py_INCREF(module_name); + Py_DECREF(candidate); + return module_name; + } + Py_DECREF(candidate); + } + } + else { + PyObject *iterator = PyObject_GetIter(modules); + if (iterator == NULL) { + return NULL; } - - PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); - if (candidate == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + while ((module_name = PyIter_Next(iterator))) { + module = PyObject_GetItem(modules, module_name); + if (module == NULL) { Py_DECREF(module_name); Py_DECREF(iterator); return NULL; } - PyErr_Clear(); - Py_DECREF(module_name); - continue; - } + if (module == Py_None) { + Py_DECREF(module); + Py_DECREF(module_name); + continue; + } + if (PyUnicode_Check(module_name) && + _PyUnicode_EqualToASCIIString(module_name, "__main__")) { + Py_DECREF(module); + Py_DECREF(module_name); + continue; + } - if (candidate == global) { + PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); + if (candidate == NULL) { + Py_DECREF(module); + Py_DECREF(module_name); + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + continue; + } + Py_DECREF(iterator); + return NULL; + } + if (candidate == global) { + Py_DECREF(candidate); + Py_DECREF(module); + Py_DECREF(iterator); + return module_name; + } Py_DECREF(candidate); - Py_DECREF(iterator); - return module_name; + Py_DECREF(module); + Py_DECREF(module_name); } - Py_DECREF(candidate); - Py_DECREF(module_name); + Py_DECREF(iterator); } - Py_DECREF(iterator); /* If no module is found, use __main__. */ module_name = _PyUnicode_FromId(&PyId___main__); From 5f0735b431d4d06359793c782bbd6237f35f22f7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 20:51:55 +0000 Subject: [PATCH 26/30] Ignore errors from PyObject_GetItem(). --- Python/import.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Python/import.c b/Python/import.c index bf0f5984ee67ab..119d7b4fb6125b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -499,6 +499,10 @@ PyImport_Cleanup(void) else { while ((key = PyIter_Next(iterator))) { value = PyObject_GetItem(modules, key); + if (value == NULL) { + PyErr_Clear(); + continue; + } CLEAR_MODULE(key, value); Py_DECREF(value); Py_DECREF(key); From 63beead2f37d4d9abdc1c20fcc7186d149cd3515 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 21:26:07 +0000 Subject: [PATCH 27/30] Factor out _checkmodule. --- Modules/_pickle.c | 80 +++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 2518826f66ff75..0046e1eb396967 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1650,6 +1650,33 @@ getattribute(PyObject *obj, PyObject *name, int allow_qualname) return attr; } +static int +_checkmodule(PyObject *module_name, PyObject *module, + PyObject *global, PyObject *dotted_path) +{ + if (module == Py_None) { + return -1; + } + if (PyUnicode_Check(module_name) && + _PyUnicode_EqualToASCIIString(module_name, "__main__")) { + return -1; + } + + PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); + if (candidate == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + return -1; + } + if (candidate != global) { + Py_DECREF(candidate); + return -1; + } + Py_DECREF(candidate); + return 0; +} + static PyObject * whichmodule(PyObject *global, PyObject *dotted_path) { @@ -1687,27 +1714,13 @@ whichmodule(PyObject *global, PyObject *dotted_path) if (PyDict_CheckExact(modules)) { i = 0; while (PyDict_Next(modules, &i, &module_name, &module)) { - PyObject *candidate; - if (PyUnicode_Check(module_name) && - _PyUnicode_EqualToASCIIString(module_name, "__main__")) - continue; - if (module == Py_None) - continue; - - candidate = get_deep_attribute(module, dotted_path, NULL); - if (candidate == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return NULL; - PyErr_Clear(); - continue; - } - - if (candidate == global) { + if (_checkmodule(module_name, module, global, dotted_path) == 0) { Py_INCREF(module_name); - Py_DECREF(candidate); return module_name; } - Py_DECREF(candidate); + if (PyErr_Occurred()) { + return NULL; + } } } else { @@ -1722,38 +1735,17 @@ whichmodule(PyObject *global, PyObject *dotted_path) Py_DECREF(iterator); return NULL; } - if (module == Py_None) { - Py_DECREF(module); - Py_DECREF(module_name); - continue; - } - if (PyUnicode_Check(module_name) && - _PyUnicode_EqualToASCIIString(module_name, "__main__")) { - Py_DECREF(module); - Py_DECREF(module_name); - continue; - } - - PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); - if (candidate == NULL) { - Py_DECREF(module); - Py_DECREF(module_name); - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - continue; - } - Py_DECREF(iterator); - return NULL; - } - if (candidate == global) { - Py_DECREF(candidate); + if (_checkmodule(module_name, module, global, dotted_path) == 0) { Py_DECREF(module); Py_DECREF(iterator); return module_name; } - Py_DECREF(candidate); Py_DECREF(module); Py_DECREF(module_name); + if (PyErr_Occurred()) { + Py_DECREF(iterator); + return NULL; + } } Py_DECREF(iterator); } From 00f3f24af469ceba80683c781f3e85fc46247f8e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 21:38:13 +0000 Subject: [PATCH 28/30] Drop an extra INCREF. --- Python/import.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/import.c b/Python/import.c index 119d7b4fb6125b..30b0550e07fd24 100644 --- a/Python/import.c +++ b/Python/import.c @@ -427,7 +427,6 @@ PyImport_Cleanup(void) if (modules == NULL) return; /* Already done */ - Py_INCREF(modules); /* Delete some special variables first. These are common places where user values hide and people complain when their From 5a7bba299e18b32441a004081ba3f43a3d6c2260 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 21:58:28 +0000 Subject: [PATCH 29/30] Drop _PyImport_GetModule() and _PyImport_GetModuleWithError(). --- Include/import.h | 2 -- Objects/typeobject.c | 3 +-- Python/_warnings.c | 4 +-- Python/ceval.c | 3 +-- Python/import.c | 60 ++++++-------------------------------------- Python/pylifecycle.c | 1 - Python/sysmodule.c | 1 + 7 files changed, 11 insertions(+), 63 deletions(-) diff --git a/Include/import.h b/Include/import.h index f1276648153874..c30f3ea33942fa 100644 --- a/Include/import.h +++ b/Include/import.h @@ -41,8 +41,6 @@ PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); -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(PyObject *) _PyImport_AddModuleObject(PyObject *name, PyObject *modules); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a06cab72e5ce42..662c493ff2dd29 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3913,9 +3913,8 @@ 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 = _PyImport_GetModuleWithError(copyreg_str); + copyreg_module = PyImport_GetModule(copyreg_str); if (copyreg_module != NULL) { - Py_INCREF(copyreg_module); return copyreg_module; } if (PyErr_Occurred()) { diff --git a/Python/_warnings.c b/Python/_warnings.c index 6dad08068672ee..f6688b040679ad 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -57,11 +57,9 @@ get_warnings_attr(const char *attr, int try_import) } } else { - warnings_module = _PyImport_GetModule(warnings_str); + warnings_module = PyImport_GetModule(warnings_str); if (warnings_module == NULL) return NULL; - - Py_INCREF(warnings_module); } if (!PyObject_HasAttrString(warnings_module, attr)) { diff --git a/Python/ceval.c b/Python/ceval.c index 5dd7cd9f03e35f..82a9776f92ff00 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4935,13 +4935,12 @@ import_from(PyObject *v, PyObject *name) Py_DECREF(pkgname); return NULL; } - x = _PyImport_GetModule(fullmodname); + x = PyImport_GetModule(fullmodname); Py_DECREF(fullmodname); if (x == NULL) { goto error; } Py_DECREF(pkgname); - Py_INCREF(x); return x; error: pkgpath = PyModule_GetFilenameObject(v); diff --git a/Python/import.c b/Python/import.c index 30b0550e07fd24..5e841ca782d2bc 100644 --- a/Python/import.c +++ b/Python/import.c @@ -309,43 +309,6 @@ _PyImport_IsInitialized(PyInterpreterState *interp) return 1; } -PyObject * -_PyImport_GetModule(PyObject *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_CheckExact(modules)) { - return PyDict_GetItem(modules, name); - } - - PyObject *mod = PyObject_GetItem(modules, name); - // For backward-comaptibility we copy the behavior of PyDict_GetItem(). - if (PyErr_Occurred()) { - PyErr_Clear(); - } - /* Return a borrowed reference instead of a new one. */ - Py_XDECREF(mod); - return mod; -} - -PyObject * -_PyImport_GetModuleWithError(PyObject *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_CheckExact(modules)) { - return PyDict_GetItemWithError(modules, name); - } - - PyObject *mod = PyObject_GetItem(modules, name); - // For backward-comaptibility we copy the behavior - // of PyDict_GetItemWithError(). - if (PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - } - /* Return a borrowed reference instead of a new one. */ - Py_XDECREF(mod); - return mod; -} - PyObject * _PyImport_GetModuleId(struct _Py_Identifier *nameid) { @@ -353,7 +316,7 @@ _PyImport_GetModuleId(struct _Py_Identifier *nameid) if (name == NULL) { return NULL; } - return _PyImport_GetModule(name); + return PyImport_GetModule(name); } int @@ -960,7 +923,7 @@ exec_code_in_module(PyObject *name, PyObject *module_dict, PyObject *code_object } Py_DECREF(v); - m = _PyImport_GetModule(name); + m = PyImport_GetModule(name); if (m == NULL) { PyErr_Format(PyExc_ImportError, "Loaded module %R not found in sys.modules", @@ -968,8 +931,6 @@ exec_code_in_module(PyObject *name, PyObject *module_dict, PyObject *code_object return NULL; } - Py_INCREF(m); - return m; } @@ -1668,7 +1629,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, Py_INCREF(abs_name); } - mod = _PyImport_GetModule(abs_name); + mod = PyImport_GetModule(abs_name); if (mod != NULL && mod != Py_None) { _Py_IDENTIFIER(__spec__); _Py_IDENTIFIER(_initializing); @@ -1677,7 +1638,6 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject *spec; int initializing = 0; - Py_INCREF(mod); /* Optimization: only call _bootstrap._lock_unlock_module() if __spec__._initializing is true. NOTE: because of this, initializing must be set *before* @@ -1706,6 +1666,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } } else { + Py_XDECREF(mod); mod = _PyObject_CallMethodIdObjArgs(interp->importlib, &PyId__find_and_load, abs_name, interp->import_func, NULL); @@ -1755,7 +1716,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, goto error; } - final_mod = _PyImport_GetModule(to_return); + final_mod = PyImport_GetModule(to_return); Py_DECREF(to_return); if (final_mod == NULL) { PyErr_Format(PyExc_KeyError, @@ -1763,7 +1724,6 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, to_return); goto error; } - Py_INCREF(final_mod); } } else { @@ -1818,9 +1778,6 @@ PyImport_ReloadModule(PyObject *m) return NULL; } } - else { - Py_INCREF(imp); - } reloaded_module = _PyObject_CallMethodIdObjArgs(imp, &PyId_reload, m, NULL); Py_DECREF(imp); @@ -1900,11 +1857,8 @@ PyImport_Import(PyObject *module_name) goto err; Py_DECREF(r); - r = _PyImport_GetModule(module_name); - if (r != NULL) { - Py_INCREF(r); - } - else if (!PyErr_Occurred()) { + r = PyImport_GetModule(module_name); + if (r == NULL && !PyErr_Occurred()) { PyErr_SetObject(PyExc_KeyError, module_name); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index b4bb7b3222ec8c..7adbc29406e014 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1918,7 +1918,6 @@ wait_for_thread_shutdown(void) PyErr_Clear(); return; } - Py_INCREF(threading); result = _PyObject_CallMethodId(threading, &PyId__shutdown, NULL); if (result == NULL) { PyErr_WriteUnraisable(threading); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 5bde4b7b7028f7..6d2cc96b5ebbdf 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -171,6 +171,7 @@ sys_displayhook(PyObject *self, PyObject *o) PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); return NULL; } + Py_DECREF(builtins); /* Print value except if None */ /* After printing, also assign to '_' */ From 3a73b521187204c37b9d2d863d141b3bbb4811f2 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 15 Sep 2017 22:16:58 +0000 Subject: [PATCH 30/30] tabs to spaces --- Modules/_pickle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 0046e1eb396967..d78517513e8ae1 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1721,8 +1721,8 @@ whichmodule(PyObject *global, PyObject *dotted_path) if (PyErr_Occurred()) { return NULL; } - } - } + } + } else { PyObject *iterator = PyObject_GetIter(modules); if (iterator == NULL) {