From 073e471305eb62a7e9dc634ce6f99f51d707712f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 23 May 2024 12:02:37 +0500 Subject: [PATCH] typing --- .../blenderbim/bim/module/csv/operator.py | 1 + .../blenderbim/bim/module/resource/data.py | 3 +- src/blenderbim/blenderbim/core/resource.py | 111 ++++++++++++------ src/blenderbim/blenderbim/tool/cost.py | 4 +- src/blenderbim/blenderbim/tool/resource.py | 95 +++++++-------- src/ifccsv/ifccsv.py | 18 ++- .../api/cost/edit_cost_value_formula.py | 1 + .../ifcopenshell/util/resource.py | 68 ++++++----- 8 files changed, 188 insertions(+), 113 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py index b62d9b93a1..47c5c28cfa 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/operator.py +++ b/src/blenderbim/blenderbim/bim/module/csv/operator.py @@ -23,6 +23,7 @@ import ifccsv import logging import tempfile import ifcopenshell +import ifcopenshell.util.selector import blenderbim.tool as tool import blenderbim.bim.module.drawing.scheduler as scheduler from blenderbim.bim.ifc import IfcStore diff --git a/src/blenderbim/blenderbim/bim/module/resource/data.py b/src/blenderbim/blenderbim/bim/module/resource/data.py index e70b29fb7a..47292fa3ab 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/data.py +++ b/src/blenderbim/blenderbim/bim/module/resource/data.py @@ -19,6 +19,7 @@ import bpy import blenderbim.tool as tool import ifcopenshell +import ifcopenshell.util.resource def refresh(): @@ -139,7 +140,7 @@ class ResourceData: return results @classmethod - def active_resource_ids(cls): + def active_resource_ids(cls) -> list[int]: obj = bpy.context.active_object element = tool.Ifc.get_entity(obj) if not element: diff --git a/src/blenderbim/blenderbim/core/resource.py b/src/blenderbim/blenderbim/core/resource.py index 63524cd03c..cf703df41b 100644 --- a/src/blenderbim/blenderbim/core/resource.py +++ b/src/blenderbim/blenderbim/core/resource.py @@ -18,42 +18,57 @@ # ############################################################################ # +from __future__ import annotations +from typing import TYPE_CHECKING, Optional, Union, Iterable -def load_resources(resource): +if TYPE_CHECKING: + import bpy + import ifcopenshell + import blenderbim.tool as tool + + +def load_resources(resource: tool.Resource) -> None: resource.load_resources() -def add_resource(tool_ifc, resource_tool, ifc_class, parent_resource=None): +def add_resource( + tool_ifc: tool.Ifc, + resource_tool: tool.Resource, + ifc_class, + parent_resource: Optional[ifcopenshell.entity_instance] = None, +) -> None: tool_ifc.run("resource.add_resource", ifc_class=ifc_class, parent_resource=parent_resource) resource_tool.load_resources() -def disable_editing_resource(resource_tool): +def disable_editing_resource(resource_tool: tool.Resource) -> None: resource_tool.disable_editing_resource() -def disable_resource_editing_ui(resource_tool): +def disable_resource_editing_ui(resource_tool: tool.Resource) -> None: resource_tool.disable_resource_editing_ui() -def enable_editing_resource(resource_tool, resource): +def enable_editing_resource(resource_tool: tool.Resource, resource) -> None: resource_tool.enable_editing_resource(resource) resource_tool.load_resource_attributes(resource) -def edit_resource(ifc, resource_tool, resource): +def edit_resource(ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: attributes = resource_tool.get_resource_attributes() ifc.run("resource.edit_resource", resource=resource, attributes=attributes) resource_tool.load_resource_properties() resource_tool.disable_editing_resource() -def remove_resource(ifc, resource_tool, resource=None): +def remove_resource(ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: ifc.run("resource.remove_resource", resource=resource) resource_tool.load_resources() -def enable_editing_resource_time(ifc_tool, resource_tool, resource): +def enable_editing_resource_time( + ifc_tool, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance +) -> None: resource_time = resource_tool.get_resource_time(resource) if resource_time is None: resource_time = ifc_tool.run("resource.add_resource_time", resource=resource) @@ -61,17 +76,21 @@ def enable_editing_resource_time(ifc_tool, resource_tool, resource): resource_tool.load_resource_time_attributes(resource_time) -def edit_resource_time(ifc, resource_tool, resource_time): +def edit_resource_time( + ifc: tool.Ifc, resource_tool: tool.Resource, resource_time: ifcopenshell.entity_instance +) -> None: attributes = resource_tool.get_resource_time_attributes() ifc.run("resource.edit_resource_time", resource_time=resource_time, attributes=attributes) resource_tool.disable_editing_resource() -def disable_editing_resource_time(resource_tool): +def disable_editing_resource_time(resource_tool: tool.Resource) -> None: resource_tool.disable_editing_resource() -def calculate_resource_work(ifc, resource_tool, resource): +def calculate_resource_work( + ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance +) -> None: if resource_tool.get_task_assignments(resource): ifc.run("resource.calculate_resource_work", resource=resource) else: @@ -81,92 +100,112 @@ def calculate_resource_work(ifc, resource_tool, resource): resource_tool.load_resources() -def enable_editing_resource_costs(resource_tool, resource): +def enable_editing_resource_costs(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: resource_tool.enable_editing_resource_costs(resource) resource_tool.disable_editing_resource_cost_value() -def disable_editing_resource_cost_value(resource_tool): +def disable_editing_resource_cost_value(resource_tool: tool.Resource) -> None: resource_tool.disable_editing_resource_cost_value() -def enable_editing_resource_cost_value(resource_tool, cost_value): +def enable_editing_resource_cost_value(resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance) -> None: resource_tool.enable_editing_cost_value_attributes(cost_value) resource_tool.load_cost_value_attributes(cost_value) -def enable_editing_resource_cost_value_formula(resource_tool, cost_value): +def enable_editing_resource_cost_value_formula( + resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance +) -> None: resource_tool.enable_editing_resource_cost_value_formula(cost_value) -def edit_resource_cost_value_formula(ifc, resource_tool, cost_value): +def edit_resource_cost_value_formula( + ifc: tool.Ifc, resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance +) -> None: formula = resource_tool.get_resource_cost_value_formula() ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula) resource_tool.disable_editing_resource_cost_value() -def edit_resource_cost_value(ifc, resource_tool, cost_value): +def edit_resource_cost_value( + ifc: tool.Ifc, resource_tool: tool.Resource, cost_value: ifcopenshell.entity_instance +) -> None: attributes = resource_tool.get_resource_cost_value_attributes() ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes) resource_tool.disable_editing_resource_cost_value() -def enable_editing_resource_base_quantity(resource_tool, resource): +def enable_editing_resource_base_quantity(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: resource_tool.enable_editing_resource_base_quantity(resource) -def add_resource_quantity(ifc, ifc_class, resource): +def add_resource_quantity(ifc: tool.Ifc, ifc_class: str, resource: ifcopenshell.entity_instance) -> None: ifc.run("resource.add_resource_quantity", resource=resource, ifc_class=ifc_class) -def remove_resource_quantity(ifc, resource): +def remove_resource_quantity(ifc: tool.Ifc, resource: ifcopenshell.entity_instance) -> None: ifc.run("resource.remove_resource_quantity", resource=resource) -def enable_editing_resource_quantity(resource_tool, resource_quantity=None): +def enable_editing_resource_quantity( + resource_tool: tool.Resource, resource_quantity: ifcopenshell.entity_instance +) -> None: resource_tool.enable_editing_resource_quantity(resource_quantity) -def disable_editing_resource_quantity(resource_tool): +def disable_editing_resource_quantity(resource_tool: tool.Resource) -> None: resource_tool.disable_editing_resource_quantity() -def edit_resource_quantity(resource_tool, ifc, physical_quantity=None): +def edit_resource_quantity( + resource_tool: tool.Resource, ifc: tool.Ifc, physical_quantity: ifcopenshell.entity_instance +) -> None: attributes = resource_tool.get_resource_quantity_attributes() ifc.run("resource.edit_resource_quantity", physical_quantity=physical_quantity, attributes=attributes) resource_tool.disable_editing_resource_quantity() -def import_resources(resource_tool, file_path): +def import_resources(resource_tool: tool.Resource, file_path: str) -> None: resource_tool.import_resources(file_path) resource_tool.load_resources() -def expand_resource(resource_tool, resource): +def expand_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: resource_tool.expand_resource(resource) resource_tool.load_resources() -def contract_resource(resource_tool, resource): +def contract_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: resource_tool.contract_resource(resource) resource_tool.load_resources() -def assign_resource(ifc, spatial, resource=None, products=None): +def assign_resource( + ifc: tool.Ifc, + spatial: tool.Spatial, + resource: ifcopenshell.entity_instance, + products: Optional[Iterable[ifcopenshell.entity_instance]] = None, +) -> None: if not products: products = spatial.get_selected_products() for product in products: rel = ifc.run("resource.assign_resource", relating_resource=resource, related_object=product) -def unassign_resource(ifc, spatial, resource=None, products=None): +def unassign_resource( + ifc: tool.Ifc, + spatial: tool.Spatial, + resource: ifcopenshell.entity_instance, + products: Optional[Iterable[ifcopenshell.entity_instance]] = None, +) -> None: if not products: products = spatial.get_selected_products() for product in products: ifc.run("resource.unassign_resource", relating_resource=resource, related_object=product) -def edit_productivity_pset(ifc, resource_tool): +def edit_productivity_pset(ifc: tool.Ifc, resource_tool: tool.Resource) -> None: resource = resource_tool.get_highlighted_resource() if resource is None: return @@ -178,7 +217,9 @@ def edit_productivity_pset(ifc, resource_tool): ifc.run("pset.edit_pset", pset=pset, properties=resource_tool.get_productivity_attributes()) -def add_usage_constraint(ifc, resource_tool, resource=None, reference_path=None): +def add_usage_constraint( + ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance, reference_path: str +) -> None: metric = resource_tool.has_metric_constraint(resource, "Usage") if metric: return print("Must remove existing metric first") @@ -198,7 +239,9 @@ def add_usage_constraint(ifc, resource_tool, resource=None, reference_path=None) ifc.run("constraint.assign_constraint", products=[resource], constraint=objective) -def remove_usage_constraint(ifc, resource_tool, resource, reference_path): +def remove_usage_constraint( + ifc: tool.Ifc, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance, reference_path: str +) -> None: constraints = resource_tool.get_constraints(resource) for constraint in constraints: metrics = resource_tool.get_metrics(constraint) @@ -210,10 +253,12 @@ def remove_usage_constraint(ifc, resource_tool, resource, reference_path): ifc.run("constraint.remove_constraint", constraint=constraint) -def go_to_resource(resource_tool, resource): +def go_to_resource(resource_tool: tool.Resource, resource: ifcopenshell.entity_instance) -> None: resource_tool.go_to_resource(resource) -def calculate_resource_usage(ifc, resource_tool, resource): +def calculate_resource_usage( + ifc: tool.Resource, resource_tool: tool.Resource, resource: ifcopenshell.entity_instance +) -> None: ifc.run("resource.calculate_resource_usage", resource=resource) resource_tool.load_resources() diff --git a/src/blenderbim/blenderbim/tool/cost.py b/src/blenderbim/blenderbim/tool/cost.py index 5d4698a24f..72acd26cd2 100644 --- a/src/blenderbim/blenderbim/tool/cost.py +++ b/src/blenderbim/blenderbim/tool/cost.py @@ -7,7 +7,7 @@ import ifcopenshell.util.cost import ifcopenshell.util.unit import blenderbim.bim.helper import json -from typing import Optional, Any, Generator +from typing import Optional, Any, Generator, Union class Cost(blenderbim.core.tool.Cost): @@ -149,7 +149,7 @@ class Cost(blenderbim.core.tool.Cost): return blenderbim.bim.helper.export_attributes(props.cost_item_attributes) @classmethod - def get_active_cost_item(cls): + def get_active_cost_item(cls) -> Union[ifcopenshell.entity_instance, None]: props = bpy.context.scene.BIMCostProperties if not props.active_cost_item_id: return None diff --git a/src/blenderbim/blenderbim/tool/resource.py b/src/blenderbim/blenderbim/tool/resource.py index 99293fcbc9..b73dac91c7 100644 --- a/src/blenderbim/blenderbim/tool/resource.py +++ b/src/blenderbim/blenderbim/tool/resource.py @@ -33,10 +33,12 @@ import ifcopenshell.util.cost import ifcopenshell.util.resource import blenderbim.bim.schema import ifcopenshell.util.constraint +from typing import Any, Union + class Resource(blenderbim.core.tool.Resource): @classmethod - def load_resources(cls): + def load_resources(cls) -> None: def create_new_resource_li(resource, level_index): new = bpy.context.scene.BIMResourceTreeProperties.resources.add() new.ifc_definition_id = resource.id() @@ -66,42 +68,44 @@ class Resource(blenderbim.core.tool.Resource): props.is_editing = True @classmethod - def load_resource_properties(cls): + def load_resource_properties(cls) -> None: props = bpy.context.scene.BIMResourceProperties tprops = bpy.context.scene.BIMResourceTreeProperties props.is_resource_update_enabled = False for item in tprops.resources: resource = tool.Ifc.get().by_id(item.ifc_definition_id) item.name = resource.Name if resource.Name else "Unnamed" - item.schedule_usage = resource.Usage.ScheduleUsage if (resource.Usage and resource.Usage.ScheduleUsage) else 0 + item.schedule_usage = ( + resource.Usage.ScheduleUsage if (resource.Usage and resource.Usage.ScheduleUsage) else 0 + ) props.is_resource_update_enabled = True @classmethod - def disable_editing_resource(cls): + def disable_editing_resource(cls) -> None: bpy.context.scene.BIMResourceProperties.active_resource_id = 0 bpy.context.scene.BIMResourceProperties.active_resource_time_id = 0 @classmethod - def disable_resource_editing_ui(cls): + def disable_resource_editing_ui(cls) -> None: bpy.context.scene.BIMResourceProperties.is_editing = False @classmethod - def load_resource_attributes(cls, resource): + def load_resource_attributes(cls, resource: ifcopenshell.entity_instance) -> None: blenderbim.bim.helper.import_attributes2(resource, bpy.context.scene.BIMResourceProperties.resource_attributes) @classmethod - def enable_editing_resource(cls, resource): + def enable_editing_resource(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.active_resource_id = resource.id() props.resource_attributes.clear() props.editing_resource_type = "ATTRIBUTES" @classmethod - def get_resource_attributes(cls): + def get_resource_attributes(cls) -> dict[str, Any]: return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.resource_attributes) @classmethod - def enable_editing_resource_time(cls, resource): + def enable_editing_resource_time(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.resource_time_attributes.clear() props.active_resource_time_id = resource.Usage.id() @@ -109,11 +113,11 @@ class Resource(blenderbim.core.tool.Resource): props.editing_resource_type = "USAGE" @classmethod - def get_resource_time(cls, resource): - return resource.Usage if resource.Usage else None + def get_resource_time(cls, resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]: + return resource.Usage or None @classmethod - def load_resource_time_attributes(cls, resource_time): + def load_resource_time_attributes(cls, resource_time: ifcopenshell.entity_instance) -> None: def callback(name, prop, data): if prop.data_type == "string": if isinstance(data[name], datetime): @@ -128,7 +132,7 @@ class Resource(blenderbim.core.tool.Resource): ) @classmethod - def get_resource_time_attributes(cls): + def get_resource_time_attributes(cls) -> dict[str, Any]: def callback(attributes, prop): if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime": if prop.is_null: @@ -147,20 +151,19 @@ class Resource(blenderbim.core.tool.Resource): return blenderbim.bim.helper.export_attributes(props.resource_time_attributes, callback) @classmethod - def enable_editing_resource_costs(cls, resource): + def enable_editing_resource_costs(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.active_resource_id = resource.id() props.editing_resource_type = "COSTS" - resource @classmethod - def disable_editing_resource_cost_value(cls): + def disable_editing_resource_cost_value(cls) -> None: props = bpy.context.scene.BIMResourceProperties props.active_cost_value_id = 0 props.cost_value_editing_type = "" @classmethod - def enable_editing_resource_cost_value_formula(cls, cost_value): + def enable_editing_resource_cost_value_formula(cls, cost_value: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.cost_value_attributes.clear() props.active_cost_value_id = cost_value.id() @@ -168,7 +171,7 @@ class Resource(blenderbim.core.tool.Resource): props.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value) if cost_value else "" @classmethod - def load_cost_value_attributes(cls, cost_value): + def load_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance): def callback(name, prop, data): if name == "AppliedValue": # TODO: for now, only support simple IfcValues (which are effectively IfcMonetaryMeasure) @@ -221,7 +224,7 @@ class Resource(blenderbim.core.tool.Resource): blenderbim.bim.helper.import_attributes2(cost_value, props.cost_value_attributes, callback) @classmethod - def enable_editing_cost_value_attributes(cls, cost_value): + def enable_editing_cost_value_attributes(cls, cost_value: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.cost_value_attributes.clear() props.active_cost_value_id = cost_value.id() @@ -232,7 +235,7 @@ class Resource(blenderbim.core.tool.Resource): return bpy.context.scene.BIMResourceProperties.cost_value_formula @classmethod - def get_resource_cost_value_attributes(cls): + def get_resource_cost_value_attributes(cls) -> dict[str, Any]: def callback(attributes, prop): if prop.name == "UnitBasisValue": if prop.is_null: @@ -257,28 +260,28 @@ class Resource(blenderbim.core.tool.Resource): ) @classmethod - def enable_editing_resource_base_quantity(cls, resource): + def enable_editing_resource_base_quantity(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.active_resource_id = resource.id() props.editing_resource_type = "QUANTITY" @classmethod - def enable_editing_resource_quantity(cls, resource_quantity): + def enable_editing_resource_quantity(cls, resource_quantity: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties props.quantity_attributes.clear() props.is_editing_quantity = True blenderbim.bim.helper.import_attributes2(resource_quantity, props.quantity_attributes) @classmethod - def disable_editing_resource_quantity(cls): + def disable_editing_resource_quantity(cls) -> None: bpy.context.scene.BIMResourceProperties.is_editing_quantity = False @classmethod - def get_resource_quantity_attributes(cls): + def get_resource_quantity_attributes(cls) -> dict[str, Any]: return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMResourceProperties.quantity_attributes) @classmethod - def expand_resource(cls, resource): + def expand_resource(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties contracted_resources = json.loads(props.contracted_resources) if not resource.id() in contracted_resources: @@ -287,14 +290,14 @@ class Resource(blenderbim.core.tool.Resource): props.contracted_resources = json.dumps(contracted_resources) @classmethod - def contract_resource(cls, resource): + def contract_resource(cls, resource: ifcopenshell.entity_instance) -> None: props = bpy.context.scene.BIMResourceProperties contracted_resources = json.loads(props.contracted_resources) contracted_resources.append(resource.id()) props.contracted_resources = json.dumps(contracted_resources) @classmethod - def import_resources(cls, file_path): + def import_resources(cls, file_path: str) -> None: from ifc4d.csv2ifc import Csv2Ifc start = time.time() @@ -305,7 +308,7 @@ class Resource(blenderbim.core.tool.Resource): print("Importing Resources CSV finished in {:.2f} seconds".format(time.time() - start)) @classmethod - def get_highlighted_resource(cls): + def get_highlighted_resource(cls) -> Union[ifcopenshell.entity_instance, None]: resources = len(bpy.context.scene.BIMResourceTreeProperties.resources) if resources and resources > bpy.context.scene.BIMResourceProperties.active_resource_index: return tool.Ifc.get().by_id( @@ -315,7 +318,7 @@ class Resource(blenderbim.core.tool.Resource): ) @classmethod - def clear_productivity_data(cls, props): + def clear_productivity_data(cls, props: bpy.types.PropertyGroup) -> None: for duration_prop in props.quantity_consumed or []: if duration_prop.name == "BaseQuantityConsumed": duration_prop.years = 0 @@ -328,7 +331,7 @@ class Resource(blenderbim.core.tool.Resource): props.quantity_produced_name = "" @classmethod - def load_productivity_data(cls): + def load_productivity_data(cls) -> None: duration_props = None for collection_prop in bpy.context.scene.BIMResourceProductivity.quantity_consumed: duration_props = collection_prop if collection_prop.name == "BaseQuantityConsumed" else None @@ -358,7 +361,7 @@ class Resource(blenderbim.core.tool.Resource): duration_props.seconds = durations_attributes["seconds"] @classmethod - def get_productivity_attributes(cls): + def get_productivity_attributes(cls) -> dict[str, Any]: props = bpy.context.scene.BIMResourceProductivity productivity = {} if props.quantity_consumed: @@ -370,7 +373,9 @@ class Resource(blenderbim.core.tool.Resource): return productivity @classmethod - def get_productivity(cls, resource, should_inherit=False): + def get_productivity( + cls, resource: ifcopenshell.entity_instance, should_inherit: bool = False + ) -> ifcopenshell.util.resource.PRODUCTIVITY_PSET_DATA: return ifcopenshell.util.resource.get_productivity(resource, should_inherit=should_inherit) @classmethod @@ -380,29 +385,29 @@ class Resource(blenderbim.core.tool.Resource): return return tool.Ifc.run( "pset.edit_pset", - pset= tool.Ifc.get().by_id(productivity["id"]), + pset=tool.Ifc.get().by_id(productivity["id"]), properties=attributes, ) @classmethod - def get_constraints(cls, resource): + def get_constraints(cls, resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: return ifcopenshell.util.constraint.get_constraints(product=resource) @classmethod - def get_metrics(cls, constraint): + def get_metrics(cls, constraint: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: return ifcopenshell.util.constraint.get_metrics(constraint) @classmethod - def get_metric_reference(cls, metric, is_deep=True): + def get_metric_reference(cls, metric: ifcopenshell.entity_instance, is_deep: bool = True): return ifcopenshell.util.constraint.get_metric_reference(metric, is_deep=is_deep) @classmethod - def has_metric_constraint(cls, resource, attribute): + def has_metric_constraint(cls, resource: ifcopenshell.entity_instance, attribute): metrics = ifcopenshell.util.constraint.get_metric_constraints(resource, attribute) return True if metrics else False @classmethod - def run_edit_resource_time(cls, resource, attributes): + def run_edit_resource_time(cls, resource: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None: if not resource.Usage: tool.Ifc.run( "resource.add_resource_time", @@ -411,7 +416,7 @@ class Resource(blenderbim.core.tool.Resource): tool.Ifc.run("resource.edit_resource_time", resource_time=resource.Usage, attributes=attributes) @classmethod - def go_to_resource(cls, resource): + def go_to_resource(cls, resource: ifcopenshell.entity_instance) -> None: def get_ancestors_ids(resource): ids = [] for rel in resource.Nests or []: @@ -427,24 +432,22 @@ class Resource(blenderbim.core.tool.Resource): bpy.context.scene.BIMResourceProperties.contracted_resources = json.dumps(contracted_resources) cls.load_resources() - resource_props = bpy.context.scene.BIMResourceTreeProperties expanded_resources = [item.ifc_definition_id for item in resource_props.resources] bpy.context.scene.BIMResourceProperties.active_resource_index = expanded_resources.index(resource.id()) - @classmethod - def run_calculate_resource_usage(cls, resource): + def run_calculate_resource_usage(cls, resource: ifcopenshell.entity_instance) -> None: tool.Ifc.run("resource.calculate_resource_usage", resource=resource) @classmethod - def get_task_assignments(cls, resource): + def get_task_assignments(cls, resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]: return ifcopenshell.util.resource.get_task_assignments(resource) @classmethod - def get_nested_resources(cls, resource): + def get_nested_resources(cls, resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: return ifcopenshell.util.resource.get_nested_resources(resource) @classmethod - def is_attribute_locked(cls, resource, attribute): - return ifcopenshell.util.constraint.is_attribute_locked(resource, attribute) \ No newline at end of file + def is_attribute_locked(cls, resource: ifcopenshell.entity_instance, attribute) -> bool: + return ifcopenshell.util.constraint.is_attribute_locked(resource, attribute) diff --git a/src/ifccsv/ifccsv.py b/src/ifccsv/ifccsv.py index f89f152a1e..aabeb51c80 100755 --- a/src/ifccsv/ifccsv.py +++ b/src/ifccsv/ifccsv.py @@ -29,7 +29,7 @@ import ifcopenshell.util.selector import ifcopenshell.util.element import ifcopenshell.util.schema from statistics import mean -from typing import Optional, Union +from typing import Optional, Union, Literal try: from odf.namespaces import OFFICENS @@ -53,6 +53,14 @@ except: pass # No Pandas support +FILE_FORMAT = Literal[ + "csv", + "ods", + "xlsx", + "pd", +] + + class IfcCsv: def __init__(self): self.headers = [] @@ -66,7 +74,7 @@ class IfcCsv: attributes, headers=None, output=None, - format=None, + format: FILE_FORMAT = None, should_preserve_existing: bool = False, include_global_id: bool = True, delimiter: str = ",", @@ -392,7 +400,11 @@ class IfcCsv: bool_true: str = "YES", bool_false: str = "NO", ) -> None: - ext = table.split(".")[-1].lower() + """ + Args: + table: filepath to the table. + """ + ext: FILE_FORMAT = table.split(".")[-1].lower() if ext == "csv": self.import_csv(ifc_file, table, attributes, delimiter, null, empty, bool_true, bool_false) diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value_formula.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value_formula.py index a9af7572b6..1c0b59a79c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value_formula.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value_formula.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell +import ifcopenshell.api import ifcopenshell.util.cost import ifcopenshell.util.unit import ifcopenshell.util.element diff --git a/src/ifcopenshell-python/ifcopenshell/util/resource.py b/src/ifcopenshell-python/ifcopenshell/util/resource.py index 59473bb2ca..bfc1aabed6 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/resource.py +++ b/src/ifcopenshell-python/ifcopenshell/util/resource.py @@ -16,18 +16,24 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell.util.cost import ifcopenshell.util.element import ifcopenshell.util.date +from typing import Union, Any -def get_productivity(resource, should_inherit=True): +PRODUCTIVITY_PSET_DATA = Union[dict[str, Any], None] + + +def get_productivity(resource: ifcopenshell.entity_instance, should_inherit: bool = True) -> PRODUCTIVITY_PSET_DATA: productivity = ifcopenshell.util.element.get_psets(resource).get("EPset_Productivity", None) if should_inherit and not productivity: - #Note: This is not part of the Schema - but it makes sense to inherit from parent + # Note: This is not part of the Schema - but it makes sense to inherit from parent productivity = get_parent_productivity(resource) return productivity -def get_parent_productivity(resource): + +def get_parent_productivity(resource: ifcopenshell.entity_instance) -> PRODUCTIVITY_PSET_DATA: if not resource.Nests: return else: @@ -36,34 +42,34 @@ def get_parent_productivity(resource): return productivity -def get_unit_consumed(productivity): +def get_unit_consumed(productivity: PRODUCTIVITY_PSET_DATA) -> Union[Any, None]: duration = productivity.get("BaseQuantityConsumed", None) if not duration: return return ifcopenshell.util.date.ifc2datetime(duration) -def get_quantity_produced(productivity): +def get_quantity_produced(productivity: PRODUCTIVITY_PSET_DATA) -> float: if not productivity: - return 0 - return productivity.get("BaseQuantityProducedValue", 0) + return 0.0 + return productivity.get("BaseQuantityProducedValue", 0.0) -def get_quantity_produced_name(productivity): +def get_quantity_produced_name(productivity: PRODUCTIVITY_PSET_DATA): if not productivity: return "" return productivity.get("BaseQuantityProducedName", "") -def get_total_quantity_produced(resource, quantity_name_in_process): - def get_product_quantity(product, quantity_name): +def get_total_quantity_produced(resource: ifcopenshell.entity_instance, quantity_name_in_process: str) -> float: + def get_product_quantity(product: ifcopenshell.entity_instance, quantity_name: str): psets = ifcopenshell.util.element.get_psets(product) for pset in psets.values(): for name, value in pset.items(): if name == quantity_name: return float(value) - total = 0 + total = 0.0 products = get_parametric_resource_products(resource) if quantity_name_in_process == "Count": total = len(products) @@ -73,7 +79,7 @@ def get_total_quantity_produced(resource, quantity_name_in_process): return total -def get_parametric_resource_products(resource): +def get_parametric_resource_products(resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: products = [] for rel in resource.HasAssignments or []: if not rel.is_a("IfcRelAssignsToProcess"): @@ -84,14 +90,15 @@ def get_parametric_resource_products(resource): products.append(rel2.RelatingProduct) return products -def get_task_assignments(resource): + +def get_task_assignments(resource: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]: for rel in resource.HasAssignments or []: if not rel.is_a("IfcRelAssignsToProcess"): continue return rel.RelatingProcess -def get_resource_required_work(resource): +def get_resource_required_work(resource: ifcopenshell.entity_instance) -> Union[str, None]: productivity = get_productivity(resource) if productivity: quantity_produced = get_quantity_produced(productivity) @@ -114,33 +121,38 @@ def get_resource_required_work(resource): return iso_string -def get_nested_resources(resource): +def get_nested_resources(resource: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: return [object for rel in resource.IsNestedBy or [] for object in rel.RelatedObjects] -def get_cost(resource): +def get_cost(resource: ifcopenshell.entity_instance) -> tuple[float, Union[str, None]]: base_costs = getattr(resource, "BaseCosts", []) - costs = [ - ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) - for cost_value in base_costs - ] if base_costs else [] + costs = ( + [ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) for cost_value in base_costs] + if base_costs + else [] + ) cost = sum(costs) - unit_basis = next( - (cost_value.UnitBasis for cost_value in base_costs if cost_value.UnitBasis), - None - ) if base_costs else None - unit = unit_basis.UnitComponent.Name if unit_basis and unit_basis.UnitComponent.is_a("IfcConversionBasedUnit") else None + unit_basis = ( + next((cost_value.UnitBasis for cost_value in base_costs if cost_value.UnitBasis), None) if base_costs else None + ) + unit = ( + unit_basis.UnitComponent.Name + if unit_basis and unit_basis.UnitComponent.is_a("IfcConversionBasedUnit") + else None + ) return cost, unit -def get_quantity(resource): - total = 0 + +def get_quantity(resource: ifcopenshell.entity_instance) -> float: if resource.BaseQuantity: return resource.BaseQuantity[3] if resource.Usage and resource.Usage.ScheduleWork: duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork) return duration.total_seconds() / 3600 -def get_parent_cost(resource): + +def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[None, tuple[float, Union[str, None]]]: if not resource.Nests: return else: