diff --git a/docs/api.rst b/docs/api.rst index 6f15f9c..693f0be 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -75,6 +75,14 @@ Python 3.13 See `Py_IsFinalizing() documentation `__. +.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key) + + See `PyDict_ContainsString() documentation `__. + +.. c:function:: int PyLong_AsInt(PyObject *obj) + + See `PyLong_AsInt() documentation `__. + Python 3.12 ----------- diff --git a/docs/changelog.rst b/docs/changelog.rst index 477d038..bab8e65 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,7 @@ Changelog ========= +* 2023-08-25: Add ``PyDict_ContainsString()`` and ``PyLong_AsInt()`` functions. * 2023-08-21: Remove support for Python 2.7, Python 3.4 and older. * 2023-08-16: Add ``Py_IsFinalizing()`` function. * 2023-07-21: Add ``PyDict_GetItemRef()`` function. diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index ae0a1a4..4219db7 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -834,6 +834,28 @@ static inline int PyDict_ContainsString(PyObject *op, const char *key) #endif +// gh-108445 added PyLong_AsInt() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int PyLong_AsInt(PyObject *obj) +{ +#ifdef PYPY_VERSION + long value = PyLong_AsLong(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + if (value < (long)INT_MIN || (long)INT_MAX < value) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C int"); + return -1; + } + return (int)value; +#else + return _PyLong_AsInt(obj); +#endif +} +#endif + + #ifdef __cplusplus } #endif diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index 0f6dae6..da5c785 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -1209,6 +1209,35 @@ test_dict_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) } +static PyObject * +test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + // test PyLong_AsInt() + assert(!PyErr_Occurred()); + PyObject *obj = PyLong_FromLong(123); + if (obj == NULL) { + return NULL; + } + int value = PyLong_AsInt(obj); + assert(value == 123); + assert(!PyErr_Occurred()); + Py_DECREF(obj); + + // test PyLong_AsInt() with overflow + PyObject *obj2 = PyLong_FromLongLong((long long)INT_MAX + 1); + if (obj2 == NULL) { + return NULL; + } + value = PyLong_AsInt(obj2); + assert(value == -1); + assert(PyErr_ExceptionMatches(PyExc_OverflowError)); + PyErr_Clear(); + Py_DECREF(obj2); + + Py_RETURN_NONE; +} + + static struct PyMethodDef methods[] = { {"test_object", test_object, METH_NOARGS, _Py_NULL}, {"test_py_is", test_py_is, METH_NOARGS, _Py_NULL}, @@ -1234,6 +1263,7 @@ static struct PyMethodDef methods[] = { {"test_getattr", test_getattr, METH_NOARGS, _Py_NULL}, {"test_getitem", test_getitem, METH_NOARGS, _Py_NULL}, {"test_dict_api", test_dict_api, METH_NOARGS, _Py_NULL}, + {"test_long_api", test_long_api, METH_NOARGS, _Py_NULL}, {_Py_NULL, _Py_NULL, 0, _Py_NULL} }; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy