mirror of https://github.com/python/cpython
gh-94808: cover `PyFunction_GetDefaults` and `PyFunction_SetDefaults` (#98449)
This commit is contained in:
parent
29b391b137
commit
7b24333fff
|
@ -942,6 +942,48 @@ class CAPITest(unittest.TestCase):
|
|||
with self.assertRaises(SystemError):
|
||||
_testcapi.function_get_module(None) # not a function
|
||||
|
||||
def test_function_get_defaults(self):
|
||||
def some(pos_only='p', zero=0, optional=None):
|
||||
pass
|
||||
|
||||
defaults = _testcapi.function_get_defaults(some)
|
||||
self.assertEqual(defaults, ('p', 0, None))
|
||||
self.assertEqual(defaults, some.__defaults__)
|
||||
|
||||
with self.assertRaises(SystemError):
|
||||
_testcapi.function_get_module(None) # not a function
|
||||
|
||||
def test_function_set_defaults(self):
|
||||
def some(pos_only='p', zero=0, optional=None):
|
||||
pass
|
||||
|
||||
old_defaults = ('p', 0, None)
|
||||
self.assertEqual(_testcapi.function_get_defaults(some), old_defaults)
|
||||
self.assertEqual(some.__defaults__, old_defaults)
|
||||
|
||||
with self.assertRaises(SystemError):
|
||||
_testcapi.function_set_defaults(some, 1) # not tuple or None
|
||||
self.assertEqual(_testcapi.function_get_defaults(some), old_defaults)
|
||||
self.assertEqual(some.__defaults__, old_defaults)
|
||||
|
||||
new_defaults = ('q', 1, None)
|
||||
_testcapi.function_set_defaults(some, new_defaults)
|
||||
self.assertEqual(_testcapi.function_get_defaults(some), new_defaults)
|
||||
self.assertEqual(some.__defaults__, new_defaults)
|
||||
|
||||
class tuplesub(tuple): ... # tuple subclasses must work
|
||||
|
||||
new_defaults = tuplesub(((1, 2), ['a', 'b'], None))
|
||||
_testcapi.function_set_defaults(some, new_defaults)
|
||||
self.assertEqual(_testcapi.function_get_defaults(some), new_defaults)
|
||||
self.assertEqual(some.__defaults__, new_defaults)
|
||||
|
||||
# `None` is special, it sets `defaults` to `NULL`,
|
||||
# it needs special handling in `_testcapi`:
|
||||
_testcapi.function_set_defaults(some, None)
|
||||
self.assertEqual(_testcapi.function_get_defaults(some), None)
|
||||
self.assertEqual(some.__defaults__, None)
|
||||
|
||||
|
||||
class TestPendingCalls(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -5788,6 +5788,33 @@ function_get_module(PyObject *self, PyObject *func)
|
|||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
function_get_defaults(PyObject *self, PyObject *func)
|
||||
{
|
||||
PyObject *defaults = PyFunction_GetDefaults(func);
|
||||
if (defaults != NULL) {
|
||||
Py_INCREF(defaults);
|
||||
return defaults;
|
||||
} else if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
} else {
|
||||
Py_RETURN_NONE; // This can happen when `defaults` are set to `None`
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
function_set_defaults(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *func = NULL, *defaults = NULL;
|
||||
if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) {
|
||||
return NULL;
|
||||
}
|
||||
int result = PyFunction_SetDefaults(func, defaults);
|
||||
if (result == -1)
|
||||
return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// type watchers
|
||||
|
||||
|
@ -6202,6 +6229,8 @@ 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},
|
||||
{"function_get_defaults", function_get_defaults, METH_O, NULL},
|
||||
{"function_set_defaults", function_set_defaults, METH_VARARGS, 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},
|
||||
|
|
Loading…
Reference in New Issue