From c55a9b83ed57a65622bc2f264ee4c5fea629a095 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 14 Nov 2026 20:20:29 +0100 Subject: [PATCH 1/2] Test PyLong import/export API on limited C API 3.15 and newer --- tests/test_pythoncapi_compat_cext.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index aee2f35..d63ce4c 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -1414,21 +1414,33 @@ test_dict_setdefault(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) } -#if !defined(PYPY_VERSION) && !defined(Py_LIMITED_API) +#if ((!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)) \ + && !defined(PYPY_VERSION)) static int test_long_import_export() { - // test import/export API - digit *digits; + // test PyLong import/export API + + const PyLongLayout *layout = PyLong_GetNativeLayout(); + assert(layout->digits_order == -1); + if (layout->digit_size != sizeof(uint32_t)) { + PyErr_SetString(PyExc_AssertionError, + "unsupported digit size"); + return -1; + } + + uint32_t *digits; PyLongWriter *writer; static PyLongExport long_export; + // test PyLongWriter_Discard() writer = PyLongWriter_Create(1, 1, (void **)&digits); if (writer == NULL) { return -1; } PyLongWriter_Discard(writer); + // test PyLongWriter_Finish() writer = PyLongWriter_Create(1, 1, (void **)&digits); if (writer == NULL) { return -1; @@ -1467,7 +1479,7 @@ test_long_import_export() return -1; } assert(long_export.value == 0); - digits = (digit*)long_export.digits; + digits = (uint32_t*)long_export.digits; assert(digits[0] == 1); assert(digits[1] == 0); assert(digits[2] == 0); @@ -1476,9 +1488,6 @@ test_long_import_export() PyLong_FreeExport(&long_export); Py_DECREF(obj); - const PyLongLayout *layout = PyLong_GetNativeLayout(); - assert(layout->digits_order == -1); - assert(layout->digit_size == sizeof(digit)); return 0; } #endif @@ -1519,7 +1528,8 @@ test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(PyLong_IsNegative(obj) == 0); assert(PyLong_IsZero(obj) == 0); -#if !defined(PYPY_VERSION) && !defined(Py_LIMITED_API) +#if ((!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)) \ + && !defined(PYPY_VERSION)) if (test_long_import_export() < 0) { return NULL; } From 470fbf681eb6a55a23f48c89a0d8c7a30eb1d54c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 14 Nov 2026 20:28:39 +0100 Subject: [PATCH 2/2] Update Py_HashPointer() doc --- docs/api.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api.rst b/docs/api.rst index 7f5ac3a..5bc1541 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -525,6 +525,8 @@ Python 3.13 See `Py_HashPointer() documentation `__. + Not available on the limited C API. + .. c:function:: Py_hash_t PyObject_GenericHash(PyObject *obj) See `PyObject_GenericHash() documentation `__.