Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,18 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. versionadded:: 3.7


.. c:function:: PyObject* PyInterpreterState_GetDict(PyInterpreterState *interp)

Return a dictionary in which interpreter-specific data may be stored.
If this function returns *NULL* then no exception has been raised and
the caller should assume no interpreter-specific dict is available.

This is not a replacement for :c:func:`PyModule_GetState()`, which
extensions should use to store interpreter-specific state information.

.. versionadded:: 3.8


.. c:function:: PyObject* PyThreadState_GetDict()

Return a dictionary in which extensions can store thread-specific state
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ struct _is {
int dlopenflags;
#endif

PyObject *dict; /* Stores per-interpreter state */

PyObject *builtins_copy;
PyObject *import_func;
/* Initialized to PyEval_EvalFrameDefault(). */
Expand Down
10 changes: 8 additions & 2 deletions Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ typedef struct _ts PyThreadState;
/* struct _is is defined in internal/pycore_pystate.h */
typedef struct _is PyInterpreterState;

/* State unique per thread */

PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void);
PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);
PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03080000
/* New in 3.8 */
PyAPI_FUNC(PyObject *) PyInterpreterState_GetDict(PyInterpreterState *);
#endif

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
/* New in 3.7 */
PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *);
#endif
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000

/* State unique per thread */

/* New in 3.3 */
PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*);
PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add a new interpreter-specific dict and expose it in the C-API via
PyInterpreterState_GetDict(). This parallels PyThreadState_GetDict().
However, extension modules should continue using PyModule_GetState() for
their own internal per-interpreter state.
14 changes: 14 additions & 0 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
Py_CLEAR(interp->builtins_copy);
Py_CLEAR(interp->importlib);
Py_CLEAR(interp->import_func);
Py_CLEAR(interp->dict);
#ifdef HAVE_FORK
Py_CLEAR(interp->before_forkers);
Py_CLEAR(interp->after_forkers_parent);
Expand Down Expand Up @@ -462,6 +463,19 @@ _PyInterpreterState_GetMainModule(PyInterpreterState *interp)
return PyMapping_GetItemString(interp->modules, "__main__");
}

PyObject *
PyInterpreterState_GetDict(PyInterpreterState *interp)
{
if (interp->dict == NULL) {
interp->dict = PyDict_New();
if (interp->dict == NULL) {
PyErr_Clear();
}
}
/* Returning NULL means no per-interpreter dict is available. */
return interp->dict;
}

/* Default implementation for _PyThreadState_GetFrame */
static struct _frame *
threadstate_getframe(PyThreadState *self)
Expand Down