From c4b57eb9037811a3e96a6af97211aad740a2672e Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 7 Mar 2025 20:38:01 +0500 Subject: [PATCH] typing --- src/bonsai/bonsai/bim/module/style/prop.py | 4 +- .../bonsai/bim/module/system/decorator.py | 3 +- .../bonsai/bim/module/system/operator.py | 8 ++-- src/bonsai/bonsai/bim/module/system/prop.py | 11 ++++- src/bonsai/bonsai/bim/module/system/ui.py | 47 ++++++++++++++----- src/bonsai/bonsai/tool/system.py | 3 +- src/bonsai/scripts/bonsai_translations.py | 9 ++-- src/bonsai/test/tool/test_system.py | 22 +++++---- .../api/system/unassign_system.py | 10 +--- 9 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/style/prop.py b/src/bonsai/bonsai/bim/module/style/prop.py index d533473ba2..7daf36f0c4 100644 --- a/src/bonsai/bonsai/bim/module/style/prop.py +++ b/src/bonsai/bonsai/bim/module/style/prop.py @@ -284,8 +284,8 @@ class BIMStylesProperties(PropertyGroup): active_style_index: IntProperty(name="Active Style Index") @property - def active_style(self): - return self.styles[self.active_style_index] if 0 <= self.active_style_index < len(self.styles) else None + def active_style(self) -> Union[Style, None]: + return tool.Blender.get_active_uilist_element(self.styles, self.active_style_index) active_style_type: EnumProperty( name="Active Style Type", diff --git a/src/bonsai/bonsai/bim/module/system/decorator.py b/src/bonsai/bonsai/bim/module/system/decorator.py index 3f902d0407..a463aae2e9 100644 --- a/src/bonsai/bonsai/bim/module/system/decorator.py +++ b/src/bonsai/bonsai/bim/module/system/decorator.py @@ -41,7 +41,8 @@ def transparent_color(color, alpha=0.1): @persistent def toggle_decorations_on_load(*args): - if bpy.context.scene.BIMSystemProperties.should_draw_decorations: + props = tool.System.get_system_props() + if props.should_draw_decorations: SystemDecorator.install(bpy.context) else: SystemDecorator.uninstall() diff --git a/src/bonsai/bonsai/bim/module/system/operator.py b/src/bonsai/bonsai/bim/module/system/operator.py index 25f3c9d00a..597c4153c3 100644 --- a/src/bonsai/bonsai/bim/module/system/operator.py +++ b/src/bonsai/bonsai/bim/module/system/operator.py @@ -50,7 +50,8 @@ class AddSystem(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - core.add_system(tool.Ifc, tool.System, ifc_class=context.scene.BIMSystemProperties.system_class) + props = tool.System.get_system_props() + core.add_system(tool.Ifc, tool.System, ifc_class=props.system_class) class EditSystem(bpy.types.Operator, tool.Ifc.Operator): @@ -59,9 +60,8 @@ class EditSystem(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - core.edit_system( - tool.Ifc, tool.System, system=tool.Ifc.get().by_id(context.scene.BIMSystemProperties.edited_system_id) - ) + props = tool.System.get_system_props() + core.edit_system(tool.Ifc, tool.System, system=tool.Ifc.get().by_id(props.edited_system_id)) class RemoveSystem(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/bonsai/bonsai/bim/module/system/prop.py b/src/bonsai/bonsai/bim/module/system/prop.py index 3e14bf74e5..bd4ccc238a 100644 --- a/src/bonsai/bonsai/bim/module/system/prop.py +++ b/src/bonsai/bonsai/bim/module/system/prop.py @@ -34,7 +34,7 @@ from bpy.props import ( from typing import TYPE_CHECKING -def get_system_class(self, context): +def get_system_class(self: "BIMSystemProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]: if not SystemData.is_loaded: SystemData.load() return SystemData.data["system_class"] @@ -45,13 +45,20 @@ class System(PropertyGroup): ifc_class: StringProperty(name="IFC Class") ifc_definition_id: IntProperty(name="IFC Definition ID") + if TYPE_CHECKING: + ifc_class: str + ifc_definition_id: int + class Zone(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") + if TYPE_CHECKING: + ifc_definition_id: int -def toggle_decorations(self, context): + +def toggle_decorations(self: "BIMSystemProperties", context: bpy.types.Context) -> None: toggle = self.should_draw_decorations if toggle: decorator.SystemDecorator.install(context) diff --git a/src/bonsai/bonsai/bim/module/system/ui.py b/src/bonsai/bonsai/bim/module/system/ui.py index 8c3d00dceb..432cf1b76a 100644 --- a/src/bonsai/bonsai/bim/module/system/ui.py +++ b/src/bonsai/bonsai/bim/module/system/ui.py @@ -16,12 +16,17 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . +from __future__ import annotations import bpy import bonsai.bim.helper import bonsai.tool as tool from bonsai.bim.helper import prop_with_search, draw_attributes from bpy.types import Panel, UIList from bonsai.bim.module.system.data import SystemData, ZonesData, ActiveObjectZonesData, ObjectSystemData, PortData +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from bonsai.bim.module.system.prop import BIMSystemProperties, System, BIMZoneProperties, Zone FLOW_DIRECTION_TO_ICON = { @@ -69,7 +74,7 @@ class BIM_PT_systems(Panel): op = row.operator("bim.unassign_system", text="", icon="X") op.system = system_id - self.props = context.scene.BIMSystemProperties + self.props = tool.System.get_system_props() row = self.layout.row(align=True) row.prop(self.props, "should_draw_decorations") @@ -142,7 +147,8 @@ class BIM_PT_ports(Panel): def draw(self, context): if not PortData.is_loaded: PortData.load() - self.props = context.scene.BIMSystemProperties + + self.props = tool.System.get_system_props() row = self.layout.row(align=True) total_ports = PortData.data["total_ports"] @@ -217,7 +223,7 @@ class BIM_PT_port(Panel): return True def draw(self, context): - self.props = context.scene.BIMSystemProperties + self.props = tool.System.get_system_props() layout = self.layout row = layout.row(align=True) @@ -295,7 +301,7 @@ class BIM_PT_flow_controls(Panel): if not ObjectSystemData.is_loaded: ObjectSystemData.load() - def display_element(control_id, flow_element_id, displayed_object_name): + def display_element(control_id: int, flow_element_id: int, displayed_object_name: str) -> None: displayed_object = bpy.data.objects[displayed_object_name] row = self.layout.row(align=True) op = row.operator("bim.assign_unassign_flow_control", text="", icon="X") @@ -355,13 +361,14 @@ class BIM_PT_zones(Panel): row.operator("bim.load_zones", text="", icon="IMPORT") return - row.operator("bim.add_zone", text="", icon="ADD") row.operator("bim.unload_zones", text="", icon="CANCEL") + row = self.layout.row(align=True) + row.alignment = "RIGHT" + row.operator("bim.add_zone", text="", icon="ADD") if self.props.zones and self.props.active_zone_index < len(self.props.zones): - row = self.layout.row(align=True) ifc_definition_id = self.props.zones[self.props.active_zone_index].ifc_definition_id - row.operator("bim.enable_editing_zone", text="Edit Zone", icon="GREASEPENCIL").zone = ifc_definition_id + row.operator("bim.enable_editing_zone", text="", icon="GREASEPENCIL").zone = ifc_definition_id row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF").system = ifc_definition_id row.operator("bim.assign_system", text="", icon="KEYFRAME_HLT").system = ifc_definition_id row.operator("bim.unassign_system", text="", icon="KEYFRAME").system = ifc_definition_id @@ -403,18 +410,27 @@ class BIM_PT_active_object_zones(Panel): class BIM_UL_systems(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, + context, + layout: bpy.types.UILayout, + data: BIMSystemProperties, + item: System, + icon, + active_data, + active_propname, + ): if item: row = layout.row(align=True) row.label(text=item.name, icon=SYSTEM_ICONS[item.ifc_class]) system_id = item.ifc_definition_id row.operator("bim.assign_system", text="", icon="ADD").system = item.ifc_definition_id - if context.scene.BIMSystemProperties.edited_system_id == system_id: + if data.edited_system_id == system_id: op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op.system = system_id row.operator("bim.edit_system", text="", icon="CHECKMARK") row.operator("bim.disable_editing_system", text="", icon="CANCEL") - elif context.scene.BIMSystemProperties.edited_system_id: + elif data.edited_system_id: op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF") op.system = system_id op = row.operator("bim.remove_system", text="", icon="X") @@ -429,7 +445,16 @@ class BIM_UL_systems(UIList): class BIM_UL_zones(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, + context, + layout: bpy.types.UILayout, + data: BIMZoneProperties, + item: Zone, + icon, + active_data, + active_propname, + ): if item: row = layout.row(align=True) row.label(text=item.name) diff --git a/src/bonsai/bonsai/tool/system.py b/src/bonsai/bonsai/tool/system.py index b7eae11989..e167ffca3a 100644 --- a/src/bonsai/bonsai/tool/system.py +++ b/src/bonsai/bonsai/tool/system.py @@ -30,12 +30,11 @@ import re from math import pi, cos, sin from mathutils import Matrix, Vector from bonsai.bim.module.system.data import ObjectSystemData, SystemDecorationData -from bonsai.bim.module.drawing.decoration import profile_consequential from enum import Enum from typing import TYPE_CHECKING, Optional, Any, Union if TYPE_CHECKING: - from bonsai.bim.module.system.prop import BIMSystemProperties, BIMZoneProperties + from bonsai.bim.module.system.prop import BIMSystemProperties, BIMZoneProperties, BIMZoneProperties class System(bonsai.core.tool.System): diff --git a/src/bonsai/scripts/bonsai_translations.py b/src/bonsai/scripts/bonsai_translations.py index a3053115fd..7e3e746934 100644 --- a/src/bonsai/scripts/bonsai_translations.py +++ b/src/bonsai/scripts/bonsai_translations.py @@ -75,7 +75,7 @@ class Message: translations: Optional[Dict[str, str]] = field(default_factory=dict) -def bonsai_strings_parse(addon_directory=None, po_directory=None): +def bonsai_strings_parse(addon_directory: Optional[Path] = None, po_directory: Optional[Path] = None): # NOTE: we decided to use our own parser due bug in Blender parser # as it tends to pick up strings from other addons and other Blender parts # and this bug probably would be to low of a priority for Blender to fix @@ -153,7 +153,7 @@ def bonsai_strings_parse(addon_directory=None, po_directory=None): def update_translations_from_po(po_directory: Path, translations_module: Path): translation_data: Dict[str, Message] = dict() - def process_po_entry(language, current_chunk: list[str]): + def process_po_entry(language: str, current_chunk: list[str]) -> None: sources = [] msgid = None msgstr = None @@ -171,6 +171,7 @@ def update_translations_from_po(po_directory: Path, translations_module: Path): elif line.startswith("#:"): sources.append(line.removeprefix("# ").strip()) + assert msgid is not None and msgstr is not None msg = translation_data.get(msgid) if msg is None: msg = Message(msgid, msgctxt, sources, {language: msgstr}) @@ -179,8 +180,8 @@ def update_translations_from_po(po_directory: Path, translations_module: Path): msg.sources.extend(sources) msg.translations[language] = msgstr - # load data from .po files - langs = set() + # load data from .po files to translation_data. + langs: set[str] = set() for po_file_path in po_directory.glob("**/*.po"): lang = po_file_path.stem langs.add(lang) diff --git a/src/bonsai/test/tool/test_system.py b/src/bonsai/test/tool/test_system.py index 7b0dc9e0d1..5a6ce1949f 100644 --- a/src/bonsai/test/tool/test_system.py +++ b/src/bonsai/test/tool/test_system.py @@ -112,22 +112,25 @@ class TestDeleteElementObjects(NewFile): class TestDisableEditingSystem(NewFile): def test_run(self): - bpy.context.scene.BIMSystemProperties.edited_system_id = 10 + props = tool.System.get_system_props() + props.edited_system_id = 10 subject.disable_editing_system() - assert bpy.context.scene.BIMSystemProperties.edited_system_id == 0 + assert props.edited_system_id == 0 class TestDisableSystemEditingUI(NewFile): def test_run(self): subject.enable_system_editing_ui() subject.disable_system_editing_ui() - assert bpy.context.scene.BIMSystemProperties.is_editing is False + props = tool.System.get_system_props() + assert props.is_editing is False class TestEnableSystemEditingUI(NewFile): def test_run(self): subject.enable_system_editing_ui() - assert bpy.context.scene.BIMSystemProperties.is_editing is True + props = tool.System.get_system_props() + assert props.is_editing is True class TestExportSystemAttributes(NewFile): @@ -171,7 +174,7 @@ class TestImportSystemAttributes(NewFile): system.Description = "Description" system.ObjectType = "ObjectType" subject().import_system_attributes(system) - props = bpy.context.scene.BIMSystemProperties + props = tool.System.get_system_props() assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Description").string_value == "Description" @@ -188,7 +191,7 @@ class TestImportSystemAttributes(NewFile): system.PredefinedType = "SHADING" system.LongName = "LongName" subject().import_system_attributes(system) - props = bpy.context.scene.BIMSystemProperties + props = tool.System.get_system_props() assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Description").string_value == "Description" @@ -207,7 +210,7 @@ class TestImportSystemAttributes(NewFile): system.PredefinedType = "ELECTRICAL" system.LongName = "LongName" subject().import_system_attributes(system) - props = bpy.context.scene.BIMSystemProperties + props = tool.System.get_system_props() assert props.system_attributes.get("GlobalId").string_value == "GlobalId" assert props.system_attributes.get("Name").string_value == "Name" assert props.system_attributes.get("Description").string_value == "Description" @@ -223,7 +226,7 @@ class TestImportSystems(NewFile): system = ifc.createIfcDistributionSystem() zone = ifc.createIfcZone() subject.import_systems() - props = bpy.context.scene.BIMSystemProperties + props = tool.System.get_system_props() assert len(props.systems) == 2 assert props.systems[0].ifc_definition_id == system.id() assert props.systems[0].name == "Unnamed" @@ -277,7 +280,8 @@ class TestSetActiveSystem(NewFile): tool.Ifc().set(ifc) system = ifcopenshell.api.run("system.add_system", ifc, ifc_class="IfcSystem") subject.set_active_edited_system(system) - assert bpy.context.scene.BIMSystemProperties.edited_system_id == system.id() + props = tool.System.get_system_props() + assert props.edited_system_id == system.id() class TestFlowElementAndControls(NewFile): diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/unassign_system.py b/src/ifcopenshell-python/ifcopenshell/api/system/unassign_system.py index 4956b33b56..2921524094 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/system/unassign_system.py +++ b/src/ifcopenshell-python/ifcopenshell/api/system/unassign_system.py @@ -29,11 +29,8 @@ def unassign_system( """Unassigns list of products from a system :param products: The list of IfcDistributionElements to unassign from the system. - :type products: list[ifcopenshell.entity_instance] :param system: The IfcSystem you want to unassign the element from. - :type system: ifcopenshell.entity_instance :return: None - :rtype: None Example: @@ -52,9 +49,4 @@ def unassign_system( # Not anymore! ifcopenshell.api.system.unassign_system(model, products=[duct], system=system) """ - settings = { - "products": products, - "system": system, - } - - ifcopenshell.api.group.unassign_group(file, products=settings["products"], group=settings["system"]) + ifcopenshell.api.group.unassign_group(file, products=products, group=system)