mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
gh-91051: allow setting a callback hook on PyType_Modified (GH-97875)
This commit is contained in:
parent
8367ca136e
commit
82ccbf69a8
9 changed files with 462 additions and 5 deletions
|
|
@ -5695,6 +5695,128 @@ function_get_module(PyObject *self, PyObject *func)
|
|||
}
|
||||
|
||||
|
||||
// type watchers
|
||||
|
||||
static PyObject *g_type_modified_events;
|
||||
static int g_type_watchers_installed;
|
||||
|
||||
static int
|
||||
type_modified_callback(PyTypeObject *type)
|
||||
{
|
||||
assert(PyList_Check(g_type_modified_events));
|
||||
if(PyList_Append(g_type_modified_events, (PyObject *)type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
type_modified_callback_wrap(PyTypeObject *type)
|
||||
{
|
||||
assert(PyList_Check(g_type_modified_events));
|
||||
PyObject *list = PyList_New(0);
|
||||
if (!list) {
|
||||
return -1;
|
||||
}
|
||||
if (PyList_Append(list, (PyObject *)type) < 0) {
|
||||
Py_DECREF(list);
|
||||
return -1;
|
||||
}
|
||||
if (PyList_Append(g_type_modified_events, list) < 0) {
|
||||
Py_DECREF(list);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
type_modified_callback_error(PyTypeObject *type)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "boom!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
add_type_watcher(PyObject *self, PyObject *kind)
|
||||
{
|
||||
int watcher_id;
|
||||
assert(PyLong_Check(kind));
|
||||
long kind_l = PyLong_AsLong(kind);
|
||||
if (kind_l == 2) {
|
||||
watcher_id = PyType_AddWatcher(type_modified_callback_wrap);
|
||||
} else if (kind_l == 1) {
|
||||
watcher_id = PyType_AddWatcher(type_modified_callback_error);
|
||||
} else {
|
||||
watcher_id = PyType_AddWatcher(type_modified_callback);
|
||||
}
|
||||
if (watcher_id < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!g_type_watchers_installed) {
|
||||
assert(!g_type_modified_events);
|
||||
if (!(g_type_modified_events = PyList_New(0))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
g_type_watchers_installed++;
|
||||
return PyLong_FromLong(watcher_id);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
clear_type_watcher(PyObject *self, PyObject *watcher_id)
|
||||
{
|
||||
if (PyType_ClearWatcher(PyLong_AsLong(watcher_id))) {
|
||||
return NULL;
|
||||
}
|
||||
g_type_watchers_installed--;
|
||||
if (!g_type_watchers_installed) {
|
||||
assert(g_type_modified_events);
|
||||
Py_CLEAR(g_type_modified_events);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_type_modified_events(PyObject *self, PyObject *Py_UNUSED(args))
|
||||
{
|
||||
if (!g_type_modified_events) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "no watchers active");
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(g_type_modified_events);
|
||||
return g_type_modified_events;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
watch_type(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *type;
|
||||
int watcher_id;
|
||||
if (!PyArg_ParseTuple(args, "iO", &watcher_id, &type)) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Watch(watcher_id, type)) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
unwatch_type(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *type;
|
||||
int watcher_id;
|
||||
if (!PyArg_ParseTuple(args, "iO", &watcher_id, &type)) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Unwatch(watcher_id, type)) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
|
||||
static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*);
|
||||
static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*);
|
||||
|
|
@ -5981,6 +6103,11 @@ static PyMethodDef TestMethods[] = {
|
|||
{"function_get_code", function_get_code, METH_O, NULL},
|
||||
{"function_get_globals", function_get_globals, METH_O, NULL},
|
||||
{"function_get_module", function_get_module, METH_O, NULL},
|
||||
{"add_type_watcher", add_type_watcher, METH_O, NULL},
|
||||
{"clear_type_watcher", clear_type_watcher, METH_O, NULL},
|
||||
{"watch_type", watch_type, METH_VARARGS, NULL},
|
||||
{"unwatch_type", unwatch_type, METH_VARARGS, NULL},
|
||||
{"get_type_modified_events", get_type_modified_events, METH_NOARGS, NULL},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue