From 77abeec5330ee0c97ab128066207e1b6f232bb56 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 12 Nov 2024 18:56:51 +0300 Subject: [PATCH] Add PyLong_IsPositive/Negative/Zero() functions (#119) Co-authored-by: Victor Stinner --- docs/api.rst | 12 ++++++++++++ docs/changelog.rst | 6 ++++++ pythoncapi_compat.h | 30 +++++++++++++++++++++++++++++ tests/test_pythoncapi_compat_cext.c | 5 +++++ 4 files changed, 53 insertions(+) diff --git a/docs/api.rst b/docs/api.rst index 68429cc..7c743f8 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -29,6 +29,18 @@ Latest version of the header file: Python 3.14 ----------- +.. c:function:: int PyLong_IsPositive(PyObject *obj) + + See `PyLong_IsPositive() documentation `__. + +.. c:function:: int PyLong_IsNegative(PyObject *obj) + + See `PyLong_IsNegative() documentation `__. + +.. c:function:: int PyLong_IsZero(PyObject *obj) + + See `PyLong_IsZero() documentation `__. + .. c:function:: int PyLong_GetSign(PyObject *obj, int *sign) See `PyLong_GetSign() documentation `__. diff --git a/docs/changelog.rst b/docs/changelog.rst index a2d188c..3a616f7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,12 @@ Changelog ========= +* 2024-11-12: Add functions: + + * ``PyLong_IsPositive()`` + * ``PyLong_IsNegative()`` + * ``PyLong_IsZero()`` + * 2024-10-09: Add functions: * ``PyBytes_Join()`` diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index ba1850e..c51dd6b 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -1520,6 +1520,36 @@ static inline int PyLong_GetSign(PyObject *obj, int *sign) } #endif +// gh-126061 added PyLong_IsPositive/Negative/Zero() to Python in 3.14.0a2 +#if PY_VERSION_HEX < 0x030E00A2 +static inline int PyLong_IsPositive(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == 1; +} + +static inline int PyLong_IsNegative(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == -1; +} + +static inline int PyLong_IsZero(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == 0; +} +#endif + // gh-124502 added PyUnicode_Equal() to Python 3.14.0a0 #if PY_VERSION_HEX < 0x030E00A0 diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index 419a5dc..b8df8a6 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -1421,6 +1421,11 @@ test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(PyLong_GetSign(obj, &sign) == 0); assert(sign == 1); + // test PyLong_IsPositive(), PyLong_IsNegative() and PyLong_IsZero() + assert(PyLong_IsPositive(obj) == 1); + assert(PyLong_IsNegative(obj) == 0); + assert(PyLong_IsZero(obj) == 0); + Py_RETURN_NONE; }