Skip to content

Commit 3ccded6

Browse files
add support for 3.13
1 parent 9103321 commit 3ccded6

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

docs/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ 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.14 and newer, not available on PyPy.
77+
Availability: Python 3.13 and newer, not available on PyPy.
7878

7979
Python 3.14
8080
-----------

pythoncapi_compat.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,11 +2659,11 @@ PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op)
26592659
}
26602660
#endif
26612661

2662-
#if 0x030E0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION)
2662+
#if 0x030D0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION)
26632663
// Immortal objects were implemented in Python 3.12, however there is no easy API
26642664
// to make objects immortal until 3.14 which has _Py_SetImmortal(). Since
26652665
// immortal objects are primarily needed for free-threading, this API is implemented
2666-
// for 3.14 and above.
2666+
// for 3.14 using _Py_SetImmortal() and uses private macros on 3.13.
26672667
static inline int
26682668
PyUnstable_SetImmortal(PyObject *op)
26692669
{
@@ -2673,7 +2673,21 @@ PyUnstable_SetImmortal(PyObject *op)
26732673
if (!PyUnstable_Object_IsUniquelyReferenced(op) || PyUnicode_Check(op)) {
26742674
return 0;
26752675
}
2676-
_Py_SetImmortal(op);
2676+
#if 0x030E0000 <= PY_VERSION_HEX
2677+
_Py_SetImmortal(op);
2678+
#else
2679+
// Python 3.13 doesn't export _Py_SetImmortal() function
2680+
if (PyObject_GC_IsTracked(op)) {
2681+
PyObject_GC_UnTrack(op);
2682+
}
2683+
#ifdef Py_GIL_DISABLED
2684+
op->ob_tid = _Py_UNOWNED_TID;
2685+
op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
2686+
op->ob_ref_shared = 0;
2687+
#else
2688+
op->ob_refcnt = _Py_IMMORTAL_REFCNT;
2689+
#endif
2690+
#endif
26772691
return 1;
26782692
}
26792693
#endif

tests/test_pythoncapi_compat_cext.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,7 +2489,7 @@ test_try_incref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
24892489
Py_RETURN_NONE;
24902490
}
24912491

2492-
#if 0x030E0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
2492+
#if 0x030D0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
24932493
static PyObject *
24942494
test_set_immortal(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
24952495
{
@@ -2579,7 +2579,7 @@ static struct PyMethodDef methods[] = {
25792579
{"test_byteswriter", test_byteswriter, METH_NOARGS, _Py_NULL},
25802580
{"test_tuple", test_tuple, METH_NOARGS, _Py_NULL},
25812581
{"test_try_incref", test_try_incref, METH_NOARGS, _Py_NULL},
2582-
#if 0x030E0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
2582+
#if 0x030D0000 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
25832583
{"test_set_immortal", test_set_immortal, METH_NOARGS, _Py_NULL},
25842584
#endif
25852585
{_Py_NULL, _Py_NULL, 0, _Py_NULL}

0 commit comments

Comments
 (0)