mirror of https://github.com/python/cpython
GH-100997: Implement Multi-Phase Init for the _testinternalcapi Module (gh-100998)
_testinternalcapi is an internal module used for testing. https://github.com/python/cpython/issues/100997
This commit is contained in:
parent
005e69403d
commit
b511d3512b
|
@ -28,6 +28,60 @@
|
|||
|
||||
#include "clinic/_testinternalcapi.c.h"
|
||||
|
||||
|
||||
#define MODULE_NAME "_testinternalcapi"
|
||||
|
||||
|
||||
static PyObject *
|
||||
_get_current_module(void)
|
||||
{
|
||||
// We ensured it was imported in _run_script().
|
||||
PyObject *name = PyUnicode_FromString(MODULE_NAME);
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *mod = PyImport_GetModule(name);
|
||||
Py_DECREF(name);
|
||||
if (mod == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
assert(mod != Py_None);
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
||||
/* module state *************************************************************/
|
||||
|
||||
typedef struct {
|
||||
PyObject *record_list;
|
||||
} module_state;
|
||||
|
||||
static inline module_state *
|
||||
get_module_state(PyObject *mod)
|
||||
{
|
||||
assert(mod != NULL);
|
||||
module_state *state = PyModule_GetState(mod);
|
||||
assert(state != NULL);
|
||||
return state;
|
||||
}
|
||||
|
||||
static int
|
||||
traverse_module_state(module_state *state, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(state->record_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
clear_module_state(module_state *state)
|
||||
{
|
||||
Py_CLEAR(state->record_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* module functions *********************************************************/
|
||||
|
||||
/*[clinic input]
|
||||
module _testinternalcapi
|
||||
[clinic start generated code]*/
|
||||
|
@ -496,13 +550,12 @@ decode_locale_ex(PyObject *self, PyObject *args)
|
|||
return res;
|
||||
}
|
||||
|
||||
static PyObject *record_list = NULL;
|
||||
|
||||
static PyObject *
|
||||
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
|
||||
{
|
||||
module_state *state = get_module_state(self);
|
||||
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
|
||||
Py_CLEAR(record_list);
|
||||
Py_CLEAR(state->record_list);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
@ -510,7 +563,10 @@ static PyObject *
|
|||
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
|
||||
{
|
||||
if (PyFunction_Check(f->f_funcobj)) {
|
||||
PyList_Append(record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
|
||||
PyObject *module = _get_current_module();
|
||||
assert(module != NULL);
|
||||
module_state *state = get_module_state(module);
|
||||
PyList_Append(state->record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
|
||||
}
|
||||
return _PyEval_EvalFrameDefault(tstate, f, exc);
|
||||
}
|
||||
|
@ -519,11 +575,12 @@ record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
|
|||
static PyObject *
|
||||
set_eval_frame_record(PyObject *self, PyObject *list)
|
||||
{
|
||||
module_state *state = get_module_state(self);
|
||||
if (!PyList_Check(list)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a list");
|
||||
return NULL;
|
||||
}
|
||||
Py_XSETREF(record_list, Py_NewRef(list));
|
||||
Py_XSETREF(state->record_list, Py_NewRef(list));
|
||||
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -613,7 +670,7 @@ get_interp_settings(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
|
||||
static PyMethodDef TestMethods[] = {
|
||||
static PyMethodDef module_functions[] = {
|
||||
{"get_configs", get_configs, METH_NOARGS},
|
||||
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
|
||||
{"test_bswap", test_bswap, METH_NOARGS},
|
||||
|
@ -638,35 +695,65 @@ static PyMethodDef TestMethods[] = {
|
|||
};
|
||||
|
||||
|
||||
/* initialization function */
|
||||
|
||||
static int
|
||||
module_exec(PyObject *module)
|
||||
{
|
||||
if (PyModule_AddObject(module, "SIZEOF_PYGC_HEAD",
|
||||
PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct PyModuleDef_Slot module_slots[] = {
|
||||
{Py_mod_exec, module_exec},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
static int
|
||||
module_traverse(PyObject *module, visitproc visit, void *arg)
|
||||
{
|
||||
module_state *state = get_module_state(module);
|
||||
assert(state != NULL);
|
||||
traverse_module_state(state, visit, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
module_clear(PyObject *module)
|
||||
{
|
||||
module_state *state = get_module_state(module);
|
||||
assert(state != NULL);
|
||||
(void)clear_module_state(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
module_free(void *module)
|
||||
{
|
||||
module_state *state = get_module_state(module);
|
||||
assert(state != NULL);
|
||||
(void)clear_module_state(state);
|
||||
}
|
||||
|
||||
static struct PyModuleDef _testcapimodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_testinternalcapi",
|
||||
NULL,
|
||||
-1,
|
||||
TestMethods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
.m_base = PyModuleDef_HEAD_INIT,
|
||||
.m_name = MODULE_NAME,
|
||||
.m_doc = NULL,
|
||||
.m_size = sizeof(module_state),
|
||||
.m_methods = module_functions,
|
||||
.m_slots = module_slots,
|
||||
.m_traverse = module_traverse,
|
||||
.m_clear = module_clear,
|
||||
.m_free = (freefunc)module_free,
|
||||
};
|
||||
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__testinternalcapi(void)
|
||||
{
|
||||
PyObject *module = PyModule_Create(&_testcapimodule);
|
||||
if (module == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyModule_AddObject(module, "SIZEOF_PYGC_HEAD",
|
||||
PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return module;
|
||||
|
||||
error:
|
||||
Py_DECREF(module);
|
||||
return NULL;
|
||||
return PyModuleDef_Init(&_testcapimodule);
|
||||
}
|
||||
|
|
|
@ -523,7 +523,6 @@ Modules/_asynciomodule.c - all_tasks -
|
|||
Modules/_asynciomodule.c - current_tasks -
|
||||
Modules/_asynciomodule.c - iscoroutine_typecache -
|
||||
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
|
||||
Modules/_testinternalcapi.c - record_list -
|
||||
Modules/_tkinter.c - tcl_lock -
|
||||
Modules/_tkinter.c - excInCmd -
|
||||
Modules/_tkinter.c - valInCmd -
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
|
@ -483,8 +483,6 @@ Modules/_testcapimodule.c - g_type_watchers_installed -
|
|||
Modules/_testimportmultiple.c - _barmodule -
|
||||
Modules/_testimportmultiple.c - _foomodule -
|
||||
Modules/_testimportmultiple.c - _testimportmultiple -
|
||||
Modules/_testinternalcapi.c - TestMethods -
|
||||
Modules/_testinternalcapi.c - _testcapimodule -
|
||||
Modules/_testmultiphase.c - Example_Type_slots -
|
||||
Modules/_testmultiphase.c - Example_Type_spec -
|
||||
Modules/_testmultiphase.c - Example_methods -
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Reference in New Issue