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.
This commit is contained in:
Bastien Montagne
2025-01-03 12:12:42 +01:00
parent d48e73977c
commit 34908de285

View File

@@ -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 <https://discuss.python.org/t/cpython-usage-of-tp-finalize/64100>`__,
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 <https://stackoverflow.com/questions/36722390/python-3-super-del>`__,
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: