From 4b82c871e332f7331d07cf70c8f0886a0c824089 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 10 Apr 2026 09:21:50 +0200 Subject: [PATCH] gh-148325: Add PyObject_GetItemData to the limited C API and stable ABI Move PyObject_GetItemData and PyObject_GetItemData_DuringGC from the unstable CPython API (Include/cpython/object.h) to the limited C API (Include/object.h), gated on Py_LIMITED_API >= 3.15, and declare them as part of the stable ABI in Misc/stable_abi.toml. --- Doc/c-api/object.rst | 4 ++++ Doc/data/stable_abi.dat | 2 ++ Include/cpython/object.h | 3 --- Include/object.h | 4 ++++ Lib/test/test_stable_abi_ctypes.py | 2 ++ .../C_API/2026-04-10-12-00-00.gh-issue-145921.aBcDeF.rst | 2 ++ Misc/stable_abi.toml | 5 +++++ PC/python3dll.c | 2 ++ 8 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-04-10-12-00-00.gh-issue-145921.aBcDeF.rst diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index eedeb180c6b760..194582adf91d25 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -624,6 +624,10 @@ Object Protocol .. versionadded:: 3.12 + .. versionchanged:: 3.15 + + Added to the limited C API. + .. c:function:: int PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) Visit the managed dictionary of *obj*. diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 4a7fbdf60bfb43..58cf3d7595d292 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -596,6 +596,8 @@ func,PyObject_GetAttr,3.2,, func,PyObject_GetAttrString,3.2,, func,PyObject_GetBuffer,3.11,, func,PyObject_GetItem,3.2,, +func,PyObject_GetItemData,3.15,, +func,PyObject_GetItemData_DuringGC,3.15,, func,PyObject_GetIter,3.2,, func,PyObject_GetOptionalAttr,3.13,, func,PyObject_GetOptionalAttrString,3.13,, diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 80d30c7765fdb0..32cef2655d47e4 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -441,9 +441,6 @@ PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate); #define Py_TRASHCAN_END -PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); -PyAPI_FUNC(void *) PyObject_GetItemData_DuringGC(PyObject *obj); - PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj); diff --git a/Include/object.h b/Include/object.h index e33f92295fb771..11aabae796f942 100644 --- a/Include/object.h +++ b/Include/object.h @@ -355,6 +355,9 @@ PyAPI_FUNC(PyObject *) PyType_FromMetaclass(PyTypeObject*, PyObject*, PyType_Spe PyAPI_FUNC(void *) PyObject_GetTypeData(PyObject *obj, PyTypeObject *cls); PyAPI_FUNC(Py_ssize_t) PyType_GetTypeDataSize(PyTypeObject *cls); #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15) +PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); +#endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030E0000 PyAPI_FUNC(int) PyType_GetBaseByToken(PyTypeObject *, void *, PyTypeObject **); #define Py_TP_USE_SPEC NULL @@ -781,6 +784,7 @@ PyAPI_FUNC(PyObject *) PyType_GetModuleByToken(PyTypeObject *type, const void *token); PyAPI_FUNC(void *) PyObject_GetTypeData_DuringGC(PyObject *obj, PyTypeObject *cls); +PyAPI_FUNC(void *) PyObject_GetItemData_DuringGC(PyObject *obj); PyAPI_FUNC(void *) PyType_GetModuleState_DuringGC(PyTypeObject *); PyAPI_FUNC(int) PyType_GetBaseByToken_DuringGC(PyTypeObject *, void *, PyTypeObject **); diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index ed0868e0017fce..6859414b030791 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -584,6 +584,8 @@ def test_windows_feature_macros(self): "PyObject_GetAttrString", "PyObject_GetBuffer", "PyObject_GetItem", + "PyObject_GetItemData", + "PyObject_GetItemData_DuringGC", "PyObject_GetIter", "PyObject_GetOptionalAttr", "PyObject_GetOptionalAttrString", diff --git a/Misc/NEWS.d/next/C_API/2026-04-10-12-00-00.gh-issue-145921.aBcDeF.rst b/Misc/NEWS.d/next/C_API/2026-04-10-12-00-00.gh-issue-145921.aBcDeF.rst new file mode 100644 index 00000000000000..3f2945c706eedf --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-04-10-12-00-00.gh-issue-145921.aBcDeF.rst @@ -0,0 +1,2 @@ +Add :c:func:`PyObject_GetItemData` and +:c:func:`PyObject_GetItemData_DuringGC` to the limited C API and stable ABI. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 606a0a88d26cf2..21da179a27e5d0 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2666,8 +2666,13 @@ [function.Py_SET_SIZE] # Before 3.15, this was a macro that accessed the PyObject member added = '3.15' +[function.PyObject_GetItemData] + # Before 3.15, this was only available in the unstable CPython API + added = '3.15' [function.PyObject_GetTypeData_DuringGC] added = '3.15' +[function.PyObject_GetItemData_DuringGC] + added = '3.15' [function.PyType_GetModuleState_DuringGC] added = '3.15' [function.PyModule_GetState_DuringGC] diff --git a/PC/python3dll.c b/PC/python3dll.c index abbe35c342c13e..afffb5f3206a0f 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -521,6 +521,8 @@ EXPORT_FUNC(PyObject_GetAttr) EXPORT_FUNC(PyObject_GetAttrString) EXPORT_FUNC(PyObject_GetBuffer) EXPORT_FUNC(PyObject_GetItem) +EXPORT_FUNC(PyObject_GetItemData) +EXPORT_FUNC(PyObject_GetItemData_DuringGC) EXPORT_FUNC(PyObject_GetIter) EXPORT_FUNC(PyObject_GetOptionalAttr) EXPORT_FUNC(PyObject_GetOptionalAttrString)