From fcc1c89923d2715c610d29c1c26772f5dce4f70a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 19 Nov 2024 12:59:42 +0100 Subject: [PATCH] API Doc: improvements/fixes regarding new requirements for __init__/__del__ --- doc/python_api/examples/bpy.types.Operator.6.py | 8 +++++--- .../examples/bpy.types.RenderEngine.1.py | 9 +++++++-- doc/python_api/rst/info_overview.rst | 17 +++++++++++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/doc/python_api/examples/bpy.types.Operator.6.py b/doc/python_api/examples/bpy.types.Operator.6.py index f3f2a53b3c7..40a40a19516 100644 --- a/doc/python_api/examples/bpy.types.Operator.6.py +++ b/doc/python_api/examples/bpy.types.Operator.6.py @@ -19,6 +19,8 @@ by returning ``{'RUNNING_MODAL'}``, initializing the modal loop. Notice ``__init__()`` and ``__del__()`` are declared. For other operator types they are not useful but for modal operators they will be called before the :class:`Operator.invoke` and after the operator finishes. +Also see the +:ref:`class construction and destruction section ` """ import bpy @@ -28,13 +30,13 @@ class ModalOperator(bpy.types.Operator): bl_label = "Simple Modal Operator" bl_options = {'REGISTER', 'UNDO'} - def __init__(self): - super().__init__() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) print("Start") def __del__(self): - super().__del__() print("End") + super().__del__() def execute(self, context): context.object.location.x = self.value / 100.0 diff --git a/doc/python_api/examples/bpy.types.RenderEngine.1.py b/doc/python_api/examples/bpy.types.RenderEngine.1.py index 6c2558f85cf..6ccc55bdc73 100644 --- a/doc/python_api/examples/bpy.types.RenderEngine.1.py +++ b/doc/python_api/examples/bpy.types.RenderEngine.1.py @@ -17,14 +17,19 @@ class CustomRenderEngine(bpy.types.RenderEngine): # Init is called whenever a new render engine instance is created. Multiple # instances may exist at the same time, for example for a viewport and final # render. - def __init__(self): + # Note the generic arguments signature, and the call to the parent class + # `__init__` methods, which are required for Blender to create the underlying + # `RenderEngine` data. + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.scene_data = None self.draw_data = None # When the render engine instance is destroy, this is called. Clean up any # render engine data here, for example stopping running render threads. def __del__(self): - pass + # Own delete code... + super().__del__() # This is the method called by Blender for both final renders (F12) and # small preview for materials, world and lights. diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 23a6659269f..7e1df042f82 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -178,6 +178,8 @@ User interface classes are given a context in which to draw, buttons, window, fi then they are drawn when that area is displayed so they are never called by Python scripts directly. +.. _info_overview_class_construction_destruction: + Construction & Destruction -------------------------- @@ -194,7 +196,6 @@ There are a few cases where defining ``__init__()`` and ``__del__()`` does make 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 import bpy @@ -209,7 +210,19 @@ must always be called, otherwise Blender's internal initialization won't happen .. note:: - Calling the parent's ``__init__()`` function is a hard requirement since Blender 4.4. + Calling the parent's ``__init__()`` function is a hard requirement since Blender 4.4. + The 'generic' signature is the recommended one here, as Blender internal BPY code is typically + 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 + as supported currently. + Doing so presents a very high risk of crashes or otherwise corruption of Blender internal data. + 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. .. _info_overview_registration: