bpo-36124: Add PyInterpreterState.dict. (gh-12132) · python/cpython@d2fdd1f

File tree

5 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

5 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -1026,6 +1026,18 @@ All of the following functions must be called after :c:func:`Py_Initialize`.

10261026

.. versionadded:: 3.7

10271027
10281028
1029+

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

1030+
1031+

Return a dictionary in which interpreter-specific data may be stored.

1032+

If this function returns *NULL* then no exception has been raised and

1033+

the caller should assume no interpreter-specific dict is available.

1034+
1035+

This is not a replacement for :c:func:`PyModule_GetState()`, which

1036+

extensions should use to store interpreter-specific state information.

1037+
1038+

.. versionadded:: 3.8

1039+
1040+
10291041

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

10301042
10311043

Return a dictionary in which extensions can store thread-specific state

Original file line numberDiff line numberDiff line change

@@ -63,6 +63,8 @@ struct _is {

6363

int dlopenflags;

6464

#endif

6565
66+

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

67+
6668

PyObject *builtins_copy;

6769

PyObject *import_func;

6870

/* Initialized to PyEval_EvalFrameDefault(). */

Original file line numberDiff line numberDiff line change

@@ -24,17 +24,23 @@ typedef struct _ts PyThreadState;

2424

/* struct _is is defined in internal/pycore_pystate.h */

2525

typedef struct _is PyInterpreterState;

2626
27-

/* State unique per thread */

28-
2927

PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void);

3028

PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);

3129

PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);

3230
31+

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03080000

32+

/* New in 3.8 */

33+

PyAPI_FUNC(PyObject *) PyInterpreterState_GetDict(PyInterpreterState *);

34+

#endif

35+
3336

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000

3437

/* New in 3.7 */

3538

PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *);

3639

#endif

3740

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000

41+
42+

/* State unique per thread */

43+
3844

/* New in 3.3 */

3945

PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*);

4046

PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*);

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,4 @@

1+

Add a new interpreter-specific dict and expose it in the C-API via

2+

PyInterpreterState_GetDict(). This parallels PyThreadState_GetDict().

3+

However, extension modules should continue using PyModule_GetState() for

4+

their own internal per-interpreter state.

Original file line numberDiff line numberDiff line change

@@ -224,6 +224,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)

224224

Py_CLEAR(interp->builtins_copy);

225225

Py_CLEAR(interp->importlib);

226226

Py_CLEAR(interp->import_func);

227+

Py_CLEAR(interp->dict);

227228

#ifdef HAVE_FORK

228229

Py_CLEAR(interp->before_forkers);

229230

Py_CLEAR(interp->after_forkers_parent);

@@ -462,6 +463,19 @@ _PyInterpreterState_GetMainModule(PyInterpreterState *interp)

462463

return PyMapping_GetItemString(interp->modules, "__main__");

463464

}

464465
466+

PyObject *

467+

PyInterpreterState_GetDict(PyInterpreterState *interp)

468+

{

469+

if (interp->dict == NULL) {

470+

interp->dict = PyDict_New();

471+

if (interp->dict == NULL) {

472+

PyErr_Clear();

473+

}

474+

}

475+

/* Returning NULL means no per-interpreter dict is available. */

476+

return interp->dict;

477+

}

478+
465479

/* Default implementation for _PyThreadState_GetFrame */

466480

static struct _frame *

467481

threadstate_getframe(PyThreadState *self)