From f6840fdc72698f556cccb268b3e81eb4bbc343b3 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:06:37 +0300 Subject: [PATCH] Add further support for PyPy3.12 v8.0.0 --- docs/api.rst | 14 ++++++++++++++ docs/changelog.rst | 3 +++ pythoncapi_compat.h | 6 ++++-- tests/test_pythoncapi_compat_cext.c | 14 +++++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index ca19e6e..1947f1b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -239,6 +239,20 @@ Python 3.14 See `PyUnstable_Object_IsUniquelyReferenced() documentation `__. + Not available on PyPy 3.12. + +.. c:function:: int PyUnstable_TryIncRef(PyObject *op) + + See `PyUnstable_TryIncRef() documentation `__. + + Not available on PyPy 3.12. + +.. c:function:: void PyUnstable_EnableTryIncRef(PyObject *op) + + See `PyUnstable_EnableTryIncRef() documentation `__. + + Not available on PyPy 3.12. + Not supported: * ``PyConfig_Names()`` diff --git a/docs/changelog.rst b/docs/changelog.rst index 75e6001..9be526e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,9 @@ Changelog ========= +* 2026-09-22: Add support for PyPy3.12 v8.0.0. + ``PyUnstable_Object_IsUniquelyReferenced()``, ``PyUnstable_TryIncRef()`` + and ``PyUnstable_EnableTryIncRef()`` are not available on PyPy3.12. * 2026-09-07: Remove code to support Python 2.7, Python 3.5 and PyPy for Python 2.7 ("pypy2"). Python 2.7 was no longer supported since August 2023. diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index e0c0f79..38de9bc 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -2130,7 +2130,8 @@ PyConfig_GetInt(const char *name, int *value) // gh-133144 added PyUnstable_Object_IsUniquelyReferenced() to Python 3.14.0b1. // Adapted from _PyObject_IsUniquelyReferenced() implementation. -#if PY_VERSION_HEX < 0x030E00B0 +// Not available on PyPy3.12: ob_refcnt carries an internal tag. +#if PY_VERSION_HEX < 0x030E00B0 && (!defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000) static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj) { #if !defined(Py_GIL_DISABLED) @@ -2148,7 +2149,8 @@ static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj) // gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to // Python 3.14.0a5. Adapted from _Py_TryIncref() and _PyObject_SetMaybeWeakref(). -#if PY_VERSION_HEX < 0x030E00A5 +// Not available on PyPy3.12: ob_refcnt carries an internal tag. +#if PY_VERSION_HEX < 0x030E00A5 && (!defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000) static inline int PyUnstable_TryIncRef(PyObject *op) { #ifndef Py_GIL_DISABLED diff --git a/tests/test_pythoncapi_compat_cext.c b/tests/test_pythoncapi_compat_cext.c index 45fa04e..c514f11 100644 --- a/tests/test_pythoncapi_compat_cext.c +++ b/tests/test_pythoncapi_compat_cext.c @@ -1956,6 +1956,8 @@ test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) } #endif +// PyUnstable_Object_IsUniquelyReferenced() is not available on PyPy3.12. +#if !defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000 static PyObject * test_uniquely_referenced(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { @@ -1975,6 +1977,7 @@ test_uniquely_referenced(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } +#endif static PyObject * test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) @@ -2419,7 +2422,9 @@ test_tuple(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) return test_tuple_fromarray(); } -// Test adapted from CPython's _testcapi/object.c +// Test adapted from CPython's _testcapi/object.c. +// PyUnstable_TryIncRef() is not available on PyPy3.12. +#if !defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000 static int TryIncref_dealloc_called = 0; static void @@ -2458,6 +2463,7 @@ test_try_incref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(TryIncref_dealloc_called == 1); Py_RETURN_NONE; } +#endif #if 0x030D0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION) static PyObject * @@ -2545,10 +2551,14 @@ static struct PyMethodDef methods[] = { {"test_config", test_config, METH_NOARGS, _Py_NULL}, #endif {"test_sys", test_sys, METH_NOARGS, _Py_NULL}, +#if !defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000 {"test_uniquely_referenced", test_uniquely_referenced, METH_NOARGS, _Py_NULL}, +#endif {"test_byteswriter", test_byteswriter, METH_NOARGS, _Py_NULL}, {"test_tuple", test_tuple, METH_NOARGS, _Py_NULL}, +#if !defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000 {"test_try_incref", test_try_incref, METH_NOARGS, _Py_NULL}, +#endif #if 0x030D0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION) {"test_set_immortal", test_set_immortal, METH_NOARGS, _Py_NULL}, #endif @@ -2580,6 +2590,7 @@ module_exec(PyObject *module) return -1; } #endif +#if !defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030C0000 TryIncrefType.tp_name = "TryIncrefType"; TryIncrefType.tp_basicsize = sizeof(PyObject); TryIncrefType.tp_dealloc = TryIncref_dealloc; @@ -2587,6 +2598,7 @@ module_exec(PyObject *module) if (PyType_Ready(&TryIncrefType) < 0) { return -1; } +#endif return 0; }