При использовании типизации в коде, обращающемся к Blender Python API, обычно мы не сталкиваемся с какими-то проблемами. Однако указание типа возвращаемого значения для функции execute() оператора Blender, не совсем очевидно.
Мы знаем, что функция execute(), основная исполняемая функция любого оператора Blender, всегда возвращает сет, состоящий из одного строкового элемента.
Это может быть:
1 2 3 4 5 |
{"FINISHED"} {"RUNNING_MODAL"} {"CANCELLED"} {"PASS_THROUGH"} {"INTERFACE"} |
В общем случае, мы можем указать для функции execute() в качестве типа возвращаемого параметра set[‘str’]
1 2 |
def execute(self, context) -> set[str]: # some code |
Это будет работать. Однако мы можем немного улучшить восприятие кода, используя указание на rna_enums.OperatorReturnItems, если для автокомплита мы используем fake-bpy-module.
Описание типа возвращаемого функцией execute() оператора описано в fake-bpy-module в модуле bpy\_typing\rna_enums
1 2 3 4 5 6 7 |
type OperatorReturnItems = typing.Literal[ "RUNNING_MODAL", # Running Modal.Keep the operator running with blender. "CANCELLED", # Cancelled.The operator exited without doing anything, so no undo entry should be pushed. "FINISHED", # Finished.The operator exited after completing its action. "PASS_THROUGH", # Pass Through.Do nothing and pass the event on. "INTERFACE", # Interface.Handled but not executed (popup menus). ] |
Дальнейшая информация предоставлена Andrej (Andrej730)
По сути bpy._typing еще более фейковый, чем весь модуль fake-bpy-module, и вообще не существует в реальном Blender API.
Поэтому нужно убедиться, что он никогда не используется во время выполнения.
Импортируйте его только внутри блока TYPE_CHECKING.
Ссылайтесь на него только с помощью кавычек, чтобы он не был оценен.
Причина, по которой нужны эти махинации, — это компромисс между реалиями Blender и системой типизации Python.
fake-bpy-module предоставляет точные возможные значения перечисления для таких вещей, как возможные возвращаемые значения, но для этого требуются те статические вещи, которые доступны только во время выполнения.
Пример кода с оформлением возвращаемого значения функции execute() оператора:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import bpy from typing import TYPE_CHECKING if TYPE_CHECKING: import bpy._typing.rna_enums as rna_enums class SimpleOperator(bpy.types.Operator): bl_idname = "wm.simple_operator" bl_label = "Simple Operator" def execute(self, context) -> set["rna_enums.OperatorReturnItems"]: print("Hello from the simplest operator!") return {"FINISHED"} # Register the operator bpy.utils.register_class(SimpleOperator) |
Обновление (04.06.2025) Andrej (Andrej730)
В последней версии fake-bpy-module модуль bpy._typing заменен на bpy.stub_internal.
Для правильной работы автокомплита теперь вместо bpy._typing нужно указывать bpy.stub_internal. В примере выше это будет выглядеть следующим образом:
Вместо:
1 |
import bpy._typing.rna_enums as rna_enums |
Нужно писать:
1 |
import bpy.stub_internal.rna_enums as rna_enums |
Весь остальной код остается без изменений.