From 33f166d4ca9535471b3d6ba2173237fafa900378 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 29 Jul 2022 23:42:07 +0800 Subject: [PATCH 1/4] Document Py_TPFLAGS_MANAGED_DICT and friends --- Doc/c-api/gcsupport.rst | 23 +++++++++++++++++++++++ Doc/c-api/typeobj.rst | 14 ++++++++++++++ Doc/whatsnew/3.11.rst | 9 +++++++++ 3 files changed, 46 insertions(+) diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 8c90d1e8991c10..451be99d63cd98 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -129,6 +129,29 @@ rules: The :c:func:`_PyObject_GC_TRACK` and :c:func:`_PyObject_GC_UNTRACK` macros have been removed from the public C API. +.. c:function:: int _PyObject_VisitManagedDict(PyObject *self, visitproc visit, void *arg) + + Visitor function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. + Call this function in c:member:`~PyTypeObject.tp_traverse`. The arguments + share the same meaning as the arguments of c:member:`~PyTypeObject.tp_traverse`. + A non-zero return value indicates an error and that returned value should be + returned immediately. + + .. warning:: This function is unstable and may change with time. + + .. versionadded:: 3.11 + +.. c:function:: void _PyObject_ClearManagedDict(PyObject *self) + + Inquiry function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. + Call this function in c:member:`~PyTypeObject.tp_clear`. + + This is analogous to the Python function :func:`gc.is_finalized`. + + .. warning:: This function is unstable and may change with time. + + .. versionadded:: 3.11 + The :c:member:`~PyTypeObject.tp_traverse` handler accepts a function parameter of this type: diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 7514801f2d4d59..a07765b0eaa775 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1260,6 +1260,20 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.10 + .. data:: Py_TPFLAGS_MANAGED_DICT + + Set this bit to allow CPython to automatically manage the ``__dict__`` + of the instances of a type. To tell CPython to clear the managed + dictionary, you must call + :c:func:`_PyObject_VisitManagedDict` in :c:member:`~PyTypeObject.tp_traverse` + and :c:func:`_PyObject_ClearManagedDict` in :c:member:`~PyTypeObject.tp_clear` + respectively. + + **Inheritance:** + + ??? + + .. versionadded:: 3.11 .. c:member:: const char* PyTypeObject.tp_doc diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 1b3a685dbacb91..52e99332599e45 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1927,6 +1927,15 @@ Porting to Python 3.11 paths and then modify them, finish initialization and use :c:func:`PySys_GetObject` to retrieve :data:`sys.path` as a Python list object and modify it directly. +* CPython no longer assumes that a ``__dict__`` exists after an object. C extension + types with inheritance and ``__dict__`` may have MRO problems. To fix this, allow + CPython to manage the ``__dict__`` of instances of your type by setting + :const:`Py_TPFLAGS_MANAGED_DICT` in :c:member:`~PyTypeObject.tp_flags`. + You must call :c:func:`_PyObject_VisitManagedDict` and + :c:func:`_PyObject_ClearManagedDict` to support GC collection. See the + respective functions for more information on how to use them. + (Contributed by Mark Shannon in :gh:`92678`.) + Deprecated ---------- From 3e28e0f88605cdc49c72710a2c06a3ef56b6c801 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 29 Jul 2022 23:43:38 +0800 Subject: [PATCH 2/4] remove unneeded line --- Doc/c-api/gcsupport.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 451be99d63cd98..c30a3ea12c9271 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -146,8 +146,6 @@ rules: Inquiry function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. Call this function in c:member:`~PyTypeObject.tp_clear`. - This is analogous to the Python function :func:`gc.is_finalized`. - .. warning:: This function is unstable and may change with time. .. versionadded:: 3.11 From efd504c0fa5deed327fa91ecf267ac35c4a1ad52 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 29 Jul 2022 23:55:59 +0800 Subject: [PATCH 3/4] fix invalid rst --- Doc/c-api/gcsupport.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index c30a3ea12c9271..c99f9f83fcf568 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -129,6 +129,7 @@ rules: The :c:func:`_PyObject_GC_TRACK` and :c:func:`_PyObject_GC_UNTRACK` macros have been removed from the public C API. + .. c:function:: int _PyObject_VisitManagedDict(PyObject *self, visitproc visit, void *arg) Visitor function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. @@ -141,6 +142,7 @@ rules: .. versionadded:: 3.11 + .. c:function:: void _PyObject_ClearManagedDict(PyObject *self) Inquiry function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. From 5c2573c9a809e325d881e0c03678629be350fb47 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 30 Jul 2022 00:10:17 +0800 Subject: [PATCH 4/4] fix rst again --- Doc/c-api/gcsupport.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index c99f9f83fcf568..ce6ab2a62e38be 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -133,8 +133,8 @@ rules: .. c:function:: int _PyObject_VisitManagedDict(PyObject *self, visitproc visit, void *arg) Visitor function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. - Call this function in c:member:`~PyTypeObject.tp_traverse`. The arguments - share the same meaning as the arguments of c:member:`~PyTypeObject.tp_traverse`. + Call this function in :c:member:`~PyTypeObject.tp_traverse`. The arguments + share the same meaning as the arguments of :c:member:`~PyTypeObject.tp_traverse`. A non-zero return value indicates an error and that returned value should be returned immediately. @@ -146,7 +146,7 @@ rules: .. c:function:: void _PyObject_ClearManagedDict(PyObject *self) Inquiry function for types with :const:`Py_TPFLAGS_MANAGED_DICT` bit set. - Call this function in c:member:`~PyTypeObject.tp_clear`. + Call this function in :c:member:`~PyTypeObject.tp_clear`. .. warning:: This function is unstable and may change with time.