diff --git a/src/bonsai/bonsai/bim/handler.py b/src/bonsai/bonsai/bim/handler.py index e0465be288..dc8c3bf7c5 100644 --- a/src/bonsai/bonsai/bim/handler.py +++ b/src/bonsai/bonsai/bim/handler.py @@ -32,14 +32,14 @@ from bonsai.bim.module.model.data import AuthoringData from bonsai.bim.module.model.workspace import LIST_OF_TOOLS, TOOLS_TO_CLASSES_MAP from mathutils import Vector from math import cos, degrees -from typing import Union +from typing import Union, Callable cwd = os.path.dirname(os.path.realpath(__file__)) global_subscription_owner = object() -def name_callback(obj, data): +def name_callback(obj: Union[bpy.types.Object, bpy.types.Material], data: str) -> None: try: obj.name except: @@ -150,7 +150,7 @@ def active_material_index_callback(obj, data): refresh_ui_data() -def subscribe_to(obj, data_path, callback): +def subscribe_to(obj: bpy.types.ID, data_path: str, callback: Callable[[bpy.types.ID, str], None]): try: subscribe_to = obj.path_resolve(data_path, False) except: diff --git a/src/bonsai/bonsai/bim/helper.py b/src/bonsai/bonsai/bim/helper.py index 37443df6a0..988a0a1885 100644 --- a/src/bonsai/bonsai/bim/helper.py +++ b/src/bonsai/bonsai/bim/helper.py @@ -272,13 +272,17 @@ def get_enum_items( ) -> Union[ Iterable[Union[tuple[str, str, str], tuple[str, str, str, int], tuple[str, str, str, str, int], None]], None ]: - # Retrieve items from a dynamic EnumProperty, which is otherwise not supported - # Or throws an error in the console when the items callback returns an empty list - # See https://blender.stackexchange.com/q/215781/86891 + """Retrieve items from a dynamic EnumProperty. + + Otherwise it's not supported or throws an error in the console when the items callback returns an empty list. + See https://blender.stackexchange.com/q/215781/86891 + + :param original_operator_path: python path to the original operator class. Needed only if `data` is `bpy.types.Operator`. + """ # OperatorProperties is missing __annotations__, so need to somehow provide original Operator. # Couldn't find any way to get Operator from OperatorProperties, so we provide the path explicitly. - # E.g. OpeartorProperties occur when Operator is passed with context_pointer_set. + # E.g. OperatorProperties occur when Operator is passed with context_pointer_set. if isinstance(data, bpy.types.OperatorProperties): if not original_operator_path: raise Exception("For OperatorProperties providing the original operator path is required.") diff --git a/src/bonsai/bonsai/bim/ifc.py b/src/bonsai/bonsai/bim/ifc.py index 358ef37aef..6e4c3d27a9 100644 --- a/src/bonsai/bonsai/bim/ifc.py +++ b/src/bonsai/bonsai/bim/ifc.py @@ -48,7 +48,7 @@ class OperationData(TypedDict): class Operation(TypedDict): rollback: Callable commit: Callable - data: OperationData + data: Union[OperationData, None] class TransactionStep(TypedDict): @@ -197,7 +197,7 @@ class IfcStore: return IfcStore.schema @staticmethod - def get_element(id_or_guid: Union[int, str]) -> IFC_CONNECTED_TYPE: + def get_element(id_or_guid: Union[int, str]) -> Union[IFC_CONNECTED_TYPE, None]: if isinstance(id_or_guid, int): obj = IfcStore.id_map.get(id_or_guid) else: @@ -385,7 +385,7 @@ class IfcStore: obj.BIMObjectProperties.ifc_definition_id = 0 @staticmethod - def execute_ifc_operator(operator: bpy.types.Operator, context: bpy.types.Context, is_invoke=False): + def execute_ifc_operator(operator: tool.Ifc.Operator, context: bpy.types.Context, is_invoke=False) -> set[str]: bonsai.last_actions.append({"type": "operator", "name": operator.bl_idname}) bpy.context.scene.BIMProperties.is_dirty = True is_top_level_operator = not bool(IfcStore.current_transaction) @@ -424,17 +424,19 @@ class IfcStore: return result @staticmethod - def begin_transaction(operator: bpy.types.Operator) -> None: + def begin_transaction(operator: tool.Ifc.Operator) -> None: IfcStore.current_transaction = str(uuid.uuid4()) operator.transaction_key = IfcStore.current_transaction @staticmethod - def end_transaction(operator: bpy.types.Operator) -> None: + def end_transaction(operator: tool.Ifc.Operator) -> None: IfcStore.current_transaction = "" operator.transaction_key = "" @staticmethod - def add_transaction_operation(operator: bpy.types.Operator, rollback=None, commit=None) -> None: + def add_transaction_operation( + operator: tool.Ifc.Operator, rollback: Optional[Callable] = None, commit: Optional[Callable] = None + ) -> None: key = getattr(operator, "transaction_key", None) data = getattr(operator, "transaction_data", None) bpy.context.scene.BIMProperties.last_transaction = key @@ -442,10 +444,10 @@ class IfcStore: rollback = rollback or getattr(operator, "rollback", lambda data: True) commit = commit or getattr(operator, "commit", lambda data: True) if IfcStore.history and IfcStore.history[-1]["key"] == key: - IfcStore.history[-1]["operations"].append(OperationData(rollback=rollback, commit=commit, data=data)) + IfcStore.history[-1]["operations"].append(Operation(rollback=rollback, commit=commit, data=data)) else: IfcStore.history.append( - TransactionStep(key=key, operations=[OperationData(rollback=rollback, commit=commit, data=data)]) + TransactionStep(key=key, operations=[Operation(rollback=rollback, commit=commit, data=data)]) ) IfcStore.future = [] diff --git a/src/bonsai/bonsai/tool/ifc.py b/src/bonsai/bonsai/tool/ifc.py index 1a12773b91..dca7fbc447 100644 --- a/src/bonsai/bonsai/tool/ifc.py +++ b/src/bonsai/bonsai/tool/ifc.py @@ -265,6 +265,9 @@ class Ifc(bonsai.core.tool.Ifc): IFC changes for Undo system. """ + transaction_key = "" + transaction_data: Union[Any, None] = None + @final def execute(self, context): IfcStore.execute_ifc_operator(self, context)