From e604e63da5d910ec6461811c82e4a0c4a7882b8d Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:07:27 +0300 Subject: [PATCH 1/6] Add colour to logs, allow testing feature branches --- .github/workflows/build.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fcc6ecc..15b1089 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,10 +1,9 @@ name: Build -on: - push: - branches: [main] - pull_request: - branches: [main] +on: [push, pull_request, workflow_dispatch] + +env: + FORCE_COLOR: 1 jobs: build: From 674982d134ba79a265c8158580fad56a6fc65074 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:10:09 +0300 Subject: [PATCH 2/6] Fix 404 link --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15b1089..2305ece 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,7 +49,7 @@ jobs: - "pypy3.11" # Old PyPy versions - # See https://foss.heptapod.net/pypy/pypy/-/issues/3991 + # See https://github.com/pypy/pypy/issues/3990 - "pypy3.6-v7.3.2" - "pypy3.7-v7.3.2" From 583b724305b51183875ab2d2727dda177f13aa1e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:10:41 +0300 Subject: [PATCH 3/6] Add PyPy3.12 to CI --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2305ece..72f0b77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,6 +47,7 @@ jobs: - "pypy3.9" - "pypy3.10" - "pypy3.11" + - "pypy3.12" # Old PyPy versions # See https://github.com/pypy/pypy/issues/3990 From b72bc5e24fbd3fb824b49ff6ef300a097631b1fa Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:20:21 +0300 Subject: [PATCH 4/6] Bump GitHub Actions --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72f0b77..17625c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,10 +106,10 @@ jobs: steps: # https://github.com/actions/checkout - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Python # https://github.com/actions/setup-python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: python-version: ${{ matrix.python }} allow-prereleases: true From d59e7e3456c692195da6057adce5c9f9905fc91b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:21:29 +0300 Subject: [PATCH 5/6] Add support for PyPy3.12 v8.0.0 --- docs/api.rst | 16 +++++++++++++++- docs/changelog.rst | 4 ++++ pythoncapi_compat.h | 12 ++++++++---- runtests.py | 1 + tests/test_pythoncapi_compat_cext.c | 14 +++++++++++++- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index ca19e6e..cefea4c 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -8,7 +8,7 @@ functions for old Python versions. Supported Python versions: * Python 3.6 - 3.15 -* PyPy 2.7 and PyPy 3.6 - 3.10 +* PyPy 3.6 - 3.12 C++03 and C++11 are supported on Python 3.6 and newer. @@ -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..7a2e92b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,10 @@ Changelog ========= +* 2026-09-22: Add support for PyPy3.12 v8.0.0, which provides + ``PyFrame_GetCode()`` and ``PyInterpreterState_Get()``. + ``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..def7948 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -126,7 +126,8 @@ static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) // bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 -#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION) +// PyPy added PyFrame_GetCode() to PyPy3.12 v8.0.0 +#if PY_VERSION_HEX < 0x030900B1 || (defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030C0000) static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) { assert(frame != _Py_NULL); @@ -285,7 +286,8 @@ _PyThreadState_GetFrameBorrow(PyThreadState *tstate) // bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 -#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION) +// PyPy added PyInterpreterState_Get() to PyPy3.12 v8.0.0 +#if PY_VERSION_HEX < 0x030900A5 || (defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030C0000) static inline PyInterpreterState* PyInterpreterState_Get(void) { PyThreadState *tstate; @@ -2130,7 +2132,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 +2151,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/runtests.py b/runtests.py index bd9640c..2754616 100755 --- a/runtests.py +++ b/runtests.py @@ -48,6 +48,7 @@ "pypy3.9", "pypy3.10", "pypy3.11", + "pypy3.12", ) 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; } From d8893274b512ffea61a5d86290b1f8732568f353 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:54:23 +0300 Subject: [PATCH 6/6] Don't enable colour logging on CI Co-authored-by: Victor Stinner --- .github/workflows/build.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17625c3..0e8058c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,6 @@ name: Build on: [push, pull_request, workflow_dispatch] -env: - FORCE_COLOR: 1 - jobs: build: runs-on: ${{ matrix.os }}