mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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
3 changed files with 117 additions and 33 deletions
|
@ -28,6 +28,60 @@
|
||||||
|
|
||||||
#include "clinic/_testinternalcapi.c.h"
|
#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]
|
/*[clinic input]
|
||||||
module _testinternalcapi
|
module _testinternalcapi
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
@ -496,13 +550,12 @@ decode_locale_ex(PyObject *self, PyObject *args)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *record_list = NULL;
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
|
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
{
|
{
|
||||||
|
module_state *state = get_module_state(self);
|
||||||
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
|
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
|
||||||
Py_CLEAR(record_list);
|
Py_CLEAR(state->record_list);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +563,10 @@ static PyObject *
|
||||||
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
|
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
|
||||||
{
|
{
|
||||||
if (PyFunction_Check(f->f_funcobj)) {
|
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);
|
return _PyEval_EvalFrameDefault(tstate, f, exc);
|
||||||
}
|
}
|
||||||
|
@ -519,11 +575,12 @@ record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_eval_frame_record(PyObject *self, PyObject *list)
|
set_eval_frame_record(PyObject *self, PyObject *list)
|
||||||
{
|
{
|
||||||
|
module_state *state = get_module_state(self);
|
||||||
if (!PyList_Check(list)) {
|
if (!PyList_Check(list)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "argument must be a list");
|
PyErr_SetString(PyExc_TypeError, "argument must be a list");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_XSETREF(record_list, Py_NewRef(list));
|
Py_XSETREF(state->record_list, Py_NewRef(list));
|
||||||
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
|
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
|
||||||
Py_RETURN_NONE;
|
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_configs", get_configs, METH_NOARGS},
|
||||||
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
|
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
|
||||||
{"test_bswap", test_bswap, 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 = {
|
static struct PyModuleDef _testcapimodule = {
|
||||||
PyModuleDef_HEAD_INIT,
|
.m_base = PyModuleDef_HEAD_INIT,
|
||||||
"_testinternalcapi",
|
.m_name = MODULE_NAME,
|
||||||
NULL,
|
.m_doc = NULL,
|
||||||
-1,
|
.m_size = sizeof(module_state),
|
||||||
TestMethods,
|
.m_methods = module_functions,
|
||||||
NULL,
|
.m_slots = module_slots,
|
||||||
NULL,
|
.m_traverse = module_traverse,
|
||||||
NULL,
|
.m_clear = module_clear,
|
||||||
NULL
|
.m_free = (freefunc)module_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
PyInit__testinternalcapi(void)
|
PyInit__testinternalcapi(void)
|
||||||
{
|
{
|
||||||
PyObject *module = PyModule_Create(&_testcapimodule);
|
return PyModuleDef_Init(&_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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,7 +523,6 @@ Modules/_asynciomodule.c - all_tasks -
|
||||||
Modules/_asynciomodule.c - current_tasks -
|
Modules/_asynciomodule.c - current_tasks -
|
||||||
Modules/_asynciomodule.c - iscoroutine_typecache -
|
Modules/_asynciomodule.c - iscoroutine_typecache -
|
||||||
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
|
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
|
||||||
Modules/_testinternalcapi.c - record_list -
|
|
||||||
Modules/_tkinter.c - tcl_lock -
|
Modules/_tkinter.c - tcl_lock -
|
||||||
Modules/_tkinter.c - excInCmd -
|
Modules/_tkinter.c - excInCmd -
|
||||||
Modules/_tkinter.c - valInCmd -
|
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 - _barmodule -
|
||||||
Modules/_testimportmultiple.c - _foomodule -
|
Modules/_testimportmultiple.c - _foomodule -
|
||||||
Modules/_testimportmultiple.c - _testimportmultiple -
|
Modules/_testimportmultiple.c - _testimportmultiple -
|
||||||
Modules/_testinternalcapi.c - TestMethods -
|
|
||||||
Modules/_testinternalcapi.c - _testcapimodule -
|
|
||||||
Modules/_testmultiphase.c - Example_Type_slots -
|
Modules/_testmultiphase.c - Example_Type_slots -
|
||||||
Modules/_testmultiphase.c - Example_Type_spec -
|
Modules/_testmultiphase.c - Example_Type_spec -
|
||||||
Modules/_testmultiphase.c - Example_methods -
|
Modules/_testmultiphase.c - Example_methods -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Add table
Add a link
Reference in a new issue