2828
2929#include "clinic/_testinternalcapi.c.h"
3030
31+
32+ #define MODULE_NAME "_testinternalcapi"
33+
34+
35+ static PyObject *
36+ _get_current_module (void )
37+ {
38+ // We ensured it was imported in _run_script().
39+ PyObject * name = PyUnicode_FromString (MODULE_NAME );
40+ if (name == NULL ) {
41+ return NULL ;
42+ }
43+ PyObject * mod = PyImport_GetModule (name );
44+ Py_DECREF (name );
45+ if (mod == NULL ) {
46+ return NULL ;
47+ }
48+ assert (mod != Py_None );
49+ return mod ;
50+ }
51+
52+
53+ /* module state *************************************************************/
54+
55+ typedef struct {
56+ PyObject * record_list ;
57+ } module_state ;
58+
59+ static inline module_state *
60+ get_module_state (PyObject * mod )
61+ {
62+ assert (mod != NULL );
63+ module_state * state = PyModule_GetState (mod );
64+ assert (state != NULL );
65+ return state ;
66+ }
67+
68+ static int
69+ traverse_module_state (module_state * state , visitproc visit , void * arg )
70+ {
71+ Py_VISIT (state -> record_list );
72+ return 0 ;
73+ }
74+
75+ static int
76+ clear_module_state (module_state * state )
77+ {
78+ Py_CLEAR (state -> record_list );
79+ return 0 ;
80+ }
81+
82+
83+ /* module functions *********************************************************/
84+
3185/*[clinic input]
3286module _testinternalcapi
3387[clinic start generated code]*/
@@ -496,21 +550,23 @@ decode_locale_ex(PyObject *self, PyObject *args)
496550 return res ;
497551}
498552
499- static PyObject * record_list = NULL ;
500-
501553static PyObject *
502554set_eval_frame_default (PyObject * self , PyObject * Py_UNUSED (args ))
503555{
556+ module_state * state = get_module_state (self );
504557 _PyInterpreterState_SetEvalFrameFunc (PyInterpreterState_Get (), _PyEval_EvalFrameDefault );
505- Py_CLEAR (record_list );
558+ Py_CLEAR (state -> record_list );
506559 Py_RETURN_NONE ;
507560}
508561
509562static PyObject *
510563record_eval (PyThreadState * tstate , struct _PyInterpreterFrame * f , int exc )
511564{
512565 if (PyFunction_Check (f -> f_funcobj )) {
513- PyList_Append (record_list , ((PyFunctionObject * )f -> f_funcobj )-> func_name );
566+ PyObject * module = _get_current_module ();
567+ assert (module != NULL );
568+ module_state * state = get_module_state (module );
569+ PyList_Append (state -> record_list , ((PyFunctionObject * )f -> f_funcobj )-> func_name );
514570 }
515571 return _PyEval_EvalFrameDefault (tstate , f , exc );
516572}
@@ -519,11 +575,12 @@ record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
519575static PyObject *
520576set_eval_frame_record (PyObject * self , PyObject * list )
521577{
578+ module_state * state = get_module_state (self );
522579 if (!PyList_Check (list )) {
523580 PyErr_SetString (PyExc_TypeError , "argument must be a list" );
524581 return NULL ;
525582 }
526- Py_XSETREF (record_list , Py_NewRef (list ));
583+ Py_XSETREF (state -> record_list , Py_NewRef (list ));
527584 _PyInterpreterState_SetEvalFrameFunc (PyInterpreterState_Get (), record_eval );
528585 Py_RETURN_NONE ;
529586}
@@ -613,7 +670,7 @@ get_interp_settings(PyObject *self, PyObject *args)
613670}
614671
615672
616- static PyMethodDef TestMethods [] = {
673+ static PyMethodDef module_functions [] = {
617674 {"get_configs" , get_configs , METH_NOARGS },
618675 {"get_recursion_depth" , get_recursion_depth , METH_NOARGS },
619676 {"test_bswap" , test_bswap , METH_NOARGS },
@@ -638,35 +695,65 @@ static PyMethodDef TestMethods[] = {
638695};
639696
640697
641- static struct PyModuleDef _testcapimodule = {
642- PyModuleDef_HEAD_INIT ,
643- "_testinternalcapi" ,
644- NULL ,
645- -1 ,
646- TestMethods ,
647- NULL ,
648- NULL ,
649- NULL ,
650- NULL
651- };
652-
698+ /* initialization function */
653699
654- PyMODINIT_FUNC
655- PyInit__testinternalcapi ( void )
700+ static int
701+ module_exec ( PyObject * module )
656702{
657- PyObject * module = PyModule_Create (& _testcapimodule );
658- if (module == NULL ) {
659- return NULL ;
660- }
661-
662703 if (PyModule_AddObject (module , "SIZEOF_PYGC_HEAD" ,
663704 PyLong_FromSsize_t (sizeof (PyGC_Head ))) < 0 ) {
664- goto error ;
705+ return 1 ;
665706 }
666707
667- return module ;
708+ return 0 ;
709+ }
668710
669- error :
670- Py_DECREF (module );
671- return NULL ;
711+ static struct PyModuleDef_Slot module_slots [] = {
712+ {Py_mod_exec , module_exec },
713+ {0 , NULL },
714+ };
715+
716+ static int
717+ module_traverse (PyObject * module , visitproc visit , void * arg )
718+ {
719+ module_state * state = get_module_state (module );
720+ assert (state != NULL );
721+ traverse_module_state (state , visit , arg );
722+ return 0 ;
723+ }
724+
725+ static int
726+ module_clear (PyObject * module )
727+ {
728+ module_state * state = get_module_state (module );
729+ assert (state != NULL );
730+ (void )clear_module_state (state );
731+ return 0 ;
732+ }
733+
734+ static void
735+ module_free (void * module )
736+ {
737+ module_state * state = get_module_state (module );
738+ assert (state != NULL );
739+ (void )clear_module_state (state );
740+ }
741+
742+ static struct PyModuleDef _testcapimodule = {
743+ .m_base = PyModuleDef_HEAD_INIT ,
744+ .m_name = MODULE_NAME ,
745+ .m_doc = NULL ,
746+ .m_size = sizeof (module_state ),
747+ .m_methods = module_functions ,
748+ .m_slots = module_slots ,
749+ .m_traverse = module_traverse ,
750+ .m_clear = module_clear ,
751+ .m_free = (freefunc )module_free ,
752+ };
753+
754+
755+ PyMODINIT_FUNC
756+ PyInit__testinternalcapi (void )
757+ {
758+ return PyModuleDef_Init (& _testcapimodule );
672759}
0 commit comments