diff --git a/docs/api.rst b/docs/api.rst index 26fcd31..a75053e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -26,6 +26,13 @@ Latest version of the header file: `pythoncapi_compat.h `_. +Python 3.14 +----------- + +.. c:function:: int PyLong_GetSign(PyObject *obj, int *sign) + + See `PyLong_GetSign() documentation `__. + Python 3.13 ----------- diff --git a/docs/changelog.rst b/docs/changelog.rst index 336df90..4d0fb9d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,7 @@ Changelog ========= +* 2024-06-03: Add ``PyLong_GetSign()``. * 2024-04-23: Drop Python 3.5 support. It cannot be tested anymore (pip fails). * 2024-04-02: Add ``PyDict_SetDefaultRef()`` function. * 2024-03-29: Add ``PyList_GetItemRef()`` function. diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index 16935df..1b59f93 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -1339,6 +1339,21 @@ PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, #endif +// gh-116560 added PyLong_GetSign() to Python 3.14a4 +#if PY_VERSION_HEX < 0x030E00A1 +static inline int PyLong_GetSign(PyObject *obj, int *sign) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + + *sign = _PyLong_Sign(obj); + return 0; +} +#endif + + #ifdef __cplusplus } #endif diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index 4fc043c..aa7b206 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -53,6 +53,7 @@ // Marker to check that pointer value was set static const char uninitialized[] = "uninitialized"; #define UNINITIALIZED_OBJ ((PyObject *)uninitialized) +#define UNINITIALIZED_INT 0x83ff979 static PyObject* @@ -1413,6 +1414,11 @@ test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) PyErr_Clear(); Py_DECREF(obj2); + // test PyLong_GetSign() + int sign = UNINITIALIZED_INT; + assert(PyLong_GetSign(obj, &sign) == 0); + assert(sign == 1); + Py_RETURN_NONE; }