From 76f0b57ff13d9022e1af1cbadaa0ec4a9b484949 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 10 Jul 2025 14:12:36 +0500 Subject: [PATCH] Migrate to import_attributes2 --- src/bonsai/bonsai/bim/helper.py | 21 +++++++------------ .../bonsai/bim/module/material/operator.py | 4 ++-- .../bonsai/bim/module/structural/operator.py | 6 ++++-- src/bonsai/bonsai/tool/attribute.py | 2 +- src/bonsai/bonsai/tool/context.py | 2 +- src/bonsai/bonsai/tool/owner.py | 12 +++++------ 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/bonsai/bonsai/bim/helper.py b/src/bonsai/bonsai/bim/helper.py index 0e914084aa..8c683607df 100644 --- a/src/bonsai/bonsai/bim/helper.py +++ b/src/bonsai/bonsai/bim/helper.py @@ -39,6 +39,9 @@ if TYPE_CHECKING: # - None - property should be imported by default workflow # - True - setting value for imported attribute should be skipped # - False - property should be skipped entirely from import + # Second argument is optional, + # because ImportCallback might be called for attributes that are not created by default + # (e.g. IFC entity attributes). ImportCallback = Callable[[str, Optional[bonsai.bim.prop.Attribute], dict[str, Any]], Union[bool, None]] # ExportCallback return values: # - True - property should be skipped entirely from export @@ -153,24 +156,16 @@ def draw_attribute( op.name = attribute.name -def import_attributes( - ifc_class: str, - props: bpy.types.bpy_prop_collection_idprop[Attribute], - data: dict[str, Any], - callback: Optional[ImportCallback] = None, -) -> None: - schema = tool.Ifc.schema() - assert (entity := schema.declaration_by_name(ifc_class).as_entity()) - for attribute in entity.all_attributes(): - import_attribute(attribute, props, data, callback=callback) - - -# A more elegant attribute importer signature, intended to supersede import_attributes +# TODO: rename to 'import_attributes'. def import_attributes2( element: Union[str, ifcopenshell.entity_instance], props: bpy.types.bpy_prop_collection_idprop[Attribute], callback: Optional[ImportCallback] = None, ) -> None: + """ + :param element: Entity or IFC class string. + """ + info: dict[str, Any] if isinstance(element, str): assert (entity := tool.Ifc.schema().declaration_by_name(element).as_entity()) attributes = entity.all_attributes() diff --git a/src/bonsai/bonsai/bim/module/material/operator.py b/src/bonsai/bonsai/bim/module/material/operator.py index 5053e3a177..6dd492aa33 100644 --- a/src/bonsai/bonsai/bim/module/material/operator.py +++ b/src/bonsai/bonsai/bim/module/material/operator.py @@ -504,14 +504,14 @@ class EnableEditingAssignedMaterial(bpy.types.Operator): if "Usage" in material.is_a(): bonsai.bim.helper.import_attributes2( - material, props.material_set_usage_attributes, callback=self.import_attributes + material, props.material_set_usage_attributes, callback=self.import_attributes_callback ) bonsai.bim.helper.import_attributes2(material[0], props.material_set_attributes) else: bonsai.bim.helper.import_attributes2(material, props.material_set_attributes) return {"FINISHED"} - def import_attributes( + def import_attributes_callback( self, name: str, prop: Union["Attribute", None], data: dict[str, Any] ) -> None | Literal[True]: if name == "CardinalPoint": diff --git a/src/bonsai/bonsai/bim/module/structural/operator.py b/src/bonsai/bonsai/bim/module/structural/operator.py index 59168e205d..c156ef1f32 100644 --- a/src/bonsai/bonsai/bim/module/structural/operator.py +++ b/src/bonsai/bonsai/bim/module/structural/operator.py @@ -613,11 +613,13 @@ class EnableEditingStructuralLoadCase(bpy.types.Operator): self.props.load_case_editing_type = "ATTRIBUTES" self.props.load_case_attributes.clear() bonsai.bim.helper.import_attributes2( - tool.Ifc.get().by_id(self.load_case), self.props.load_case_attributes, callback=self.import_attributes + tool.Ifc.get().by_id(self.load_case), + self.props.load_case_attributes, + callback=self.import_attributes_callback, ) return {"FINISHED"} - def import_attributes(self, name: str, prop: object, data: object) -> None | Literal[False]: + def import_attributes_callback(self, name: str, prop: object, data: object) -> None | Literal[False]: if name in ["SelfWeightCoefficients"]: return False diff --git a/src/bonsai/bonsai/tool/attribute.py b/src/bonsai/bonsai/tool/attribute.py index bb1757f420..3113172bd2 100644 --- a/src/bonsai/bonsai/tool/attribute.py +++ b/src/bonsai/bonsai/tool/attribute.py @@ -68,7 +68,7 @@ class Attribute(bonsai.core.tool.Attribute): @classmethod def import_entity_attributes(cls, entity: ifcopenshell.entity_instance) -> None: props = cls.get_explorer_props() - helper.import_attributes(entity.is_a(), props.entity_attributes, entity.get_info()) + helper.import_attributes2(entity, props.entity_attributes) @classmethod def export_entity_attributes(cls) -> dict[str, Any]: diff --git a/src/bonsai/bonsai/tool/context.py b/src/bonsai/bonsai/tool/context.py index 39f795e2f3..98f791f0a2 100644 --- a/src/bonsai/bonsai/tool/context.py +++ b/src/bonsai/bonsai/tool/context.py @@ -72,7 +72,7 @@ class Context(bonsai.core.tool.Context): assert prop prop.data_type = "string" - bonsai.bim.helper.import_attributes(context.is_a(), props.context_attributes, context.get_info(), callback) + bonsai.bim.helper.import_attributes2(context, props.context_attributes, callback) @classmethod def clear_context(cls) -> None: diff --git a/src/bonsai/bonsai/tool/owner.py b/src/bonsai/bonsai/tool/owner.py index 4f95ff6782..289ebe75b9 100644 --- a/src/bonsai/bonsai/tool/owner.py +++ b/src/bonsai/bonsai/tool/owner.py @@ -97,7 +97,7 @@ class Owner(bonsai.core.tool.Owner): for line in data[name] or []: collection.add().name = line - bonsai.bim.helper.import_attributes(address.is_a(), props.address_attributes, address.get_info(), callback) + bonsai.bim.helper.import_attributes2(address, props.address_attributes, callback) @classmethod def clear_address(cls) -> None: @@ -154,7 +154,7 @@ class Owner(bonsai.core.tool.Owner): organisation = tool.Ifc.get().by_id(props.active_organisation_id) props.organisation_attributes.clear() - bonsai.bim.helper.import_attributes("IfcOrganization", props.organisation_attributes, organisation.get_info()) + bonsai.bim.helper.import_attributes2(organisation, props.organisation_attributes) @classmethod def clear_organisation(cls) -> None: @@ -209,7 +209,7 @@ class Owner(bonsai.core.tool.Owner): for name_ in data[name] or []: collection.add().name = name_ or "" - bonsai.bim.helper.import_attributes("IfcPerson", props.person_attributes, person.get_info(), callback) + bonsai.bim.helper.import_attributes2(person, props.person_attributes, callback) @classmethod def clear_person(cls) -> None: @@ -253,7 +253,7 @@ class Owner(bonsai.core.tool.Owner): role = cls.get_role() props = cls.get_owner_props() props.role_attributes.clear() - bonsai.bim.helper.import_attributes("IfcActorRole", props.role_attributes, role.get_info()) + bonsai.bim.helper.import_attributes2(role, props.role_attributes) @classmethod def clear_role(cls) -> None: @@ -329,9 +329,7 @@ class Owner(bonsai.core.tool.Owner): new.enum_value = str(data["ApplicationDeveloper"].id()) return True - bonsai.bim.helper.import_attributes( - "IfcApplication", props.application_attributes, application.get_info(), callback - ) + bonsai.bim.helper.import_attributes2(application, props.application_attributes, callback) @classmethod def export_application_attributes(cls) -> dict[str, Any]: