From 34908de28591cb0e59bf20dcfe9897cac0bf2583 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Jan 2025 12:12:42 +0100 Subject: [PATCH] Update BPY API 'creation & destruction' section re __del__(). While in theory it would be good to have calls to super classes' `__del__()` destructors in subclasses, matching the ones to `__init__()`, several limitations of current CPython implementation do not make it a practical requirement. So remove `__del__` from examples, and add a note summarizing the current problems with using it (aka `tp_finalize` in C++ code). Also see !132476 for some discussion about that topic. --- doc/python_api/rst/info_overview.rst | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 78b8310f606..b3f00641edf 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -192,9 +192,9 @@ have a new instance for every redraw. Some other types, like :class:`bpy.types.Operator`, have an even more complex internal handling, which can lead to several instantiations for a single operator execution. -There are a few cases where defining ``__init__()`` and ``__del__()`` does make sense, -e.g. when sub-classing a :class:`bpy.types.RenderEngine`. When doing so, the parent matching function -must always be called, otherwise Blender's internal initialization won't happen properly: +There are a few cases where defining ``__init__()`` does make sense, e.g. when sub-classing a +:class:`bpy.types.RenderEngine`. When doing so, the parent matching function must always be called, +otherwise Blender's internal initialization won't happen properly: .. code-block:: python @@ -204,10 +204,6 @@ must always be called, otherwise Blender's internal initialization won't happen super().__init__(*args, **kwargs) ... - def __del__(self): - ... - super().__del__() - .. note:: Calling the parent's ``__init__()`` function is a hard requirement since Blender 4.4. @@ -215,7 +211,6 @@ must always be called, otherwise Blender's internal initialization won't happen the only caller of these functions. The actual arguments passed to the constructor are fully internal data, and may change depending on the implementation. - .. note:: Defining a custom ``__new__()`` function is strongly discouraged, not tested, and not considered @@ -224,6 +219,21 @@ must always be called, otherwise Blender's internal initialization won't happen But if defined, it must take the same two generic positional and keyword arguments, and call the parent's ``__new__()`` with them if actually creating a new object. +.. note:: + + Due to internal + `CPython implementation details `__, + C++-defined Blender types do not define or use a ``__del__()`` (aka ``tp_finalize()``) destructor + currently. + As this function + `does not exist if not explicitely defined `__, + that means that calling ``super().__del__()`` in the ``__del__()`` function of a sub-class will + fail with the following error: + ``AttributeError: 'super' object has no attribute '__del__'``. + If a call to the MRO 'parent' destructor is needed for some reason, the caller code must ensure + that the destructor does exist, e.g. using something like that: + ``getattr(super(), "__del__", lambda self: None)(self)`` + .. _info_overview_registration: