From 74d0161c8a42951c84e2a39a2a41107f5a4da479 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Apr 2025 18:01:24 +0300 Subject: [PATCH 1/2] gh-132753: Argument Clinic: Fix support of c_default for the bool converter --- Lib/test/test_clinic.py | 5 +++ Modules/_testclinic.c | 20 ++++++++++ Modules/clinic/_testclinic.c.h | 60 +++++++++++++++++++++++++++- Tools/clinic/libclinic/converters.py | 3 +- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 199050d0d61438..0b59910277f9b4 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -3032,6 +3032,11 @@ def test_bool_converter(self): self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False)) + def test_bool_converter_default(self): + self.assertEqual(ac_tester.bool_converter_default(), (1, 0, -2, -3)) + self.assertEqual(ac_tester.bool_converter_default(False, True, False, True), + (0, 1, 0, 1)) + def test_char_converter(self): with self.assertRaises(TypeError): ac_tester.char_converter(1) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 0a1f13db6ca204..46ef587a6b6812 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -224,6 +224,25 @@ bool_converter_impl(PyObject *module, int a, int b, int c) } +/*[clinic input] +bool_converter_default + + a: bool = True + b: bool = False + c: bool(c_default="-2") = True + d: bool(c_default="-3") = x + / + +[clinic start generated code]*/ + +static PyObject * +bool_converter_default_impl(PyObject *module, int a, int b, int c, int d) +/*[clinic end generated code: output=97757cf2e24f6940 input=bb40f29518f69e70]*/ +{ + return Py_BuildValue("iiii", a, b, c, d); +} + + /*[clinic input] char_converter @@ -2296,6 +2315,7 @@ static PyMethodDef tester_methods[] = { BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF UNICODE_CONVERTER_METHODDEF BOOL_CONVERTER_METHODDEF + BOOL_CONVERTER_DEFAULT_METHODDEF CHAR_CONVERTER_METHODDEF UNSIGNED_CHAR_CONVERTER_METHODDEF SHORT_CONVERTER_METHODDEF diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 56b0ca316d4952..0994c9a7283fb4 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -195,6 +195,64 @@ bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(bool_converter_default__doc__, +"bool_converter_default($module, a=True, b=False, c=True, d=x, /)\n" +"--\n" +"\n"); + +#define BOOL_CONVERTER_DEFAULT_METHODDEF \ + {"bool_converter_default", _PyCFunction_CAST(bool_converter_default), METH_FASTCALL, bool_converter_default__doc__}, + +static PyObject * +bool_converter_default_impl(PyObject *module, int a, int b, int c, int d); + +static PyObject * +bool_converter_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int a = 1; + int b = 0; + int c = -2; + int d = -3; + + if (!_PyArg_CheckPositional("bool_converter_default", nargs, 0, 4)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyObject_IsTrue(args[0]); + if (a < 0) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + b = PyObject_IsTrue(args[1]); + if (b < 0) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = PyObject_IsTrue(args[2]); + if (c < 0) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + d = PyObject_IsTrue(args[3]); + if (d < 0) { + goto exit; + } +skip_optional: + return_value = bool_converter_default_impl(module, a, b, c, d); + +exit: + return return_value; +} + PyDoc_STRVAR(char_converter__doc__, "char_converter($module, a=b\'A\', b=b\'\\x07\', c=b\'\\x08\', d=b\'\\t\', e=b\'\\n\',\n" " f=b\'\\x0b\', g=b\'\\x0c\', h=b\'\\r\', i=b\'\"\', j=b\"\'\", k=b\'?\',\n" @@ -4423,4 +4481,4 @@ _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall(PyObject *type, PyO exit: return return_value; } -/*[clinic end generated code: output=ea0b8fb0949fa49f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b41f0076aa0b9fb8 input=a9049054013a1b77]*/ diff --git a/Tools/clinic/libclinic/converters.py b/Tools/clinic/libclinic/converters.py index 871d7542ba0763..b176ee4ecd444a 100644 --- a/Tools/clinic/libclinic/converters.py +++ b/Tools/clinic/libclinic/converters.py @@ -30,7 +30,8 @@ def converter_init(self, *, accept: TypeSet = {object}) -> None: fail(f"bool_converter: illegal 'accept' argument {accept!r}") if self.default is not unspecified and self.default is not unknown: self.default = bool(self.default) - self.c_default = str(int(self.default)) + if self.c_default in {'Py_True', 'Py_False'}: + self.c_default = str(int(self.default)) def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'i': From a54469c104c0d35c8fa625be0176613d344c2c04 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Apr 2025 20:39:35 +0300 Subject: [PATCH 2/2] Change test name. --- Lib/test/test_clinic.py | 6 +++--- Modules/_testclinic.c | 8 ++++---- Modules/clinic/_testclinic.c.h | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 0b59910277f9b4..0c99620e27cde4 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -3032,9 +3032,9 @@ def test_bool_converter(self): self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False)) - def test_bool_converter_default(self): - self.assertEqual(ac_tester.bool_converter_default(), (1, 0, -2, -3)) - self.assertEqual(ac_tester.bool_converter_default(False, True, False, True), + def test_bool_converter_c_default(self): + self.assertEqual(ac_tester.bool_converter_c_default(), (1, 0, -2, -3)) + self.assertEqual(ac_tester.bool_converter_c_default(False, True, False, True), (0, 1, 0, 1)) def test_char_converter(self): diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 46ef587a6b6812..3e903b6d87d89f 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -225,7 +225,7 @@ bool_converter_impl(PyObject *module, int a, int b, int c) /*[clinic input] -bool_converter_default +bool_converter_c_default a: bool = True b: bool = False @@ -236,8 +236,8 @@ bool_converter_default [clinic start generated code]*/ static PyObject * -bool_converter_default_impl(PyObject *module, int a, int b, int c, int d) -/*[clinic end generated code: output=97757cf2e24f6940 input=bb40f29518f69e70]*/ +bool_converter_c_default_impl(PyObject *module, int a, int b, int c, int d) +/*[clinic end generated code: output=cf204382e1e4c30c input=185786302ab84081]*/ { return Py_BuildValue("iiii", a, b, c, d); } @@ -2315,7 +2315,7 @@ static PyMethodDef tester_methods[] = { BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF UNICODE_CONVERTER_METHODDEF BOOL_CONVERTER_METHODDEF - BOOL_CONVERTER_DEFAULT_METHODDEF + BOOL_CONVERTER_C_DEFAULT_METHODDEF CHAR_CONVERTER_METHODDEF UNSIGNED_CHAR_CONVERTER_METHODDEF SHORT_CONVERTER_METHODDEF diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 0994c9a7283fb4..636eea665e9025 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -195,19 +195,19 @@ bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -PyDoc_STRVAR(bool_converter_default__doc__, -"bool_converter_default($module, a=True, b=False, c=True, d=x, /)\n" +PyDoc_STRVAR(bool_converter_c_default__doc__, +"bool_converter_c_default($module, a=True, b=False, c=True, d=x, /)\n" "--\n" "\n"); -#define BOOL_CONVERTER_DEFAULT_METHODDEF \ - {"bool_converter_default", _PyCFunction_CAST(bool_converter_default), METH_FASTCALL, bool_converter_default__doc__}, +#define BOOL_CONVERTER_C_DEFAULT_METHODDEF \ + {"bool_converter_c_default", _PyCFunction_CAST(bool_converter_c_default), METH_FASTCALL, bool_converter_c_default__doc__}, static PyObject * -bool_converter_default_impl(PyObject *module, int a, int b, int c, int d); +bool_converter_c_default_impl(PyObject *module, int a, int b, int c, int d); static PyObject * -bool_converter_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +bool_converter_c_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int a = 1; @@ -215,7 +215,7 @@ bool_converter_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs int c = -2; int d = -3; - if (!_PyArg_CheckPositional("bool_converter_default", nargs, 0, 4)) { + if (!_PyArg_CheckPositional("bool_converter_c_default", nargs, 0, 4)) { goto exit; } if (nargs < 1) { @@ -247,7 +247,7 @@ bool_converter_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } skip_optional: - return_value = bool_converter_default_impl(module, a, b, c, d); + return_value = bool_converter_c_default_impl(module, a, b, c, d); exit: return return_value; @@ -4481,4 +4481,4 @@ _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall(PyObject *type, PyO exit: return return_value; } -/*[clinic end generated code: output=b41f0076aa0b9fb8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b57b94aeba0882b4 input=a9049054013a1b77]*/