From f2eb08a066d623c390c78a7a946d52be1e7c878f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 22 May 2024 11:05:42 +0500 Subject: [PATCH] typing --- src/blenderbim/blenderbim/core/cost.py | 2 +- src/blenderbim/blenderbim/tool/cost.py | 4 +-- src/ifc5d/ifc5d/csv2ifc.py | 4 +-- src/ifc5d/ifc5d/ifc5Dspreadsheet.py | 22 ++++++++++++--- .../api/cost/add_cost_item_quantity.py | 5 +++- .../api/cost/assign_cost_item_quantity.py | 15 +++++++---- .../ifcopenshell/util/unit.py | 27 ++++++++++++++++--- 7 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/blenderbim/blenderbim/core/cost.py b/src/blenderbim/blenderbim/core/cost.py index f23cb60a49..0859ed59b1 100644 --- a/src/blenderbim/blenderbim/core/cost.py +++ b/src/blenderbim/blenderbim/core/cost.py @@ -289,7 +289,7 @@ def calculate_cost_item_resource_value(ifc: tool.Ifc, cost_item: ifcopenshell.en ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item) -def export_cost_schedules(cost: tool.Cost, filepath, format, cost_schedule=None): +def export_cost_schedules(cost: tool.Cost, filepath: str, format: str, cost_schedule=None): cost.play_sound() return cost.export_cost_schedules(filepath, format, cost_schedule) diff --git a/src/blenderbim/blenderbim/tool/cost.py b/src/blenderbim/blenderbim/tool/cost.py index aa4bb8264c..5d4698a24f 100644 --- a/src/blenderbim/blenderbim/tool/cost.py +++ b/src/blenderbim/blenderbim/tool/cost.py @@ -529,7 +529,7 @@ class Cost(blenderbim.core.tool.Cost): props.is_cost_update_enabled = True @classmethod - def export_cost_schedules(cls, filepath, format=None, cost_schedule=None): + def export_cost_schedules(cls, filepath: str, format: str, cost_schedule=None): import subprocess import os import sys @@ -642,7 +642,7 @@ class Cost(blenderbim.core.tool.Cost): return bool(cost_items) @classmethod - def load_product_cost_items(cls, product): + def load_product_cost_items(cls, product: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMCostProperties props.is_cost_update_enabled = False props.product_cost_items.clear() diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 3bdaa0d93c..218a257d48 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -212,7 +212,7 @@ class Csv2Ifc: self.create_cost_items(cost_item["children"], cost_item["ifc"]) - def create_unit(self, symbol) -> ifcopenshell.entity_instance: + def create_unit(self, symbol: str) -> ifcopenshell.entity_instance: unit = self.units.get(symbol, None) if unit: return unit @@ -227,7 +227,7 @@ class Csv2Ifc: ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") -def has_property(self, product, property_name) -> bool: +def has_property(self, product: ifcopenshell.entity_instance, property_name: str) -> bool: if not property_name: return True qtos = ifcopenshell.util.element.get_psets(product, qtos_only=True) diff --git a/src/ifc5d/ifc5d/ifc5Dspreadsheet.py b/src/ifc5d/ifc5d/ifc5Dspreadsheet.py index 8e2b739cbb..826f610817 100644 --- a/src/ifc5d/ifc5d/ifc5Dspreadsheet.py +++ b/src/ifc5d/ifc5d/ifc5Dspreadsheet.py @@ -26,13 +26,18 @@ import ifcopenshell import ifcopenshell.util.element import ifcopenshell.util.cost import ifcopenshell.util.date +from typing import Union, Optional class IfcDataGetter: @staticmethod - def get_schedules(file, filter_by_schedule=None): + def get_schedules( + file: ifcopenshell.file, filter_by_schedule: Optional[ifcopenshell.entity_instance] = None + ) -> list[ifcopenshell.entity_instance]: return [ - schedule for schedule in file.by_type("IfcCostSchedule") if not filter_by_schedule or schedule == filter_by_schedule + schedule + for schedule in file.by_type("IfcCostSchedule") + if not filter_by_schedule or schedule == filter_by_schedule ] @staticmethod @@ -195,7 +200,18 @@ class IfcDataGetter: class Ifc5Dwriter: - def __init__(self, file=None, output=None, cost_schedule=None): + file: ifcopenshell.file + + def __init__( + self, + file: Union[str, ifcopenshell.file], + output: str, + cost_schedule: Optional[ifcopenshell.entity_instance] = None, + ): + """ + Args: + cost_schedule: exported cost schedule. If not provided, will export all available schedules. + """ self.output = output if isinstance(file, str): self.file = ifcopenshell.open(file) diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/add_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/add_cost_item_quantity.py index 61ba86f6b2..fd1d793300 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/add_cost_item_quantity.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/add_cost_item_quantity.py @@ -17,10 +17,13 @@ # along with IfcOpenShell. If not, see . import ifcopenshell.api +import ifcopenshell.util.unit def add_cost_item_quantity( - file: ifcopenshell.file, cost_item: ifcopenshell.entity_instance, ifc_class: str = "IfcQuantityCount" + file: ifcopenshell.file, + cost_item: ifcopenshell.entity_instance, + ifc_class: ifcopenshell.util.unit.QUANTITY_CLASS = "IfcQuantityCount", ) -> ifcopenshell.entity_instance: """Adds a new quantity associated with a cost item diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py index ae0643acae..d9ef5c61f6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py @@ -17,14 +17,14 @@ # along with IfcOpenShell. If not, see . import ifcopenshell.api -from typing import Optional +from typing import Any def assign_cost_item_quantity( file: ifcopenshell.file, cost_item: ifcopenshell.entity_instance, products: list[ifcopenshell.entity_instance], - prop_name: Optional[str] = "", + prop_name: str = "", ) -> None: """Adds a cost item quantity that is parametrically connected to a product @@ -96,6 +96,9 @@ def assign_cost_item_quantity( class Usecase: + file: ifcopenshell.file + settings: dict[str, Any] + def execute(self): if self.settings["prop_name"]: self.quantities = set(self.settings["cost_item"].CostQuantities or []) @@ -113,7 +116,9 @@ class Usecase: else: self.update_cost_item_count() - def assign_cost_control(self, related_object, cost_item): + def assign_cost_control( + self, related_object: ifcopenshell.entity_instance, cost_item: ifcopenshell.entity_instance + ) -> ifcopenshell.entity_instance: return ifcopenshell.api.run( "control.assign_control", self.file, @@ -121,12 +126,12 @@ class Usecase: relating_control=cost_item, ) - def add_quantity_from_related_object(self, element): + def add_quantity_from_related_object(self, element: ifcopenshell.entity_instance) -> None: for relationship in element.IsDefinedBy: if relationship.is_a("IfcRelDefinesByProperties"): self.add_quantity_from_qto(relationship.RelatingPropertyDefinition) - def add_quantity_from_qto(self, qto): + def add_quantity_from_qto(self, qto: ifcopenshell.entity_instance) -> None: if not qto.is_a("IfcElementQuantity"): return for prop in qto.Quantities: diff --git a/src/ifcopenshell-python/ifcopenshell/util/unit.py b/src/ifcopenshell-python/ifcopenshell/util/unit.py index fdbee952a4..55eda62d82 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/unit.py +++ b/src/ifcopenshell-python/ifcopenshell/util/unit.py @@ -337,6 +337,25 @@ unit_symbols = { "fahrenheit": "°F", } +QUANTITY_CLASS = Literal[ + "IfcQuantityCount", + "IfcQuantityNumber", + "IfcQuantityLength", + "IfcQuantityArea", + "IfcQuantityVolume", + "IfcQuantityWeight", + "IfcQuantityTime", + "IfcQuantityCount", +] + +MEASURE_CLASS = Literal[ + "IfcNumericMeasure", + "IfcLengthMeasure", + "IfcAreaMeasure", + "IfcVolumeMeasure", + "IfcMassMeasure", +] + def get_prefix(text): if text: @@ -468,14 +487,14 @@ def get_property_unit( return units[0] -def get_unit_measure_class(unit_type: str) -> str: +def get_unit_measure_class(unit_type: str) -> MEASURE_CLASS: if unit_type == "USERDEFINED": # See https://github.com/buildingSMART/IFC4.3.x-development/issues/71 return "IfcNumericMeasure" return "Ifc" + unit_type[0:-4].lower().capitalize() + "Measure" -def get_measure_unit_type(measure_class: str) -> str: +def get_measure_unit_type(measure_class: MEASURE_CLASS) -> str: if measure_class == "IfcNumericMeasure": # See https://github.com/buildingSMART/IFC4.3.x-development/issues/71 return "USERDEFINED" @@ -484,7 +503,7 @@ def get_measure_unit_type(measure_class: str) -> str: return measure_class.upper() + "UNIT" -def get_symbol_measure_class(symbol: Optional[str] = None) -> str: +def get_symbol_measure_class(symbol: Optional[str] = None) -> MEASURE_CLASS: # Dumb, but everybody gets it, unlike regex golf if not symbol: return "IfcNumericMeasure" @@ -502,7 +521,7 @@ def get_symbol_measure_class(symbol: Optional[str] = None) -> str: return "IfcNumericMeasure" -def get_symbol_quantity_class(symbol: Optional[str] = None) -> str: +def get_symbol_quantity_class(symbol: Optional[str] = None) -> QUANTITY_CLASS: # Dumb, but everybody gets it, unlike regex golf if not symbol: return "IfcQuantityCount"