8000 Add PyLong_AsInt() function (#72) · python/pythoncapi-compat@8109811 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8109811

Browse files
authored
Add PyLong_AsInt() function (#72)
1 parent 4734c8e commit 8109811

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

docs/api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ Python 3.13
7575
7676
See `Py_IsFinalizing() documentation <https://docs.python.org/dev/c-api/init.html#c.Py_IsFinalizing>`__.
7777
78+
.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key)
79+
80+
See `PyDict_ContainsString() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_ContainsString>`__.
81+
82+
.. c:function:: int PyLong_AsInt(PyObject *obj)
83+
84+
See `PyLong_AsInt() documentation <https://docs.python.org/dev/c-api/long.html#c.PyLong_AsInt>`__.
85+
7886
7987
Python 3.12
8088
-----------

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Changelog
22
=========
33

4+
* 2023-08-25: Add ``PyDict_ContainsString()`` and ``PyLong_AsInt()`` functions.
45
* 2023-08-21: Remove support for Python 2.7, Python 3.4 and older.
56
* 2023-08-16: Add ``Py_IsFinalizing()`` function.
67
* 2023-07-21: Add ``PyDict_GetItemRef()`` function.

pythoncapi_compat.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,28 @@ static inline int PyDict_ContainsString(PyObject *op, const char *key)
834834
#endif
835835

836836

837+
// gh-108445 added PyLong_AsInt() to Python 3.13.0a1
838+
#if PY_VERSION_HEX < 0x030D00A1
839+
static inline int PyLong_AsInt(PyObject *obj)
840+
{
841+
#ifdef PYPY_VERSION
842+
long value = PyLong_AsLong(obj);
843+
if (value == -1 && PyErr_Occurred()) {
844+
return -1;
845+
}
846+
if (value < (long)INT_MIN || (long)INT_MAX < value) {
847+
PyErr_SetString(PyExc_OverflowError,
848+
"Python int too large to convert to C int");
849+
return -1;
850+
}
851+
return (int)value;
852+
#else
853+
return _PyLong_AsInt(obj);
854+
#endif
855+
}
856+
#endif
857+
858+
837859
#ifdef __cplusplus
838860
}
839861
#endif

tests/test_pythoncapi_compat_cext.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,35 @@ test_dict_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
12091209
}
12101210

12111211

1212+
static PyObject *
1213+
test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
1214+
{
1215+
// test PyLong_AsInt()
1216+
assert(!PyErr_Occurred());
1217+
PyObject *obj = PyLong_FromLong(123);
1218+
if (obj == NULL) {
1219+
return NULL;
1220+
}
1221+
int value = PyLong_AsInt(obj);
1222+
assert(value == 123);
1223+
assert(!PyErr_Occurred());
1224+
Py_DECREF(obj);
1225+
1226+
// test PyLong_AsInt() with overflow
1227+
PyObject *obj2 = PyLong_FromLongLong((long long)INT_MAX + 1);
1228+
if (obj2 == NULL) {
1229+
return NULL;
1230+
}
1231+
value = PyLong_AsInt(obj2);
1232+
assert(value == -1);
1233+
assert(PyErr_ExceptionMatches(PyExc_OverflowError));
1234+
PyErr_Clear();
1235+
Py_DECREF(obj2);
1236+
1237+
Py_RETURN_NONE;
1238+
}
1239+
1240+
12121241
static struct PyMethodDef methods[] = {
12131242
{"test_object", test_object, METH_NOARGS, _Py_NULL},
12141243
{"test_py_is", test_py_is, METH_NOARGS, _Py_NULL},
@@ -1234,6 +1263,7 @@ static struct PyMethodDef methods[] = {
12341263
{"test_getattr", test_getattr, METH_NOARGS, _Py_NULL},
12351264
{"test_getitem", test_getitem, METH_NOARGS, _Py_NULL},
12361265
{"test_dict_api", test_dict_api, METH_NOARGS, _Py_NULL},
1266+
{"test_long_api", test_long_api, METH_NOARGS, _Py_NULL},
12371267
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
12381268
};
12391269

0 commit comments

Comments
 (0)
0