mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-94808: add tests covering PyFunction_GetKwDefaults
and PyFunction_SetKwDefaults
(GH-98809)
This commit is contained in:
parent
c5c40773cb
commit
317acb8038
2 changed files with 124 additions and 3 deletions
|
@ -1038,7 +1038,14 @@ class CAPITest(unittest.TestCase):
|
||||||
_testcapi.function_get_module(None) # not a function
|
_testcapi.function_get_module(None) # not a function
|
||||||
|
|
||||||
def test_function_get_defaults(self):
|
def test_function_get_defaults(self):
|
||||||
def some(pos_only='p', zero=0, optional=None):
|
def some(
|
||||||
|
pos_only1, pos_only2='p',
|
||||||
|
/,
|
||||||
|
zero=0, optional=None,
|
||||||
|
*,
|
||||||
|
kw1,
|
||||||
|
kw2=True,
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
defaults = _testcapi.function_get_defaults(some)
|
defaults = _testcapi.function_get_defaults(some)
|
||||||
|
@ -1046,10 +1053,17 @@ class CAPITest(unittest.TestCase):
|
||||||
self.assertEqual(defaults, some.__defaults__)
|
self.assertEqual(defaults, some.__defaults__)
|
||||||
|
|
||||||
with self.assertRaises(SystemError):
|
with self.assertRaises(SystemError):
|
||||||
_testcapi.function_get_module(None) # not a function
|
_testcapi.function_get_defaults(None) # not a function
|
||||||
|
|
||||||
def test_function_set_defaults(self):
|
def test_function_set_defaults(self):
|
||||||
def some(pos_only='p', zero=0, optional=None):
|
def some(
|
||||||
|
pos_only1, pos_only2='p',
|
||||||
|
/,
|
||||||
|
zero=0, optional=None,
|
||||||
|
*,
|
||||||
|
kw1,
|
||||||
|
kw2=True,
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
old_defaults = ('p', 0, None)
|
old_defaults = ('p', 0, None)
|
||||||
|
@ -1061,11 +1075,22 @@ class CAPITest(unittest.TestCase):
|
||||||
self.assertEqual(_testcapi.function_get_defaults(some), old_defaults)
|
self.assertEqual(_testcapi.function_get_defaults(some), old_defaults)
|
||||||
self.assertEqual(some.__defaults__, old_defaults)
|
self.assertEqual(some.__defaults__, old_defaults)
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
_testcapi.function_set_defaults(1, ()) # not a function
|
||||||
|
self.assertEqual(_testcapi.function_get_defaults(some), old_defaults)
|
||||||
|
self.assertEqual(some.__defaults__, old_defaults)
|
||||||
|
|
||||||
new_defaults = ('q', 1, None)
|
new_defaults = ('q', 1, None)
|
||||||
_testcapi.function_set_defaults(some, new_defaults)
|
_testcapi.function_set_defaults(some, new_defaults)
|
||||||
self.assertEqual(_testcapi.function_get_defaults(some), new_defaults)
|
self.assertEqual(_testcapi.function_get_defaults(some), new_defaults)
|
||||||
self.assertEqual(some.__defaults__, new_defaults)
|
self.assertEqual(some.__defaults__, new_defaults)
|
||||||
|
|
||||||
|
# Empty tuple is fine:
|
||||||
|
new_defaults = ()
|
||||||
|
_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
|
class tuplesub(tuple): ... # tuple subclasses must work
|
||||||
|
|
||||||
new_defaults = tuplesub(((1, 2), ['a', 'b'], None))
|
new_defaults = tuplesub(((1, 2), ['a', 'b'], None))
|
||||||
|
@ -1079,6 +1104,73 @@ class CAPITest(unittest.TestCase):
|
||||||
self.assertEqual(_testcapi.function_get_defaults(some), None)
|
self.assertEqual(_testcapi.function_get_defaults(some), None)
|
||||||
self.assertEqual(some.__defaults__, None)
|
self.assertEqual(some.__defaults__, None)
|
||||||
|
|
||||||
|
def test_function_get_kw_defaults(self):
|
||||||
|
def some(
|
||||||
|
pos_only1, pos_only2='p',
|
||||||
|
/,
|
||||||
|
zero=0, optional=None,
|
||||||
|
*,
|
||||||
|
kw1,
|
||||||
|
kw2=True,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
defaults = _testcapi.function_get_kw_defaults(some)
|
||||||
|
self.assertEqual(defaults, {'kw2': True})
|
||||||
|
self.assertEqual(defaults, some.__kwdefaults__)
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
_testcapi.function_get_kw_defaults(None) # not a function
|
||||||
|
|
||||||
|
def test_function_set_kw_defaults(self):
|
||||||
|
def some(
|
||||||
|
pos_only1, pos_only2='p',
|
||||||
|
/,
|
||||||
|
zero=0, optional=None,
|
||||||
|
*,
|
||||||
|
kw1,
|
||||||
|
kw2=True,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
old_defaults = {'kw2': True}
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, old_defaults)
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
_testcapi.function_set_kw_defaults(some, 1) # not dict or None
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, old_defaults)
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
_testcapi.function_set_kw_defaults(1, {}) # not a function
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, old_defaults)
|
||||||
|
|
||||||
|
new_defaults = {'kw2': (1, 2, 3)}
|
||||||
|
_testcapi.function_set_kw_defaults(some, new_defaults)
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, new_defaults)
|
||||||
|
|
||||||
|
# Empty dict is fine:
|
||||||
|
new_defaults = {}
|
||||||
|
_testcapi.function_set_kw_defaults(some, new_defaults)
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, new_defaults)
|
||||||
|
|
||||||
|
class dictsub(dict): ... # dict subclasses must work
|
||||||
|
|
||||||
|
new_defaults = dictsub({'kw2': None})
|
||||||
|
_testcapi.function_set_kw_defaults(some, new_defaults)
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults)
|
||||||
|
self.assertEqual(some.__kwdefaults__, new_defaults)
|
||||||
|
|
||||||
|
# `None` is special, it sets `kwdefaults` to `NULL`,
|
||||||
|
# it needs special handling in `_testcapi`:
|
||||||
|
_testcapi.function_set_kw_defaults(some, None)
|
||||||
|
self.assertEqual(_testcapi.function_get_kw_defaults(some), None)
|
||||||
|
self.assertEqual(some.__kwdefaults__, None)
|
||||||
|
|
||||||
|
|
||||||
class TestPendingCalls(unittest.TestCase):
|
class TestPendingCalls(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -5862,6 +5862,33 @@ function_set_defaults(PyObject *self, PyObject *args)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
function_get_kw_defaults(PyObject *self, PyObject *func)
|
||||||
|
{
|
||||||
|
PyObject *defaults = PyFunction_GetKwDefaults(func);
|
||||||
|
if (defaults != NULL) {
|
||||||
|
Py_INCREF(defaults);
|
||||||
|
return defaults;
|
||||||
|
} else if (PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
Py_RETURN_NONE; // This can happen when `kwdefaults` are set to `None`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
function_set_kw_defaults(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *func = NULL, *defaults = NULL;
|
||||||
|
if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int result = PyFunction_SetKwDefaults(func, defaults);
|
||||||
|
if (result == -1)
|
||||||
|
return NULL;
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// type watchers
|
// type watchers
|
||||||
|
|
||||||
|
@ -6281,6 +6308,8 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"function_get_module", function_get_module, METH_O, NULL},
|
{"function_get_module", function_get_module, METH_O, NULL},
|
||||||
{"function_get_defaults", function_get_defaults, METH_O, NULL},
|
{"function_get_defaults", function_get_defaults, METH_O, NULL},
|
||||||
{"function_set_defaults", function_set_defaults, METH_VARARGS, NULL},
|
{"function_set_defaults", function_set_defaults, METH_VARARGS, NULL},
|
||||||
|
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
|
||||||
|
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
|
||||||
{"add_type_watcher", add_type_watcher, METH_O, NULL},
|
{"add_type_watcher", add_type_watcher, METH_O, NULL},
|
||||||
{"clear_type_watcher", clear_type_watcher, METH_O, NULL},
|
{"clear_type_watcher", clear_type_watcher, METH_O, NULL},
|
||||||
{"watch_type", watch_type, METH_VARARGS, NULL},
|
{"watch_type", watch_type, METH_VARARGS, NULL},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue