Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 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
5 changes: 5 additions & 0 deletions Doc/c-api/import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the module is not found?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this function returns a borrowed reference. This should be specially emphasized.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be returning a borrowed reference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only code that uses it (_pickle_Unpickler_find_class_impl) is written as PyImport_GetModule returning a borrowed reference.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an omission on my part. I should have moved the Py_DECREF(module) line down.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should document that the function returns NULL if the module is not already imported, but raise an exception and return NULL on exception. I don't think that it's obvious from the current doc.


.. versionadded:: 3.7

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

Expand Down
25 changes: 23 additions & 2 deletions Include/import.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,26 @@ 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_GetModuleString(const char *name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't tink that it's worth it to add _PyImport_GetModuleString(): it's only used 2 times. Please use _PyImport_GetModuleId() with_Py_IDENTIFIER, and remove _PyImport_GetModuleString(). I dislike having N versions of the same function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll drop it.

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 +112,20 @@ 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_FixupExtensionObjectEx(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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can remove a field in the middle of the struct, as that would break the stable ABI (perhaps @zooba can confirm). Instead probably replace it with void *_unused or something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This structure is not a part of the stable ABI.

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