diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 32587be4c9e..3be7fe3d8e4 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -113,8 +113,28 @@ There are only a few functions special to module objects. Return a pointer to the :c:type:`PyModuleDef` struct from which the module was created, or *NULL* if the module wasn't created with - :c:func:`PyModule_Create`. + :c:func:`PyModule_Create`.i +.. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) + + Returns the module object that was created from *def* for the current interpreter. + This method requires that the module object has been attached to the interpreter state with + :c:func:`PyState_AddModule` beforehand. In case the corresponding module object is not + found or has not been attached to the interpreter state yet, it returns NULL. + +.. c:function:: int PyState_AddModule(PyModuleDef *def, PyObject *module) + + Attaches the module object passed to the function to the interpreter state. This allows + the module object to be accessible via + :c:func:`PyState_FindModule`. + + .. versionadded:: 3.3 + +.. c:function:: int PyState_RemoveModule(PyModuleDef *def, PyObject *module) + + Removes the module object created from *def* from the interpreter state. + + .. versionadded:: 3.3 Initializing C modules ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Include/pystate.h b/Include/pystate.h index 62724928f59..25c2faae925 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -124,6 +124,11 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* New in 3.3 */ +PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*); +PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*); +#endif PyAPI_FUNC(PyObject*) PyState_FindModule(struct PyModuleDef*); PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *); diff --git a/Misc/NEWS b/Misc/NEWS index c32697d5e4b..1149ecf3e1d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.3.0 Beta 1? Core and Builtins ----------------- +- Issue #15042: Add PyState_AddModule and PyState_RemoveModule. Add version + guard for Py_LIMITED_API additions. Patch by Robin Schreiber. + - Issue #10053: Don't close FDs when FileIO.__init__ fails. Loosely based on the work by Hirokazu Yamamoto. @@ -154,6 +157,9 @@ Extension Modules Documentation ------------- +- Issue #15081: Document PyState_FindModule. + Patch by Robin Schreiber. + - Issue #14814: Added first draft of ipaddress module API reference Tests diff --git a/PC/python3.def b/PC/python3.def index 54b288f3289..0c9e25ced10 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -471,6 +471,8 @@ EXPORTS PySlice_Type=python33.PySlice_Type DATA PySortWrapper_Type=python33.PySortWrapper_Type DATA PyState_FindModule=python33.PyState_FindModule + PyState_AddModule=python33.PyState_AddModule + PyState_RemoveModule=python33.PyState_RemoveModule PyStructSequence_GetItem=python33.PyStructSequence_GetItem PyStructSequence_New=python33.PyStructSequence_New PyStructSequence_NewType=python33.PyStructSequence_NewType diff --git a/Python/pystate.c b/Python/pystate.c index a0489ad08a2..cf08a2b4c63 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -239,9 +239,9 @@ _PyThreadState_Init(PyThreadState *tstate) } PyObject* -PyState_FindModule(struct PyModuleDef* m) +PyState_FindModule(struct PyModuleDef* module) { - Py_ssize_t index = m->m_base.m_index; + Py_ssize_t index = module->m_base.m_index; PyInterpreterState *state = PyThreadState_GET()->interp; PyObject *res; if (index == 0) @@ -273,6 +273,47 @@ _PyState_AddModule(PyObject* module, struct PyModuleDef* def) def->m_base.m_index, module); } +int +PyState_AddModule(PyObject* module, struct PyModuleDef* def) +{ + Py_ssize_t index; + PyInterpreterState *state = PyThreadState_GET()->interp; + if (!def) { + Py_FatalError("PyState_AddModule: Module Definition is NULL"); + return -1; + } + index = def->m_base.m_index; + if (state->modules_by_index) { + if(PyList_GET_SIZE(state->modules_by_index) >= index) { + if(module == PyList_GET_ITEM(state->modules_by_index, index)) { + Py_FatalError("PyState_AddModule: Module already added!"); + return -1; + } + } + } + return _PyState_AddModule(module, def); +} + +int +PyState_RemoveModule(struct PyModuleDef* def) +{ + Py_ssize_t index = def->m_base.m_index; + PyInterpreterState *state = PyThreadState_GET()->interp; + if (index == 0) { + Py_FatalError("PyState_RemoveModule: Module index invalid."); + return -1; + } + if (state->modules_by_index == NULL) { + Py_FatalError("PyState_RemoveModule: Interpreters module-list not acessible."); + return -1; + } + if (index > PyList_GET_SIZE(state->modules_by_index)) { + Py_FatalError("PyState_RemoveModule: Module index out of bounds."); + return -1; + } + return PyList_SetItem(state->modules_by_index, index, Py_None); +} + void PyThreadState_Clear(PyThreadState *tstate) {