Skip to content

Commit 0fdc7d7

Browse files
committed
Trigger events when {kw}defaults are changed via the C-API
1 parent 9d3496f commit 0fdc7d7

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

Lib/test/test_capi.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
_add_func_watcher,
4747
_allocate_too_many_func_watchers,
4848
_clear_func_watcher,
49+
_set_func_defaults_via_capi,
50+
_set_func_kwdefaults_via_capi,
4951
)
5052

5153
import _testinternalcapi
@@ -1595,10 +1597,18 @@ def myfunc():
15951597
myfunc.__defaults__ = new_defaults
15961598
self.assertIn((PYFUNC_EVENT_MODIFY_DEFAULTS, myfunc, new_defaults), events)
15971599

1600+
new_defaults = (456,)
1601+
_set_func_defaults_via_capi(myfunc, new_defaults)
1602+
self.assertIn((PYFUNC_EVENT_MODIFY_DEFAULTS, myfunc, new_defaults), events)
1603+
15981604
new_kwdefaults = {"self": 123}
15991605
myfunc.__kwdefaults__ = new_kwdefaults
16001606
self.assertIn((PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
16011607

1608+
new_kwdefaults = {"self": 456}
1609+
_set_func_kwdefaults_via_capi(myfunc, new_kwdefaults)
1610+
self.assertIn((PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
1611+
16021612
# Clear events reference to func
16031613
events = []
16041614
del myfunc

Modules/_testcapi/func_events.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,40 @@ allocate_too_many_watchers(PyObject *self, PyObject *args)
190190
Py_RETURN_NONE;
191191
}
192192

193+
static PyObject *
194+
set_defaults(PyObject *self, PyObject *args)
195+
{
196+
PyObject *func = NULL;
197+
PyObject *defaults = NULL;
198+
if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) {
199+
return NULL;
200+
}
201+
if (PyFunction_SetDefaults(func, defaults) < 0) {
202+
return NULL;
203+
}
204+
Py_RETURN_NONE;
205+
}
206+
207+
static PyObject *
208+
set_kwdefaults(PyObject *self, PyObject *args)
209+
{
210+
PyObject *func = NULL;
211+
PyObject *kwdefaults = NULL;
212+
if (!PyArg_ParseTuple(args, "OO", &func, &kwdefaults)) {
213+
return NULL;
214+
}
215+
if (PyFunction_SetKwDefaults(func, kwdefaults) < 0) {
216+
return NULL;
217+
}
218+
Py_RETURN_NONE;
219+
}
220+
193221
static PyMethodDef TestMethods[] = {
194222
{"_add_func_watcher", add_watcher, METH_O},
195223
{"_clear_func_watcher", clear_watcher, METH_O},
196224
{"_allocate_too_many_func_watchers", allocate_too_many_watchers, METH_NOARGS},
225+
{"_set_func_defaults_via_capi", set_defaults, METH_VARARGS},
226+
{"_set_func_kwdefaults_via_capi", set_kwdefaults, METH_VARARGS},
197227
{NULL},
198228
};
199229

Objects/funcobject.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,8 @@ PyFunction_SetDefaults(PyObject *op, PyObject *defaults)
255255
PyErr_SetString(PyExc_SystemError, "non-tuple default args");
256256
return -1;
257257
}
258-
handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS, op, NULL);
258+
handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS,
259+
(PyFunctionObject *) op, defaults);
259260
((PyFunctionObject *)op)->func_version = 0;
260261
Py_XSETREF(((PyFunctionObject *)op)->func_defaults, defaults);
261262
return 0;
@@ -296,7 +297,8 @@ PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults)
296297
"non-dict keyword only default args");
297298
return -1;
298299
}
299-
handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS, op, NULL);
300+
handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS,
301+
(PyFunctionObject *) op, defaults);
300302
((PyFunctionObject *)op)->func_version = 0;
301303
Py_XSETREF(((PyFunctionObject *)op)->func_kwdefaults, defaults);
302304
return 0;

0 commit comments

Comments
 (0)