diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 9c9c97f7b853d8..7a6f55ae21dc90 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -100,7 +100,7 @@ rules: * :c:member:`~PyTypeObject.tp_alloc` -.. c:function:: PyObject* PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size) +.. c:function:: PyObject* PyObject_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size) Analogous to :c:macro:`PyObject_GC_New` but allocates *extra_size* bytes at the end of the object (at offset @@ -115,15 +115,18 @@ rules: :c:func:`PyObject_GC_Del` (usually called via the object's :c:member:`~PyTypeObject.tp_free` slot). - .. warning:: - The function is marked as unstable because the final mechanism - for reserving extra data after an instance is not yet decided. - For allocating a variable number of fields, prefer using - :c:type:`PyVarObject` and :c:member:`~PyTypeObject.tp_itemsize` - instead. + For allocating a variable number of fields, prefer using + :c:type:`PyVarObject` and :c:member:`~PyTypeObject.tp_itemsize` + instead. .. versionadded:: 3.12 + .. versionchanged:: 3.15 + The function is now part of the :ref:`limited API `. + + Previously, the function was named + ``PyUnstable_Object_GC_NewWithExtraData``. + .. c:macro:: PyObject_GC_Resize(TYPE, op, newsize) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index c3960d6ff87ec8..86f545decc8863 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -599,7 +599,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) :c:member:`!tp_itemsize` field. For a type with fixed-length instances, all instances have the same size, given in :c:member:`!tp_basicsize`. (Exceptions to this rule can be made using - :c:func:`PyUnstable_Object_GC_NewWithExtraData`.) + :c:func:`PyObject_GC_NewWithExtraData`.) For a type with variable-length instances, the instances must have an :c:member:`~PyVarObject.ob_size` field, and the instance size is diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 4a7fbdf60bfb43..2ba0a99eaf493d 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -585,6 +585,7 @@ func,PyObject_Free,3.2,, func,PyObject_GC_Del,3.2,, func,PyObject_GC_IsFinalized,3.9,, func,PyObject_GC_IsTracked,3.9,, +func,PyObject_GC_NewWithExtraData,3.15,, func,PyObject_GC_Track,3.2,, func,PyObject_GC_UnTrack,3.2,, func,PyObject_GenericGetAttr,3.2,, diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index e0c2ce286f13ce..fd502b1a8f2a05 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -83,8 +83,7 @@ PyAPI_FUNC(int) PyType_SUPPORTS_WEAKREFS(PyTypeObject *type); PyAPI_FUNC(PyObject **) PyObject_GET_WEAKREFS_LISTPTR(PyObject *op); -PyAPI_FUNC(PyObject *) PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *, - size_t); + /* Visit all live GC-capable objects, similar to gc.get_objects(None). The diff --git a/Include/objimpl.h b/Include/objimpl.h index 56472a72e42d34..731a16a2f03277 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -182,6 +182,8 @@ PyAPI_FUNC(void) PyObject_GC_Del(void *); #define PyObject_GC_NewVar(type, typeobj, n) \ _Py_CAST(type*, _PyObject_GC_NewVar((typeobj), (n))) +PyAPI_FUNC(PyObject *) PyObject_GC_NewWithExtraData(PyTypeObject *, size_t); + PyAPI_FUNC(int) PyObject_GC_IsTracked(PyObject *); PyAPI_FUNC(int) PyObject_GC_IsFinalized(PyObject *); diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index ed0868e0017fce..e421024a0199d2 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -573,6 +573,7 @@ def test_windows_feature_macros(self): "PyObject_GC_Del", "PyObject_GC_IsFinalized", "PyObject_GC_IsTracked", + "PyObject_GC_NewWithExtraData", "PyObject_GC_Track", "PyObject_GC_UnTrack", "PyObject_GenericGetAttr", diff --git a/Misc/NEWS.d/next/C_API/2026-04-13-00-00-00.gh-issue-148498.GCNewExtra.rst b/Misc/NEWS.d/next/C_API/2026-04-13-00-00-00.gh-issue-148498.GCNewExtra.rst new file mode 100644 index 00000000000000..68e63d2e860ed1 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-04-13-00-00-00.gh-issue-148498.GCNewExtra.rst @@ -0,0 +1,3 @@ +Rename :c:func:`!PyUnstable_Object_GC_NewWithExtraData` to +:c:func:`PyObject_GC_NewWithExtraData` and add it to the +:ref:`limited API `. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 606a0a88d26cf2..453b2748bab96e 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2706,3 +2706,5 @@ # Note: The `_reserved` member of this struct is for interal use only. # (The definition of 'full-abi' was clarified when this entry was added.) struct_abi_kind = 'full-abi' +[function.PyObject_GC_NewWithExtraData] + added = '3.15' diff --git a/Modules/_testcapi/gc.c b/Modules/_testcapi/gc.c index 863cb52980f942..69f035fcb923af 100644 --- a/Modules/_testcapi/gc.c +++ b/Modules/_testcapi/gc.c @@ -228,7 +228,7 @@ static PyObject * obj_extra_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { size_t extra_size = sizeof(PyObject *); - PyObject *obj = PyUnstable_Object_GC_NewWithExtraData(type, extra_size); + PyObject *obj = PyObject_GC_NewWithExtraData(type, extra_size); if (obj == NULL) { return PyErr_NoMemory(); } diff --git a/PC/python3dll.c b/PC/python3dll.c index abbe35c342c13e..3d43c9a91d7773 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -510,6 +510,7 @@ EXPORT_FUNC(PyObject_Free) EXPORT_FUNC(PyObject_GC_Del) EXPORT_FUNC(PyObject_GC_IsFinalized) EXPORT_FUNC(PyObject_GC_IsTracked) +EXPORT_FUNC(PyObject_GC_NewWithExtraData) EXPORT_FUNC(PyObject_GC_Track) EXPORT_FUNC(PyObject_GC_UnTrack) EXPORT_FUNC(PyObject_GenericGetAttr) diff --git a/Python/gc.c b/Python/gc.c index 284ac725d37ac6..5b0d48601bfdeb 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -2489,7 +2489,7 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) } PyObject * -PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) +PyObject_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) { size_t presize = _PyType_PreHeaderSize(tp); size_t size = _PyObject_SIZE(tp) + extra_size; diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 4b46ca04f56b20..90dd01948b1a0a 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -2983,7 +2983,7 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) } PyObject * -PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) +PyObject_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) { size_t presize = _PyType_PreHeaderSize(tp); size_t size = _PyObject_SIZE(tp) + extra_size;