Skip to content

Commit 0e30c50

Browse files
committed
Fix PyIter_NextItem() for limited API 3.9 and older
* Enable test_frame() on PyPy 3.11. * Enable PyObject_CallOneArg() tests on limited C API. * Enable test_gc() on Python 3.9. * Enable test_module_add_type() on limited C API 3.9 and older. * Enable PyDict_ContainsString() tests on limited C API. * Enable test_config() on Python 3.8. * Enable test_tuple_fromarray() on the limited C API.
1 parent 077e5da commit 0e30c50

3 files changed

Lines changed: 125 additions & 104 deletions

File tree

‎docs/api.rst‎

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ Python 3.15
7474

7575
See `PyUnstable_SetImmortal() documentation <https://docs.python.org/dev/c-api/object.html#c.PyUnstable_SetImmortal>`__.
7676

77-
Availability: Python 3.13 and newer, not available on PyPy, not available
78-
with the limited C API.
77+
Availability: Python 3.13 and newer.
78+
79+
Not available on PyPy, and not on the limited C API.
7980

8081
Python 3.14
8182
-----------
@@ -278,13 +279,17 @@ Python 3.14
278279

279280
See `PyConfig_Get() documentation <https://docs.python.org/dev/c-api/init_config.html#c.PyConfig_Get>`__.
280281

281-
Not available on the limited C API.
282+
Availability: Python 3.9 and newer.
283+
284+
Not available on PyPy and not on the limited C API.
282285

283286
.. c:function:: int PyConfig_GetInt(const char *name, int *value)
284287

285288
See `PyConfig_GetInt() documentation <https://docs.python.org/dev/c-api/init_config.html#c.PyConfig_GetInt>`__.
286289

287-
Not available on the limited C API.
290+
Availability: Python 3.9 and newer.
291+
292+
Not available on PyPy and not on the limited C API.
288293

289294
.. c:function:: int PyUnstable_Object_IsUniquelyReferenced(PyObject *op)
290295

@@ -633,39 +638,41 @@ Python 3.11
633638

634639
Pack a C double as the IEEE 754 binary16 half-precision format.
635640

636-
Availability: Python 3.6 and newer. Not available on PyPy nor on limited C
637-
API 3.10 and older.
641+
Availability: Python 3.6 and newer.
642+
643+
Not available on PyPy nor on limited C API.
638644

639645
.. c:function:: int PyFloat_Pack4(double x, unsigned char *p, int le)
640646

641647
Pack a C double as the IEEE 754 binary32 single precision format.
642648

643-
Not available on PyPy nor on limited C API 3.10 and older.
649+
Not available on PyPy nor on limited C API.
644650

645651
.. c:function:: int PyFloat_Pack8(double x, unsigned char *p, int le)
646652

647653
Pack a C double as the IEEE 754 binary64 double precision format.
648654

649-
Not available on PyPy nor on limited C API 3.10 and older.
655+
Not available on PyPy nor on limited C API.
650656

651657
.. c:function:: double PyFloat_Unpack2(const unsigned char *p, int le)
652658

653659
Unpack the IEEE 754 binary16 half-precision format as a C double.
654660

655-
Availability: Python 3.6 and newer. Not available on PyPy nor on limited C
656-
API 3.10 and older.
661+
Availability: Python 3.6 and newer.
662+
663+
Not available on PyPy nor on limited C API.
657664

658665
.. c:function:: double PyFloat_Unpack4(const unsigned char *p, int le)
659666

660667
Unpack the IEEE 754 binary32 single precision format as a C double.
661668

662-
Not available on PyPy nor on limited C API 3.10 and older.
669+
Not available on PyPy nor on limited C API.
663670

664671
.. c:function:: double PyFloat_Unpack8(const unsigned char *p, int le)
665672

666673
Unpack the IEEE 754 binary64 double precision format as a C double.
667674

668-
Not available on PyPy nor on limited C API 3.10 and older.
675+
Not available on PyPy nor on limited C API.
669676

670677
.. c:function:: PyObject* PyType_GetName(PyTypeObject *type)
671678

@@ -797,7 +804,7 @@ PyThreadState
797804

798805
See `PyThreadState_GetFrame() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_GetFrame>`__.
799806

800-
Not available on PyPy
807+
Availability: PyPy 3.11 and newer, and limited C API 3.9.
801808

802809
.. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate)
803810

‎pythoncapi_compat.h‎

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
341341
#endif
342342

343343
#if ((!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000) \
344-
&& !defined(PYPY_VERSION))
344+
&& (!defined(PYPY_VERSION) || PY_VERSION_HEX >= 0x030B0000))
345345
static inline PyFrameObject*
346346
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
347347
{
@@ -432,7 +432,8 @@ static inline PyObject* PyObject_CallNoArgs(PyObject *func)
432432
// bpo-39245 made PyObject_CallOneArg() public (previously called
433433
// _PyObject_CallOneArg) in Python 3.9.0a4
434434
// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11
435-
#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4
435+
#if (!defined(PyObject_CallOneArg) \
436+
&& (PY_VERSION_HEX < 0x030900A4 || defined(Py_LIMITED_API)))
436437
static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)
437438
{
438439
return PyObject_CallFunctionObjArgs(func, arg, NULL);
@@ -1076,6 +1077,7 @@ PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_
10761077
#endif
10771078
{
10781079
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030a0000
1080+
// Limited C API 3.9 and older
10791081
bytes = PyUnicode_AsUTF8String(unicode);
10801082
if (bytes == NULL) {
10811083
// Memory allocation failure. The API cannot report error,
@@ -1086,7 +1088,8 @@ PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_
10861088
utf8 = PyBytes_AsString(bytes);
10871089
len = PyBytes_Size(bytes);
10881090
#else
1089-
// Python 3.10 added PyUnicode_AsUTF8AndSize() to the limited C API
1091+
// Python 3.12 and older, and limited C API 3.10 and newer.
1092+
// Python 3.10 added PyUnicode_AsUTF8AndSize() to the limited C API.
10901093
utf8 = PyUnicode_AsUTF8AndSize(unicode, &len);
10911094
if (utf8 == NULL) {
10921095
// Memory allocation failure. The API cannot report error,
@@ -1297,10 +1300,11 @@ static inline int PyTime_PerfCounter(PyTime_t *result)
12971300

12981301
// gh-111389 added hash constants to Python 3.13.0a5. These constants were
12991302
// added first as private macros to Python 3.4.0b1 and PyPy 7.3.8.
1300-
#if (!defined(PyHASH_BITS) \
1301-
&& ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
1302-
|| (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
1303-
&& PYPY_VERSION_NUM >= 0x07030800)))
1303+
#if ((!defined(PyHASH_BITS) \
1304+
&& ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
1305+
|| (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
1306+
&& PYPY_VERSION_NUM >= 0x07030800))) \
1307+
&& !defined(Py_LIMITED_API))
13041308
# define PyHASH_BITS _PyHASH_BITS
13051309
# define PyHASH_MODULUS _PyHASH_MODULUS
13061310
# define PyHASH_INF _PyHASH_INF
@@ -1443,10 +1447,10 @@ PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
14431447
#endif
14441448

14451449
#if PY_VERSION_HEX < 0x030D00B3
1446-
# define Py_BEGIN_CRITICAL_SECTION(op) {
1447-
# define Py_END_CRITICAL_SECTION() }
1448-
# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
1449-
# define Py_END_CRITICAL_SECTION2() }
1450+
# define Py_BEGIN_CRITICAL_SECTION(op) {
1451+
# define Py_END_CRITICAL_SECTION() }
1452+
# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
1453+
# define Py_END_CRITICAL_SECTION2() }
14501454
#endif
14511455

14521456
#if PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION) && !defined(Py_LIMITED_API)
@@ -1826,7 +1830,8 @@ static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
18261830
|| (defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030e0000))
18271831
static inline int PyIter_NextItem(PyObject *iter, PyObject **item)
18281832
{
1829-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000
1833+
// Limited API: PyType_GetSlot() only accepts all types since Python 3.10
1834+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
18301835
iternextfunc tp_iternext;
18311836

18321837
assert(iter != NULL);
@@ -1835,7 +1840,6 @@ static inline int PyIter_NextItem(PyObject *iter, PyObject **item)
18351840
#ifndef Py_LIMITED_API
18361841
tp_iternext = Py_TYPE(iter)->tp_iternext;
18371842
#else
1838-
// PyType_GetSlot() only accepts all types since Python 3.10
18391843
tp_iternext = _Py_CAST(iternextfunc, PyType_GetSlot(Py_TYPE(iter), Py_tp_iternext));
18401844
#endif
18411845
if (tp_iternext == NULL) {
@@ -1856,13 +1860,14 @@ static inline int PyIter_NextItem(PyObject *iter, PyObject **item)
18561860
}
18571861
return -1;
18581862
#else
1863+
// Implementation for limited C API 3.9 and older
1864+
18591865
assert(iter != NULL);
18601866
assert(item != NULL);
18611867

18621868
// Cannot check if iter is an iterator: PyIter_Check() is only implemented
18631869
// as a function since Python 3.8.
18641870

1865-
// Limited C API 3.2 and 3.3
18661871
*item = PyIter_Next(iter);
18671872
if (*item != NULL) {
18681873
return 1;
@@ -2547,6 +2552,7 @@ static inline PyObject*
25472552
PySys_GetAttr(PyObject *name)
25482553
{
25492554
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030a0000
2555+
// Limited C API 3.9 and older
25502556
PyObject *bytes, *result;
25512557
bytes = PyUnicode_AsUTF8String(name);
25522558
if (bytes == NULL) {
@@ -2556,6 +2562,7 @@ PySys_GetAttr(PyObject *name)
25562562
Py_DECREF(bytes);
25572563
return result;
25582564
#else
2565+
// Python 3.14 and newer, and limited C API 3.10 and newer
25592566
#ifndef Py_LIMITED_API
25602567
const char *name_str = PyUnicode_AsUTF8(name);
25612568
#else
@@ -2583,6 +2590,7 @@ static inline int
25832590
PySys_GetOptionalAttr(PyObject *name, PyObject **value)
25842591
{
25852592
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030a0000
2593+
// Limited C API 3.9 and older
25862594
PyObject *bytes;
25872595
int res;
25882596
bytes = PyUnicode_AsUTF8String(name);

0 commit comments

Comments
 (0)