diff --git a/src/blenderbim/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py index 2c21ba8352..6795a02147 100644 --- a/src/blenderbim/blenderbim/bim/module/model/opening.py +++ b/src/blenderbim/blenderbim/bim/module/model/opening.py @@ -24,10 +24,14 @@ import shapely import logging import numpy as np import ifcopenshell +import ifcopenshell.api +import ifcopenshell.geom import ifcopenshell.util.shape import ifcopenshell.util.element import ifcopenshell.util.shape_builder +import ifcopenshell.util.placement import ifcopenshell.util.representation +import ifcopenshell.util.unit import blenderbim.tool as tool import blenderbim.core.geometry import blenderbim.bim.import_ifc as import_ifc diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index 8d255a38a0..96cef5e893 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -25,9 +25,13 @@ import ifcopenshell.util.system import ifcopenshell.util.element import ifcopenshell.util.placement import ifcopenshell.util.representation +import ifcopenshell.util.type +import ifcopenshell.util.unit import blenderbim.tool as tool +import blenderbim.core.aggregate import blenderbim.core.type import blenderbim.core.geometry +import blenderbim.core.spatial from . import wall, slab, profile, mep from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.model.data import AuthoringData @@ -273,7 +277,7 @@ class AddConstrTypeInstance(bpy.types.Operator): obj.location[2] = collection_obj.location[2] + bpy.context.scene.BIMModelProperties.rl2 @staticmethod - def generate_layered_element(ifc_class, relating_type): + def generate_layered_element(ifc_class: str, relating_type: ifcopenshell.entity_instance) -> bool: layer_set_direction = None parametric = ifcopenshell.util.element.get_psets(relating_type).get("EPset_Parametric") @@ -297,6 +301,7 @@ class AddConstrTypeInstance(bpy.types.Operator): material = ifcopenshell.util.element.get_material(tool.Ifc.get_entity(obj)) material.LayerSetDirection = layer_set_direction return True + return False class ChangeTypePage(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/model/profile.py b/src/blenderbim/blenderbim/bim/module/model/profile.py index 0b889ba035..8a4bde560d 100644 --- a/src/blenderbim/blenderbim/bim/module/model/profile.py +++ b/src/blenderbim/blenderbim/bim/module/model/profile.py @@ -21,14 +21,18 @@ import copy import bmesh import mathutils.geometry import ifcopenshell +import ifcopenshell.api import ifcopenshell.util.type import ifcopenshell.util.unit import ifcopenshell.util.element +import ifcopenshell.util.placement +import ifcopenshell.util.representation import blenderbim.bim.handler import blenderbim.tool as tool import blenderbim.core.type import blenderbim.core.geometry import blenderbim.core.material +import blenderbim.core.root from math import pi, degrees, inf from mathutils import Vector, Matrix, Quaternion from blenderbim.bim.module.geometry.helper import Helper diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py index fb042a9046..de1d44715b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/slab.py +++ b/src/blenderbim/blenderbim/bim/module/model/slab.py @@ -29,6 +29,7 @@ import ifcopenshell.util.type import blenderbim.bim.handler import blenderbim.core.type import blenderbim.core.geometry +import blenderbim.core.root import blenderbim.tool as tool from math import radians from mathutils import Vector, Matrix @@ -113,7 +114,7 @@ def calculate_quantities(usecase_path, ifc_file, settings): class DumbSlabGenerator: - def __init__(self, relating_type): + def __init__(self, relating_type: ifcopenshell.entity_instance): self.relating_type = relating_type def generate(self): diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index 59f49b254b..3463cb5f78 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -24,7 +24,9 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.unit import ifcopenshell.util.element +import ifcopenshell.util.placement import ifcopenshell.util.representation +import ifcopenshell.util.type import mathutils.geometry import blenderbim.bim.handler import blenderbim.core.type diff --git a/src/blenderbim/test/tool/test_root.py b/src/blenderbim/test/tool/test_root.py index 448fb4bc4d..099880df3f 100644 --- a/src/blenderbim/test/tool/test_root.py +++ b/src/blenderbim/test/tool/test_root.py @@ -18,6 +18,7 @@ import bpy import ifcopenshell +import ifcopenshell.api import blenderbim.core.tool import blenderbim.tool as tool from test.bim.bootstrap import NewFile diff --git a/src/ifcopenshell-python/ifcopenshell/api/type/map_type_representations.py b/src/ifcopenshell-python/ifcopenshell/api/type/map_type_representations.py index b8480dc211..940fd25902 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/type/map_type_representations.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/map_type_representations.py @@ -22,7 +22,12 @@ import ifcopenshell.util.element class Usecase: - def __init__(self, file, related_object=None, relating_type=None): + def __init__( + self, + file: ifcopenshell.file, + related_object: ifcopenshell.entity_instance, + relating_type: ifcopenshell.entity_instance, + ): """Ensures that all occurrences has the same representation as the type If a type has a representation, all occurrences must have the same @@ -87,7 +92,7 @@ class Usecase: "relating_type": relating_type, } - def execute(self): + def execute(self) -> None: if not self.settings["relating_type"].RepresentationMaps: return representations = [] diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 4f6ead203b..4e1a03eb1e 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -19,7 +19,7 @@ from __future__ import annotations import ifcopenshell import ifcopenshell.util.element -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Optional, Union, Literal, overload def get_pset( @@ -53,13 +53,13 @@ def get_pset( :type should_inherit: bool,optional :return: A dictionary of property names and values, or a single value if a property is specified. - :rtype: dict[str, Any] + :rtype: Union[Any, dict[str, Any]] Example: .. code:: python - element = ifcopenshell.by_type("IfcWall")[0] + element = ifc_file.by_type("IfcWall")[0] psets_and_qtos = ifcopenshell.util.element.get_pset(element, "Pset_WallCommon") """ pset = None @@ -132,6 +132,8 @@ def get_psets( :type qtos_only: bool,optional :param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type. :type should_inherit: bool,optional + :param verbose: More detailed prop values, defaults to False. + :type verbose: bool,optional :return: Key, value pair of psets' names and their properties' names & values :rtype: dict[str, dict[str, Any]] @@ -139,7 +141,7 @@ def get_psets( .. code:: python - element = ifcopenshell.by_type("IfcWall")[0] + element = ifc_file.by_type("IfcWall")[0] psets = ifcopenshell.util.element.get_psets(element, psets_only=True) qsets = ifcopenshell.util.element.get_psets(element, qtos_only=True) psets_and_qtos = ifcopenshell.util.element.get_psets(element) @@ -173,9 +175,20 @@ def get_psets( return psets +@overload def get_property_definition( - definition: ifcopenshell.entity_instance, prop: Optional[str] = None, verbose=False + definition: Optional[ifcopenshell.entity_instance], prop: None = None, verbose=False +) -> dict[str, Any]: ... +@overload +def get_property_definition(definition: Optional[ifcopenshell.entity_instance], prop: str, verbose=False) -> Any: ... +@overload +def get_property_definition(definition: None, prop: None = None, verbose: bool = False) -> None: ... +def get_property_definition( + definition: Optional[ifcopenshell.entity_instance], prop: Optional[str] = None, verbose=False ) -> Union[Any, dict[str, Any]]: + """if prop name is not provided in `prop`, will return dict of all available properties + otherwise will return the value of the specified `prop`. + """ if not definition: return @@ -214,6 +227,12 @@ def get_property_definition( return props +@overload +def get_quantity(quantities: list[ifcopenshell.entity_instance], name: str, verbose: Literal[False] = False) -> Any: ... +@overload +def get_quantity( + quantities: list[ifcopenshell.entity_instance], name: str, verbose: Literal[True] +) -> dict[str, Any]: ... def get_quantity( quantities: list[ifcopenshell.entity_instance], name: str, verbose=False ) -> Union[Any, dict[str, Any]]: @@ -232,7 +251,17 @@ def get_quantity( return result -def get_quantities(quantities: list[ifcopenshell.entity_instance], verbose=False) -> dict[str, dict[str, Any]]: +@overload +def get_quantities( + quantities: list[ifcopenshell.entity_instance], verbose: Literal[False] = False +) -> dict[str, Any]: ... +@overload +def get_quantities( + quantities: list[ifcopenshell.entity_instance], verbose: Literal[True] +) -> dict[str, dict[str, Any]]: ... +def get_quantities( + quantities: list[ifcopenshell.entity_instance], verbose=False +) -> dict[str, Union[Any, dict[str, Any]]]: results = {} for quantity in quantities or []: if quantity.is_a("IfcPhysicalSimpleQuantity"): @@ -257,6 +286,12 @@ def get_quantities(quantities: list[ifcopenshell.entity_instance], verbose=False return results +@overload +def get_property(properties: list[ifcopenshell.entity_instance], name: str, verbose: Literal[False] = False) -> Any: ... +@overload +def get_property( + properties: list[ifcopenshell.entity_instance], name: str, verbose: Literal[True] +) -> dict[str, Any]: ... def get_property( properties: list[ifcopenshell.entity_instance], name: str, verbose=False ) -> Union[Any, dict[str, Any]]: @@ -285,7 +320,17 @@ def get_property( return result -def get_properties(properties: list[ifcopenshell.entity_instance], verbose=False) -> dict[str, dict[str, Any]]: +@overload +def get_properties( + properties: list[ifcopenshell.entity_instance], verbose: Literal[False] = False +) -> dict[str, Any]: ... +@overload +def get_properties( + properties: list[ifcopenshell.entity_instance], verbose: Literal[True] +) -> dict[str, dict[str, Any]]: ... +def get_properties( + properties: list[ifcopenshell.entity_instance], verbose=False +) -> dict[str, Union[Any, dict[str, Any]]]: results = {} for prop in properties or []: ifc_class = prop.is_a() @@ -433,7 +478,7 @@ def get_shape_aspects(element: ifcopenshell.entity_instance) -> list[ifcopenshel def get_material( element: ifcopenshell.entity_instance, should_skip_usage=False, should_inherit=True -) -> ifcopenshell.entity_instance: +) -> Union[ifcopenshell.entity_instance, None]: """Gets the material of the element The material may be a single material, material set (layered, profiled, or @@ -449,8 +494,8 @@ def get_material( :param should_inherit: If True, any inherited materials from associated types will be considered. :type should_inherit: bool - :return: The associated material of the element. - :rtype: ifcopenshell.entity_instance.entity_instance + :return: The associated material of the element or `None`. + :rtype: Union[ifcopenshell.entity_instance.entity_instance, None] Example: diff --git a/src/ifcopenshell-python/ifcopenshell/util/system.py b/src/ifcopenshell-python/ifcopenshell/util/system.py index 0c8789a098..3a5be9693f 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/system.py +++ b/src/ifcopenshell-python/ifcopenshell/util/system.py @@ -17,9 +17,10 @@ # along with IfcOpenShell. If not, see . -import ifcopenshell.util +import ifcopenshell.util.system +from typing import Optional, Union, Literal -group_types = { +group_types: dict[str, tuple[str, ...]] = { "IfcZone": ("IfcZone", "IfcSpace", "IfcSpatialZone"), "IfcBuiltSystem": ( "IfcBuiltElement", @@ -39,22 +40,24 @@ group_types = { "IfcGroup": ("IfcObjectDefinition",), } +FLOW_DIRECTION = Literal["SINK", "SOURCE", "SOURCEANDSINK", "NOTEDEFINED"] -def is_assignable(product, system) -> bool: + +def is_assignable(product: ifcopenshell.entity_instance, system: ifcopenshell.entity_instance) -> bool: for assignable in group_types.get(system.is_a(), ()): if product.is_a(assignable): return True return False -def get_system_elements(system): +def get_system_elements(system: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: results = [] for rel in system.IsGroupedBy: results.extend(rel.RelatedObjects) return results -def get_element_systems(element): +def get_element_systems(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: results = [] for rel in element.HasAssignments: if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.is_a() in ( @@ -67,7 +70,9 @@ def get_element_systems(element): return results -def get_ports(element, flow_direction=None): +def get_ports( + element: ifcopenshell.entity_instance, flow_direction: Optional[FLOW_DIRECTION] = None +) -> list[ifcopenshell.entity_instance]: results = [] for rel in getattr(element, "IsNestedBy", []) or []: for port in rel.RelatedObjects: @@ -85,14 +90,14 @@ def get_ports(element, flow_direction=None): return results -def get_connected_port(port): +def get_connected_port(port: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]: for rel in port.ConnectedTo: return rel.RelatedPort for rel in port.ConnectedFrom: return rel.RelatingPort -def get_port_element(port): +def get_port_element(port: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance: if hasattr(port, "Nests"): for rel in port.Nests: return rel.RelatingObject @@ -102,7 +107,9 @@ def get_port_element(port): return rel.RelatedElement -def get_connected_to(element, flow_direction=None): +def get_connected_to( + element: ifcopenshell.entity_instance, flow_direction: Optional[FLOW_DIRECTION] = None +) -> list[ifcopenshell.entity_instance]: results = [] for port in ifcopenshell.util.system.get_ports(element, flow_direction=flow_direction): for rel in port.ConnectedTo: @@ -115,7 +122,9 @@ def get_connected_to(element, flow_direction=None): return results -def get_connected_from(element, flow_direction=None): +def get_connected_from( + element: ifcopenshell.entity_instance, flow_direction: Optional[FLOW_DIRECTION] = None +) -> list[ifcopenshell.entity_instance]: results = [] for port in ifcopenshell.util.system.get_ports(element, flow_direction=flow_direction): for rel in port.ConnectedFrom: diff --git a/src/ifcopenshell-python/test/api/project/test_append_asset.py b/src/ifcopenshell-python/test/api/project/test_append_asset.py index 3e03be43d5..bca7a1580d 100644 --- a/src/ifcopenshell-python/test/api/project/test_append_asset.py +++ b/src/ifcopenshell-python/test/api/project/test_append_asset.py @@ -18,6 +18,7 @@ import test.bootstrap import ifcopenshell.api +import ifcopenshell.util.element class TestAppendAsset(test.bootstrap.IFC4): diff --git a/src/ifcopenshell-python/test/api/pset/test_add_pset.py b/src/ifcopenshell-python/test/api/pset/test_add_pset.py index 3170b53abd..9d18e16ee2 100644 --- a/src/ifcopenshell-python/test/api/pset/test_add_pset.py +++ b/src/ifcopenshell-python/test/api/pset/test_add_pset.py @@ -18,6 +18,7 @@ import test.bootstrap import ifcopenshell.api +import ifcopenshell.util.element class TestAddPset(test.bootstrap.IFC4): diff --git a/src/ifcopenshell-python/test/api/pset/test_add_qto.py b/src/ifcopenshell-python/test/api/pset/test_add_qto.py index d4cbd74a5c..3afb847c89 100644 --- a/src/ifcopenshell-python/test/api/pset/test_add_qto.py +++ b/src/ifcopenshell-python/test/api/pset/test_add_qto.py @@ -18,6 +18,7 @@ import test.bootstrap import ifcopenshell.api +import ifcopenshell.util.element class TestAddQto(test.bootstrap.IFC4): diff --git a/src/ifcopenshell-python/test/api/root/test_copy_class.py b/src/ifcopenshell-python/test/api/root/test_copy_class.py index 5fcaf8cb90..a4177150fa 100644 --- a/src/ifcopenshell-python/test/api/root/test_copy_class.py +++ b/src/ifcopenshell-python/test/api/root/test_copy_class.py @@ -19,6 +19,8 @@ import numpy import test.bootstrap import ifcopenshell.api +import ifcopenshell.util +import ifcopenshell.util.system class TestCopyClass(test.bootstrap.IFC4): diff --git a/src/ifcopenshell-python/test/api/system/test_assign_port.py b/src/ifcopenshell-python/test/api/system/test_assign_port.py index 836222298c..130e208b02 100644 --- a/src/ifcopenshell-python/test/api/system/test_assign_port.py +++ b/src/ifcopenshell-python/test/api/system/test_assign_port.py @@ -19,6 +19,7 @@ import numpy import test.bootstrap import ifcopenshell.api +import ifcopenshell.util.placement import ifcopenshell.util.system