diff --git a/src/blenderbim/blenderbim/core/cost.py b/src/blenderbim/blenderbim/core/cost.py index ec8cc3e7e1..e703844b23 100644 --- a/src/blenderbim/blenderbim/core/cost.py +++ b/src/blenderbim/blenderbim/core/cost.py @@ -1,88 +1,115 @@ -def add_cost_schedule(ifc, name, predefined_type): +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2021 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +from __future__ import annotations +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + import bpy + import ifcopenshell + import blenderbim.tool as tool + + +def add_cost_schedule(ifc: tool.Ifc, name, predefined_type): ifc.run("cost.add_cost_schedule", name=name, predefined_type=predefined_type) -def edit_cost_schedule(ifc, cost, cost_schedule): +def edit_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance): attributes = cost.get_cost_schedule_attributes() ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes) cost.disable_editing_cost_schedule() -def disable_editing_cost_schedule(cost): +def disable_editing_cost_schedule(cost: tool.Cost): cost.disable_editing_cost_schedule() -def remove_cost_schedule(ifc, cost_schedule): +def remove_cost_schedule(ifc: tool.Ifc, cost_schedule: ifcopenshell.entity_instance): ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule) -def enable_editing_cost_schedule_attributes(cost, cost_schedule): +def enable_editing_cost_schedule_attributes(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance): cost.load_cost_schedule_attributes(cost_schedule) cost.enable_editing_cost_schedule_attributes(cost_schedule) -def enable_editing_cost_items(cost, cost_schedule): +def enable_editing_cost_items(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance): cost.enable_editing_cost_items(cost_schedule) cost.load_cost_schedule_tree() cost.play_sound() -def add_summary_cost_item(ifc, cost, cost_schedule): +def add_summary_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance): ifc.run("cost.add_cost_item", cost_schedule=cost_schedule) cost.load_cost_schedule_tree() # cost.play_sound() -def add_cost_item(ifc, cost, cost_item): +def add_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance): ifc.run("cost.add_cost_item", cost_item=cost_item) cost.load_cost_schedule_tree() # cost.enable_editing_cost_schedule_attributes(cost_schedule) -def expand_cost_item(cost, cost_item): +def expand_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.expand_cost_item(cost_item) cost.load_cost_schedule_tree() -def expand_cost_items(cost): +def expand_cost_items(cost: tool.Cost): cost.expand_cost_items() cost.load_cost_schedule_tree() -def contract_cost_item(cost, cost_item): +def contract_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.contract_cost_item(cost_item) cost.load_cost_schedule_tree() -def contract_cost_items(cost): +def contract_cost_items(cost: tool.Cost): cost.contract_cost_items() cost.load_cost_schedule_tree() -def remove_cost_item(ifc, cost, cost_item_id): +def remove_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item_id: int): cost_item = ifc.get().by_id(cost_item_id) ifc.run("cost.remove_cost_item", cost_item=cost_item) cost.clean_up_cost_item_tree(cost_item_id) cost.load_cost_schedule_tree() -def enable_editing_cost_item_attributes(cost, cost_item): +def enable_editing_cost_item_attributes(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.enable_editing_cost_item_attributes(cost_item) cost.load_cost_item_attributes(cost_item) -def disable_editing_cost_item(cost): +def disable_editing_cost_item(cost: tool.Cost): cost.disable_editing_cost_item() -def edit_cost_item(ifc, cost): +def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost): attributes = cost.get_cost_item_attributes() ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes) cost.disable_editing_cost_item() cost.load_cost_schedule_tree() -def assign_cost_item_type(ifc, cost, spatial, cost_item, prop_name): +def assign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, prop_name): product_types = spatial.get_selected_product_types() [ ifc.run("control.assign_control", relating_control=cost_item, related_object=product_type) @@ -91,7 +118,7 @@ def assign_cost_item_type(ifc, cost, spatial, cost_item, prop_name): cost.load_cost_item_types(cost_item) -def unassign_cost_item_type(ifc, cost, spatial, cost_item, product_types): +def unassign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, product_types): if not product_types: product_types = spatial.get_selected_product_types() [ @@ -101,83 +128,83 @@ def unassign_cost_item_type(ifc, cost, spatial, cost_item, product_types): cost.load_cost_item_types(cost_item) -def load_cost_item_types(cost): +def load_cost_item_types(cost: tool.Cost): cost_item = cost.get_active_cost_item() cost.load_cost_item_types(cost_item) -def assign_cost_item_quantity(ifc, cost, cost_item, related_object_type, prop_name): +def assign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type, prop_name): products = cost.get_products(related_object_type) if products: ifc.run("cost.assign_cost_item_quantity", cost_item=cost_item, products=products, prop_name=prop_name) cost.load_cost_item_quantity_assignments(cost_item, related_object_type=related_object_type) -def load_cost_item_quantities(cost): +def load_cost_item_quantities(cost: tool.Cost): cost.load_cost_item_quantities() -def load_cost_item_element_quantities(cost): +def load_cost_item_element_quantities(cost: tool.Cost): cost_item = cost.get_highlighted_cost_item() cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PRODUCT") -def load_cost_item_task_quantities(cost): +def load_cost_item_task_quantities(cost: tool.Cost): cost_item = cost.get_highlighted_cost_item() cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PROCESS") -def load_cost_item_resource_quantities(cost): +def load_cost_item_resource_quantities(cost: tool.Cost): cost_item = cost.get_highlighted_cost_item() cost.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE") -def assign_cost_value(ifc, cost_item, cost_rate): +def assign_cost_value(ifc: tool.Ifc, cost_item, cost_rate): ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate) -def load_schedule_of_rates(cost, schedule_of_rates): +def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates): cost.load_schedule_of_rates_tree(schedule_of_rates) -def unassign_cost_item_quantity(ifc, cost, cost_item, products): +def unassign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item, products): ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products) cost.load_cost_item_quantities() -def enable_editing_cost_item_quantities(cost, cost_item): +def enable_editing_cost_item_quantities(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.enable_editing_cost_item_quantities(cost_item) -def enable_editing_cost_item_values(cost, cost_item): +def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.enable_editing_cost_item_values(cost_item) -def add_cost_item_quantity(ifc, cost_item, ifc_class): +def add_cost_item_quantity(ifc: tool.Ifc, cost_item, ifc_class): ifc.run("cost.add_cost_item_quantity", cost_item=cost_item, ifc_class=ifc_class) -def remove_cost_item_quantity(ifc, cost_item, physical_quantity): +def remove_cost_item_quantity(ifc: tool.Ifc, cost_item, physical_quantity): ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity) -def enable_editing_cost_item_quantity(cost, physical_quantity): +def enable_editing_cost_item_quantity(cost: tool.Cost, physical_quantity): cost.load_cost_item_quantity_attributes(physical_quantity) cost.enable_editing_cost_item_quantity(physical_quantity) -def disable_editing_cost_item_quantity(cost): +def disable_editing_cost_item_quantity(cost: tool.Cost): cost.disable_editing_cost_item_quantity() -def edit_cost_item_quantity(ifc, cost, physical_quantity): +def edit_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, physical_quantity): attributes = cost.get_cost_item_quantity_attributes() ifc.run("cost.edit_cost_item_quantity", physical_quantity=physical_quantity, attributes=attributes) cost.disable_editing_cost_item_quantity() cost.load_cost_item_quantities() -def add_cost_value(ifc, cost, parent, cost_type, cost_category): +def add_cost_value(ifc: tool.Ifc, cost: tool.Cost, parent, cost_type, cost_category): value = ifc.run("cost.add_cost_value", parent=parent) ifc.run( "cost.edit_cost_value", @@ -186,82 +213,82 @@ def add_cost_value(ifc, cost, parent, cost_type, cost_category): ) -def remove_cost_value(ifc, parent, cost_value): +def remove_cost_value(ifc: tool.Ifc, parent, cost_value): ifc.run("cost.remove_cost_value", parent=parent, cost_value=cost_value) -def enable_editing_cost_item_value(cost, cost_value): +def enable_editing_cost_item_value(cost: tool.Cost, cost_value): cost.load_cost_item_value_attributes(cost_value) cost.enable_editing_cost_item_value(cost_value) -def disable_editing_cost_item_value(cost): +def disable_editing_cost_item_value(cost: tool.Cost): cost.disable_editing_cost_item_value() -def enable_editing_cost_item_value_formula(cost, cost_value): +def enable_editing_cost_item_value_formula(cost: tool.Cost, cost_value): cost.load_cost_item_value_formula_attributes(cost_value) cost.enable_editing_cost_item_value_formula(cost_value) -def edit_cost_item_value_formula(ifc, cost, cost_value): +def edit_cost_item_value_formula(ifc: tool.Ifc, cost: tool.Cost, cost_value): formula = cost.get_cost_item_value_formula() ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula) cost.disable_editing_cost_item_value() -def edit_cost_value(ifc, cost, cost_value): +def edit_cost_value(ifc: tool.Ifc, cost: tool.Cost, cost_value): attributes = cost.get_cost_value_attributes() ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes) cost.disable_editing_cost_item_value() # cost.load_cost_item_values(cost.get_highlighted_cost_item()) -def copy_cost_item_values(ifc, cost, source, destination): +def copy_cost_item_values(ifc: tool.Ifc, cost: tool.Cost, source, destination): ifc.run("cost.copy_cost_item_values", source=source, destination=destination) -def select_cost_item_products(cost, spatial, cost_item): +def select_cost_item_products(cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance): is_deep = cost.show_nested_cost_item_elements() products = cost.get_cost_item_products(cost_item, is_deep) spatial.select_products(products) -def select_cost_schedule_products(cost, spatial, cost_schedule): +def select_cost_schedule_products(cost: tool.Cost, spatial: tool.Spatial, cost_schedule: ifcopenshell.entity_instance): products = cost.get_cost_schedule_products(cost_schedule) spatial.select_products(products) -def import_cost_schedule_csv(cost, file_path, is_schedule_of_rates): +def import_cost_schedule_csv(cost: tool.Cost, file_path, is_schedule_of_rates): cost.import_cost_schedule_csv(file_path, is_schedule_of_rates) -def add_cost_column(cost, name): +def add_cost_column(cost: tool.Cost, name): cost.add_cost_column(name) -def remove_cost_column(cost, name): +def remove_cost_column(cost: tool.Cost, name): cost.remove_cost_column(name) -def expand_cost_item_rate(cost, cost_item): +def expand_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.expand_cost_item_rate(cost_item) -def contract_cost_item_rate(cost, cost_item): +def contract_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost.contract_cost_item_rate(cost_item) -def calculate_cost_item_resource_value(ifc, cost_item): +def calculate_cost_item_resource_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance): ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item) -def export_cost_schedules(cost, filepath, format, cost_schedule=None): +def export_cost_schedules(cost: tool.Cost, filepath, format, cost_schedule=None): cost.play_sound() return cost.export_cost_schedules(filepath, format, cost_schedule) -def clear_cost_item_assignments(ifc, cost, cost_item, related_object_type): +def clear_cost_item_assignments(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type): products = cost.get_cost_item_assignments(cost_item, filter_by_type=related_object_type) if products: ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products) @@ -269,7 +296,7 @@ def clear_cost_item_assignments(ifc, cost, cost_item, related_object_type): cost.load_cost_schedule_tree() -def select_unassigned_products(ifc, cost, spatial): +def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial): spatial.deselect_objects() products = ifc.get().by_type("IfcElement") cost_schedule = cost.get_active_cost_schedule() @@ -277,11 +304,11 @@ def select_unassigned_products(ifc, cost, spatial): spatial.select_products(selection) -def load_product_cost_items(cost, product): +def load_product_cost_items(cost: tool.Cost, product): cost.load_product_cost_items(product) -def highlight_product_cost_item(spatial, cost, cost_item): +def highlight_product_cost_item(spatial: tool.Spatial, cost: tool.Cost, cost_item: ifcopenshell.entity_instance): cost_schedule = cost.get_cost_schedule(cost_item) is_cost_schedule_active = cost.is_cost_schedule_active(cost_schedule) if is_cost_schedule_active: @@ -290,7 +317,7 @@ def highlight_product_cost_item(spatial, cost, cost_item): return "Cost schedule is not active" -def change_parent_cost_item(ifc, cost, new_parent): +def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent): cost_item = cost.get_active_cost_item() if cost_item and cost.is_root_cost_item(cost_item): return "Cannot change root cost item" @@ -300,7 +327,7 @@ def change_parent_cost_item(ifc, cost, new_parent): cost.load_cost_schedule_tree() -def copy_cost_item(ifc, cost): +def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost): cost_item = cost.get_highlighted_cost_item() if cost_item: cost_item = ifc.run("cost.copy_cost_item", cost_item=cost_item) @@ -308,7 +335,7 @@ def copy_cost_item(ifc, cost): cost.load_cost_schedule_tree() -def add_currency(ifc, cost): +def add_currency(ifc: tool.Ifc, cost: tool.Cost): unit = ifc.run("unit.add_monetary_unit") attributes = cost.get_currency_attributes() ifc.run("unit.edit_monetary_unit", unit=unit, attributes=attributes) diff --git a/src/blenderbim/blenderbim/tool/cost.py b/src/blenderbim/blenderbim/tool/cost.py index f51d157862..01a392e727 100644 --- a/src/blenderbim/blenderbim/tool/cost.py +++ b/src/blenderbim/blenderbim/tool/cost.py @@ -36,7 +36,7 @@ class Cost(blenderbim.core.tool.Cost): blenderbim.bim.helper.import_attributes2(cost_schedule, props.cost_schedule_attributes, callback=special_import) @classmethod - def enable_editing_cost_items(cls, cost_schedule): + def enable_editing_cost_items(cls, cost_schedule: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMCostProperties props.active_cost_schedule_id = cost_schedule.id() props.is_editing = "COST_ITEMS" @@ -473,7 +473,9 @@ class Cost(blenderbim.core.tool.Cost): cls.load_schedule_of_rates_tree(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates))) @classmethod - def create_new_cost_item_li(cls, props_collection, cost_item, level_index, type="cost_rate"): + def create_new_cost_item_li( + cls, props_collection, cost_item: ifcopenshell.entity_instance, level_index: int, type: str = "cost_rate" + ) -> None: new = props_collection.add() new.ifc_definition_id = cost_item.id() new.name = cost_item.Name or "Unnamed" diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 1e708d1e8f..776f40d4a6 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -23,22 +23,25 @@ import ifcopenshell.util.unit import ifcopenshell.util.selector import ifcopenshell.util.element import locale +from typing import Any, Optional + +CostItem = dict[str, Any] class Csv2Ifc: def __init__(self): - self.csv = None - self.file = None - self.cost_items = [] - self.cost_schedule = None - self.is_schedule_of_rates = False - self.units = {} + self.csv: str = None + self.file: ifcopenshell.file = None + self.cost_items: list[CostItem] = [] + self.cost_schedule: ifcopenshell.entity_instance = None + self.is_schedule_of_rates: bool = False + self.units: dict[str, ifcopenshell.entity_instance] = {} - def execute(self): + def execute(self) -> None: self.parse_csv() self.create_ifc() - def parse_csv(self): + def parse_csv(self) -> None: self.parents = {} self.headers = {} locale.setlocale(locale.LC_ALL, "") # set the system locale @@ -64,7 +67,7 @@ class Csv2Ifc: self.parents[hierarchy_key - 1]["children"].append(cost_data) self.parents[hierarchy_key] = cost_data - def get_row_cost_data(self, row): + def get_row_cost_data(self, row: list[str]) -> CostItem: name = row[self.headers["Name"]] identification = row[self.headers["Identification"]] if "Identification" in self.headers else None quantity = row[self.headers["Quantity"]] @@ -99,7 +102,7 @@ class Csv2Ifc: "children": [], } - def create_ifc(self): + def create_ifc(self) -> None: if not self.file: self.create_boilerplate_ifc() if not self.cost_schedule: @@ -108,11 +111,13 @@ class Csv2Ifc: self.cost_schedule.PredefinedType = "SCHEDULEOFRATES" self.create_cost_items(self.cost_items) - def create_cost_items(self, cost_items, parent=None): + def create_cost_items( + self, cost_items: list[CostItem], parent: Optional[ifcopenshell.entity_instance] = None + ) -> None: for cost_item in cost_items: self.create_cost_item(cost_item, parent) - def create_cost_item(self, cost_item, parent): + def create_cost_item(self, cost_item: CostItem, parent: Optional[ifcopenshell.entity_instance] = None) -> None: if parent is None: cost_item["ifc"] = ifcopenshell.api.run("cost.add_cost_item", self.file, cost_schedule=self.cost_schedule) else: @@ -161,6 +166,7 @@ class Csv2Ifc: quantity = ifcopenshell.api.run( "cost.add_cost_item_quantity", self.file, cost_item=cost_item["ifc"], ifc_class=quantity_class ) + # 3 IfcPhysicalSimpleQuantity Value quantity[3] = cost_item["Quantity"] if cost_item["assignments"]["Query"]: @@ -184,7 +190,7 @@ class Csv2Ifc: self.create_cost_items(cost_item["children"], cost_item["ifc"]) - def create_unit(self, symbol): + def create_unit(self, symbol) -> ifcopenshell.entity_instance: unit = self.units.get(symbol, None) if unit: return unit @@ -194,12 +200,12 @@ class Csv2Ifc: self.units[symbol] = unit return unit - def create_boilerplate_ifc(self): + def create_boilerplate_ifc(self) -> None: self.file = ifcopenshell.file(schema="IFC4") ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") -def has_property(self, product, property_name): +def has_property(self, product, property_name) -> bool: if not property_name: return True qtos = ifcopenshell.util.element.get_psets(product, qtos_only=True)