diff --git a/src/bonsai/bonsai/bim/module/csv/ui.py b/src/bonsai/bonsai/bim/module/csv/ui.py index bc994a0815..a407efc7d1 100644 --- a/src/bonsai/bonsai/bim/module/csv/ui.py +++ b/src/bonsai/bonsai/bim/module/csv/ui.py @@ -32,6 +32,7 @@ class BIM_PT_ifccsv(Panel): bl_parent_id = "BIM_PT_tab_collaboration" def draw(self, context): + assert self.layout layout = self.layout props = tool.Blender.get_csv_props() diff --git a/src/bonsai/bonsai/bim/module/root/data.py b/src/bonsai/bonsai/bim/module/root/data.py index 34fc15b0e4..b09af3a8b5 100644 --- a/src/bonsai/bonsai/bim/module/root/data.py +++ b/src/bonsai/bonsai/bim/module/root/data.py @@ -18,6 +18,7 @@ from collections import defaultdict import bpy +import ifcopenshell.util.attribute import ifcopenshell.util.element import ifcopenshell.util.schema from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc, get_class_suggestions @@ -83,14 +84,15 @@ class IfcClassData: types_enum = [] rprops = tool.Root.get_root_props() ifc_class = rprops.ifc_class - declaration = tool.Ifc.schema().declaration_by_name(ifc_class) + declaration = tool.Ifc.schema().declaration_by_name(ifc_class).as_entity() + assert declaration version = tool.Ifc.get_schema() for attribute in declaration.attributes(): if attribute.name() == "PredefinedType": types_enum.extend( [ (e, e, get_predefined_type_doc(version, ifc_class, e) or "") - for e in attribute.type_of_attribute().declared_type().enumeration_items() + for e in ifcopenshell.util.attribute.get_enum_items(attribute) ] ) break diff --git a/src/bonsai/bonsai/tool/sequence.py b/src/bonsai/bonsai/tool/sequence.py index 36de10d157..ceb5994228 100644 --- a/src/bonsai/bonsai/tool/sequence.py +++ b/src/bonsai/bonsai/tool/sequence.py @@ -86,7 +86,7 @@ class Sequence(bonsai.core.tool.Sequence): def get_work_plan_attributes(cls) -> dict[str, Any]: import bonsai.bim.module.sequence.helper as helper - def callback(attributes, prop): + def callback(attributes: dict[str, Any], prop: Attribute) -> bool: if "Date" in prop.name or "Time" in prop.name: if prop.is_null: attributes[prop.name] = None @@ -99,14 +99,16 @@ class Sequence(bonsai.core.tool.Sequence): return True attributes[prop.name] = helper.parse_duration(prop.string_value) return True + return False props = cls.get_work_plan_props() return bonsai.bim.helper.export_attributes(props.work_plan_attributes, callback) @classmethod def load_work_plan_attributes(cls, work_plan: ifcopenshell.entity_instance) -> None: - def callback(name, prop, data): + def callback(name: str, prop: Union[Attribute, None], data: dict[str, Any]) -> None | Literal[True]: if name in ["CreationDate", "StartTime", "FinishTime"]: + assert prop prop.string_value = "" if prop.is_null else data[name] return True @@ -137,7 +139,7 @@ class Sequence(bonsai.core.tool.Sequence): def get_work_schedule_attributes(cls) -> dict[str, Any]: import bonsai.bim.module.sequence.helper as helper - def callback(attributes, prop): + def callback(attributes: dict[str, Any], prop: Attribute) -> bool: if "Date" in prop.name or "Time" in prop.name: if prop.is_null: attributes[prop.name] = None @@ -150,14 +152,16 @@ class Sequence(bonsai.core.tool.Sequence): return True attributes[prop.name] = helper.parse_duration(prop.string_value) return True + return False props = cls.get_work_schedule_props() return bonsai.bim.helper.export_attributes(props.work_schedule_attributes, callback) @classmethod def load_work_schedule_attributes(cls, work_schedule: ifcopenshell.entity_instance) -> None: - def callback(name, prop, data): + def callback(name: str, prop: Union[Attribute, None], data: dict[str, Any]) -> None | Literal[True]: if name in ["CreationDate", "StartTime", "FinishTime"]: + assert prop prop.string_value = "" if prop.is_null else data[name] return True @@ -419,6 +423,7 @@ class Sequence(bonsai.core.tool.Sequence): duration_props[key] = value return True if isinstance(data[name], datetime): + assert prop prop.string_value = "" if prop.is_null else data[name].isoformat() return True @@ -635,13 +640,14 @@ class Sequence(bonsai.core.tool.Sequence): def get_work_time_attributes(cls) -> dict[str, Any]: import bonsai.bim.module.sequence.helper as helper - def callback(attributes, prop): + def callback(attributes: dict[str, Any], prop: Attribute) -> bool: if "Start" in prop.name or "Finish" in prop.name: if prop.is_null: attributes[prop.name] = None return True attributes[prop.name] = helper.parse_datetime(prop.string_value) return True + return False props = bpy.context.scene.BIMWorkCalendarProperties return bonsai.bim.helper.export_attributes(props.work_time_attributes, callback) @@ -725,7 +731,7 @@ class Sequence(bonsai.core.tool.Sequence): def load_lag_time_attributes(cls, lag_time: ifcopenshell.entity_instance) -> None: props = cls.get_work_schedule_props() - def callback(name, prop, data): + def callback(name: str, prop: Union[Attribute, None], data: dict[str, Any]) -> None | Literal[True]: if name == "LagValue": prop = props.lag_time_attributes.add() prop.name = name diff --git a/src/bonsai/bonsai/tool/structural.py b/src/bonsai/bonsai/tool/structural.py index cf984bf176..3f218e52e9 100644 --- a/src/bonsai/bonsai/tool/structural.py +++ b/src/bonsai/bonsai/tool/structural.py @@ -161,7 +161,7 @@ class Structural(bonsai.core.tool.Structural): new.is_null = data[attribute.name()] is None new.is_optional = attribute.optional() if attribute.name() == "PredefinedType": - new.enum_items = json.dumps(attribute.type_of_attribute().declared_type().enumeration_items()) + new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute)) new.data_type = "enum" if data[attribute.name()]: new.enum_value = data[attribute.name()] diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task.py index 03cf6cb5eb..9ad03f7a2f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task.py @@ -147,5 +147,6 @@ def add_task( relating_object=parent_task, ) if file.schema != "IFC2X3" and parent_task.Identification: + assert rel task.Identification = parent_task.Identification + "." + str(len(rel.RelatedObjects)) return task diff --git a/src/ifcopenshell-python/ifcopenshell/util/cost.py b/src/ifcopenshell-python/ifcopenshell/util/cost.py index 71af763d48..2b6f425fce 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/cost.py +++ b/src/ifcopenshell-python/ifcopenshell/util/cost.py @@ -21,6 +21,7 @@ import ifcopenshell from typing import Optional, Union, Literal, Any from collections.abc import Generator import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper +import ifcopenshell.util.attribute from ifcopenshell.util.doc import get_predefined_type_doc from ifcopenshell.util.element import get_psets from ifcopenshell.util.unit import get_unit_symbol @@ -283,13 +284,13 @@ def get_cost_values(cost_item: ifcopenshell.entity_instance) -> list[dict[str, s def get_cost_schedule_types(file: ifcopenshell.file) -> list[dict[str, str]]: schema = ifcopenshell_wrapper.schema_by_name(file.schema_identifier) - results = [] + results: list[dict[str, str]] = [] declaration = schema.declaration_by_name("IfcCostSchedule").as_entity() assert declaration version = file.schema_identifier for attribute in declaration.attributes(): if attribute.name() == "PredefinedType": - for enumeration in attribute.type_of_attribute().declared_type().enumeration_items(): + for enumeration in ifcopenshell.util.attribute.get_enum_items(attribute): results.append( { "name": enumeration, diff --git a/src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py b/src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py index b0bf0cdda5..44d5bc28cf 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py +++ b/src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py @@ -18,7 +18,7 @@ RUN_FROM_DEV_REPO = False -import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper +import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.api.unit import ifcopenshell.api.project import ifcopenshell.guid @@ -28,6 +28,7 @@ import sys from pathlib import Path from lxml import etree from itertools import chain +from typing import cast if not RUN_FROM_DEV_REPO: @@ -128,11 +129,17 @@ class PsetTemplatesGenerator: self.units = dict() schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.ifc_file.schema_identifier) - self.ifc_derived_unit_enum = ( - schema.declaration_by_name("IfcDerivedUnitEnum").as_enumeration_type().enumeration_items() - ) - self.ifc_unit_enum = schema.declaration_by_name("IfcUnitEnum").as_enumeration_type().enumeration_items() - select_types = schema.declaration_by_name("IfcValue").select_list() + derived_unit_enum = schema.declaration_by_name("IfcDerivedUnitEnum").as_enumeration_type() + assert derived_unit_enum + self.ifc_derived_unit_enum = derived_unit_enum.enumeration_items() + + ifc_unit_enum = schema.declaration_by_name("IfcUnitEnum").as_enumeration_type() + assert ifc_unit_enum + self.ifc_unit_enum = ifc_unit_enum.enumeration_items() + + value_select = schema.declaration_by_name("IfcValue").as_select_type() + assert value_select + select_types = cast(tuple[W.select_type, ...], value_select.select_list()) self.ifc_value_types = [t.name() for t in chain(*[select_type.select_list() for select_type in select_types])] project = self.ifc_entity("IfcProject", Name=project_name, GlobalId=ifcopenshell.guid.new())