From 1ed354afde7ea7e881c645e7e1d5617da350abd4 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 13 Feb 2025 00:58:51 +0000 Subject: [PATCH] bpo-45325: Add a new 'p' parameter to Py_BuildValue to convert an integer into a Python bool --- Doc/c-api/arg.rst | 4 +++ Doc/whatsnew/3.14.rst | 4 +++ ...5-02-13-00-57-05.gh-issue-45325.Cwif9z.rst | 3 +++ Modules/_testcapimodule.c | 26 +++++++++++++++++++ Python/modsupport.c | 5 ++++ 5 files changed, 42 insertions(+) create mode 100644 Misc/NEWS.d/next/C_API/2025-02-13-00-57-05.gh-issue-45325.Cwif9z.rst diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index 209056ef2f8bce..deebaba1952999 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -645,6 +645,10 @@ Building values ``n`` (:class:`int`) [:c:type:`Py_ssize_t`] Convert a C :c:type:`Py_ssize_t` to a Python integer. + ``p`` (:class:`bool`) [int] + Convert a C :c:expr:`int` to a Python :class:`bool` object. + .. versionadded:: 3.14 + ``c`` (:class:`bytes` of length 1) [char] Convert a C :c:expr:`int` representing a byte to a Python :class:`bytes` object of length 1. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index e40b597ee52157..4e3883e6f5c43b 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1416,6 +1416,10 @@ New features and get an attribute of the module. (Contributed by Victor Stinner in :gh:`128911`.) +* Add support for a new ``p`` format unit in :c:func:`Py_BuildValue` that allows to + take a C integer and produce a Python :class:`bool` object. (Contributed by + Pablo Galindo in :issue:`45325`.) + Limited C API changes --------------------- diff --git a/Misc/NEWS.d/next/C_API/2025-02-13-00-57-05.gh-issue-45325.Cwif9z.rst b/Misc/NEWS.d/next/C_API/2025-02-13-00-57-05.gh-issue-45325.Cwif9z.rst new file mode 100644 index 00000000000000..d9536547788295 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2025-02-13-00-57-05.gh-issue-45325.Cwif9z.rst @@ -0,0 +1,3 @@ +Add a new ``p`` format parameter to :c:func:`Py_BuildValue` that allows to +take a C integer and produce a Python :class:`bool` object. Patch by Pablo +Galindo. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c84646ccf03fa7..3d5fa9006447de 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -411,6 +411,31 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } +static PyObject * +test_buildvalue_p(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *res = Py_BuildValue("p", 3); + if (res == NULL) { + return NULL; + } + if (!Py_IsTrue(res)) { + Py_DECREF(res); + return raiseTestError(self, "test_buildvalue_p", "Py_BuildValue(\"p\", 3) returned wrong result"); + } + Py_DECREF(res); + + res = Py_BuildValue("p", 0); + if (res == NULL) { + return NULL; + } + if (!Py_IsFalse(res)) { + Py_DECREF(res); + return raiseTestError(self, "test_buildvalue_p", "Py_BuildValue(\"p\", 0) returned wrong result"); + } + Py_DECREF(res); + + Py_RETURN_NONE; +} static PyObject * pyobject_repr_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) @@ -2512,6 +2537,7 @@ static PyMethodDef TestMethods[] = { {"py_buildvalue", py_buildvalue, METH_VARARGS}, {"py_buildvalue_ints", py_buildvalue_ints, METH_VARARGS}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, + {"test_buildvalue_p", test_buildvalue_p, METH_NOARGS}, {"test_reftracer", test_reftracer, METH_NOARGS}, {"_test_thread_state", test_thread_state, METH_VARARGS}, {"gilstate_ensure_release", gilstate_ensure_release, METH_NOARGS}, diff --git a/Python/modsupport.c b/Python/modsupport.c index 517dc971f88c87..501231affe8cd4 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -364,6 +364,11 @@ do_mkvalue(const char **p_format, va_list *p_va) int i = va_arg(*p_va, int); return PyUnicode_FromOrdinal(i); } + case 'p': + { + int i = va_arg(*p_va, int); + return PyBool_FromLong(i); + } case 's': case 'z':