diff --git a/src/blenderbim/blenderbim/bim/module/cost/data.py b/src/blenderbim/blenderbim/bim/module/cost/data.py
index b1a7d6f365..61bf88ddc3 100644
--- a/src/blenderbim/blenderbim/bim/module/cost/data.py
+++ b/src/blenderbim/blenderbim/bim/module/cost/data.py
@@ -19,10 +19,13 @@
import bpy
import ifcopenshell
import ifcopenshell.util.cost
+import ifcopenshell.util.date
import ifcopenshell.util.element
+import ifcopenshell.util.unit
import blenderbim.tool as tool
import blenderbim.bim.schema
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
+from typing import Any
def refresh():
@@ -34,6 +37,7 @@ def refresh():
class CostSchedulesData:
data = {}
is_loaded = False
+ _cost_values: dict[int, dict[str, Any]]
@classmethod
def load(cls):
diff --git a/src/blenderbim/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py
index 1d55fb305d..5a7e517d71 100644
--- a/src/blenderbim/blenderbim/bim/module/model/opening.py
+++ b/src/blenderbim/blenderbim/bim/module/model/opening.py
@@ -44,6 +44,7 @@ from bpy.types import SpaceView3D
from bpy.props import FloatProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from gpu_extras.batch import batch_for_shader
+from typing import Union, Optional, Any
class AddFilledOpening(bpy.types.Operator, tool.Ifc.Operator):
@@ -59,7 +60,12 @@ class AddFilledOpening(bpy.types.Operator, tool.Ifc.Operator):
class FilledOpeningGenerator:
- def generate(self, filling_obj, voided_obj, target=None):
+ def generate(
+ self,
+ filling_obj: Union[bpy.types.Object, None],
+ voided_obj: Union[bpy.types.Object, None],
+ target: Optional[Vector] = None,
+ ) -> None:
props = bpy.context.scene.BIMModelProperties
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
@@ -187,7 +193,7 @@ class FilledOpeningGenerator:
should_sync_changes_first=False,
)
- def regenerate_from_type(self, usecase_path, ifc_file, settings):
+ def regenerate_from_type(self, usecase_path: str, ifc_file: ifcopenshell.file, settings: dict[str, Any]) -> None:
relating_type = settings["relating_type"]
for related_object in settings["related_objects"]:
@@ -252,7 +258,9 @@ class FilledOpeningGenerator:
should_sync_changes_first=False,
)
- def generate_opening_from_filling(self, filling, filling_obj):
+ def generate_opening_from_filling(
+ self, filling: ifcopenshell.entity_instance, filling_obj: bpy.types.Object
+ ) -> ifcopenshell.entity_instance:
# Since openings are reused later, we give a default thickness of 1.2m
# which should cover the majority of curved, or super thick walls.
thickness = 1.2
@@ -346,7 +354,9 @@ class FilledOpeningGenerator:
return True
return False
- def get_existing_opening_occurrence_if_any(self, filling):
+ def get_existing_opening_occurrence_if_any(
+ self, filling: ifcopenshell.entity_instance
+ ) -> Union[ifcopenshell.entity_instance, None]:
filling_type = ifcopenshell.util.element.get_type(filling)
if filling_type:
filling_occurrences = ifcopenshell.util.element.get_types(filling_type)
diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/data.py b/src/blenderbim/blenderbim/bim/module/pset_template/data.py
index 96c17cc712..77b6685a36 100644
--- a/src/blenderbim/blenderbim/bim/module/pset_template/data.py
+++ b/src/blenderbim/blenderbim/bim/module/pset_template/data.py
@@ -21,6 +21,7 @@ import bpy
import pathlib
import ifcopenshell
import ifcopenshell.util.attribute
+import ifcopenshell.util.doc
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
diff --git a/src/blenderbim/blenderbim/core/cost.py b/src/blenderbim/blenderbim/core/cost.py
index e703844b23..f23cb60a49 100644
--- a/src/blenderbim/blenderbim/core/cost.py
+++ b/src/blenderbim/blenderbim/core/cost.py
@@ -109,7 +109,9 @@ def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost):
cost.load_cost_schedule_tree()
-def assign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, prop_name):
+def assign_cost_item_type(
+ ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance, prop_name
+):
product_types = spatial.get_selected_product_types()
[
ifc.run("control.assign_control", relating_control=cost_item, related_object=product_type)
@@ -118,7 +120,9 @@ def assign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial,
cost.load_cost_item_types(cost_item)
-def unassign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, product_types):
+def unassign_cost_item_type(
+ ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance, product_types
+):
if not product_types:
product_types = spatial.get_selected_product_types()
[
@@ -133,7 +137,9 @@ def load_cost_item_types(cost: tool.Cost):
cost.load_cost_item_types(cost_item)
-def assign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type, prop_name):
+def assign_cost_item_quantity(
+ ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, 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)
@@ -159,7 +165,7 @@ def load_cost_item_resource_quantities(cost: tool.Cost):
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE")
-def assign_cost_value(ifc: tool.Ifc, cost_item, cost_rate):
+def assign_cost_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, cost_rate):
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
@@ -167,7 +173,7 @@ 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: tool.Ifc, cost: tool.Cost, cost_item, products):
+def unassign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, products):
ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products)
cost.load_cost_item_quantities()
@@ -180,11 +186,11 @@ def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.ent
cost.enable_editing_cost_item_values(cost_item)
-def add_cost_item_quantity(ifc: tool.Ifc, cost_item, ifc_class):
+def add_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, ifc_class):
ifc.run("cost.add_cost_item_quantity", cost_item=cost_item, ifc_class=ifc_class)
-def remove_cost_item_quantity(ifc: tool.Ifc, cost_item, physical_quantity):
+def remove_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, physical_quantity):
ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity)
@@ -288,7 +294,9 @@ def export_cost_schedules(cost: tool.Cost, filepath, format, cost_schedule=None)
return cost.export_cost_schedules(filepath, format, cost_schedule)
-def clear_cost_item_assignments(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type):
+def clear_cost_item_assignments(
+ ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, 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)
diff --git a/src/blenderbim/blenderbim/core/drawing.py b/src/blenderbim/blenderbim/core/drawing.py
index f52fc2e1c5..582a80551b 100644
--- a/src/blenderbim/blenderbim/core/drawing.py
+++ b/src/blenderbim/blenderbim/core/drawing.py
@@ -16,36 +16,44 @@
# 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 pathlib import Path
-import ifcopenshell
+from typing import TYPE_CHECKING, Optional
+
+if TYPE_CHECKING:
+ import bpy
+ import ifcopenshell
+ import blenderbim.tool as tool
-def enable_editing_text(drawing, obj=None):
+def enable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.enable_editing_text(obj)
drawing.import_text_attributes(obj)
-def disable_editing_text(drawing, obj=None):
+def disable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.disable_editing_text(obj)
-def edit_text(drawing, obj=None):
+def edit_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.synchronise_ifc_and_text_attributes(obj)
drawing.update_text_size_pset(obj)
drawing.update_text_value(obj)
drawing.disable_editing_text(obj)
-def enable_editing_assigned_product(drawing, obj=None):
+def enable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.enable_editing_assigned_product(obj)
drawing.import_assigned_product(obj)
-def disable_editing_assigned_product(drawing, obj=None):
+def disable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.disable_editing_assigned_product(obj)
-def edit_assigned_product(ifc, drawing, obj=None, product=None):
+def edit_assigned_product(
+ ifc: tool.Ifc, drawing: tool.Drawing, obj: bpy.types.Object, product: Optional[ifcopenshell.entity_instance] = None
+) -> None:
element = ifc.get_entity(obj)
existing_product = drawing.get_assigned_product(element)
if existing_product != product:
@@ -58,16 +66,16 @@ def edit_assigned_product(ifc, drawing, obj=None, product=None):
drawing.disable_editing_assigned_product(obj)
-def load_sheets(drawing):
+def load_sheets(drawing: tool.Drawing) -> None:
drawing.import_sheets()
drawing.enable_editing_sheets()
-def disable_editing_sheets(drawing):
+def disable_editing_sheets(drawing: tool.Drawing) -> None:
drawing.disable_editing_sheets()
-def add_sheet(ifc, drawing, titleblock: ifcopenshell.entity_instance):
+def add_sheet(ifc: tool.Ifc, drawing, titleblock: ifcopenshell.entity_instance) -> None:
sheet = ifc.run("document.add_information")
layout = ifc.run("document.add_reference", information=sheet)
titleblock_reference = ifc.run("document.add_reference", information=sheet)
@@ -93,7 +101,7 @@ def add_sheet(ifc, drawing, titleblock: ifcopenshell.entity_instance):
drawing.import_sheets()
-def regenerate_sheet(drawing, sheet=None):
+def regenerate_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
titleblock_uri = drawing.get_document_uri(sheet, "TITLEBLOCK")
drawing.create_svg_sheet(sheet, drawing.sanitise_filename(Path(titleblock_uri).stem))
try:
@@ -104,11 +112,11 @@ def regenerate_sheet(drawing, sheet=None):
drawing.delete_file(path_layout)
-def open_sheet(drawing, sheet=None):
+def open_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
drawing.open_layout_svg(drawing.get_document_uri(sheet, "LAYOUT"))
-def remove_sheet(ifc, drawing, sheet=None):
+def remove_sheet(ifc: tool.Ifc, drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
for reference in drawing.get_document_references(sheet):
if drawing.get_reference_description(reference) in ("LAYOUT", "SHEET", "REVISION", "RASTER"):
uri = ifc.resolve_uri(drawing.get_document_uri(reference))
@@ -118,7 +126,7 @@ def remove_sheet(ifc, drawing, sheet=None):
drawing.import_sheets()
-def rename_sheet(ifc, drawing, sheet: ifcopenshell.entity_instance, identification: str, name: str) -> None:
+def rename_sheet(ifc: tool.Ifc, drawing, sheet: ifcopenshell.entity_instance, identification: str, name: str) -> None:
if ifc.get_schema() == "IFC2X3":
attributes = {"DocumentId": identification, "Name": name}
else:
@@ -144,30 +152,32 @@ def rename_sheet(ifc, drawing, sheet: ifcopenshell.entity_instance, identificati
drawing.move_file(old_location, ifc.resolve_uri(new_location))
-def rename_reference(ifc, drawing, reference=None, identification=None):
+def rename_reference(
+ ifc: tool.Ifc, drawing: tool.Drawing, reference: ifcopenshell.entity_instance, identification: str
+) -> None:
attributes = drawing.generate_reference_attributes(reference, Identification=identification)
ifc.run("document.edit_reference", reference=reference, attributes=attributes)
-def load_schedules(drawing):
+def load_schedules(drawing: tool.Drawing) -> None:
drawing.import_documents("SCHEDULE")
drawing.enable_editing_schedules()
-def load_references(drawing):
+def load_references(drawing: tool.Drawing) -> None:
drawing.import_documents("REFERENCE")
drawing.enable_editing_references()
-def disable_editing_schedules(drawing):
+def disable_editing_schedules(drawing: tool.Drawing) -> None:
drawing.disable_editing_schedules()
-def disable_editing_references(drawing):
+def disable_editing_references(drawing: tool.Drawing) -> None:
drawing.disable_editing_references()
-def add_document(ifc, drawing, document_type, uri=None):
+def add_document(ifc: tool.Ifc, drawing: tool.Drawing, document_type: tool.Drawing.DOCUMENT_TYPE, uri: str) -> None:
document = ifc.run("document.add_information")
reference = ifc.run("document.add_reference", information=document)
name = drawing.get_path_filename(uri)
@@ -180,34 +190,43 @@ def add_document(ifc, drawing, document_type, uri=None):
drawing.import_documents(document_type)
-def remove_document(ifc, drawing, document_type, document=None):
+def remove_document(
+ ifc: tool.Ifc,
+ drawing: tool.Drawing,
+ document_type: tool.Drawing.DOCUMENT_TYPE,
+ document: ifcopenshell.entity_instance,
+) -> None:
ifc.run("document.remove_information", information=document)
drawing.import_documents(document_type)
-def open_schedule(drawing, schedule=None):
+def open_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
drawing.open_spreadsheet(drawing.get_document_uri(schedule))
-def open_reference(drawing, reference=None):
+def open_reference(drawing: tool.Drawing, reference: ifcopenshell.entity_instance) -> None:
drawing.open_svg(drawing.get_document_uri(reference))
-def update_document_name(ifc, drawing, document=None, name=None):
+def update_document_name(
+ ifc: tool.Ifc, drawing: tool.Drawing, document: ifcopenshell.entity_instance, name=None
+) -> None:
if drawing.get_name(document) != name:
ifc.run("document.edit_information", information=document, attributes={"Name": name})
-def load_drawings(drawing):
+def load_drawings(drawing: tool.Drawing) -> None:
drawing.import_drawings()
drawing.enable_editing_drawings()
-def disable_editing_drawings(drawing):
+def disable_editing_drawings(drawing: tool.Drawing) -> None:
drawing.disable_editing_drawings()
-def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
+def add_drawing(
+ ifc: tool.Ifc, collector: tool.Collector, drawing: tool.Drawing, target_view=None, location_hint=None
+) -> None:
drawing_name = drawing.ensure_unique_drawing_name(drawing.generate_drawing_name(target_view, location_hint))
drawing_matrix = drawing.generate_drawing_matrix(target_view, location_hint)
camera = drawing.create_camera(drawing_name, drawing_matrix, location_hint)
@@ -265,7 +284,12 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
drawing.import_drawings()
-def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotations=False):
+def duplicate_drawing(
+ ifc: tool.Ifc,
+ drawing_tool: tool.Drawing,
+ drawing: ifcopenshell.entity_instance,
+ should_duplicate_annotations: bool = False,
+) -> ifcopenshell.entity_instance:
drawing_name = drawing_tool.ensure_unique_drawing_name(drawing_tool.get_name(drawing))
new_drawing = ifc.run("root.copy_class", product=drawing)
drawing_tool.copy_representation(drawing, new_drawing)
@@ -302,7 +326,7 @@ def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotati
return new_drawing
-def remove_drawing(ifc, drawing_tool, drawing=None):
+def remove_drawing(ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance) -> None:
if drawing_tool.is_active_drawing(drawing):
drawing_tool.run_drawing_activate_model()
@@ -330,7 +354,9 @@ def remove_drawing(ifc, drawing_tool, drawing=None):
drawing_tool.import_drawings()
-def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
+def update_drawing_name(
+ ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance, name=None
+) -> None:
if drawing_tool.get_name(drawing) != name:
ifc.run("attribute.edit_attributes", product=drawing, attributes={"Name": name})
group = drawing_tool.get_drawing_group(drawing)
@@ -364,7 +390,13 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
drawing_tool.import_sheets()
-def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None):
+def add_annotation(
+ ifc: tool.Ifc,
+ collector: tool.Collector,
+ drawing_tool: tool.Drawing,
+ drawing: ifcopenshell.entity_instance,
+ object_type: str,
+) -> None:
target_view = drawing_tool.get_drawing_target_view(drawing)
context = drawing_tool.get_annotation_context(target_view, object_type)
if not context:
@@ -387,12 +419,14 @@ def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None)
drawing_tool.enable_editing(obj)
-def build_schedule(drawing, schedule=None):
+def build_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
drawing.create_svg_schedule(schedule)
drawing.open_svg(drawing.get_path_with_ext(drawing.get_document_uri(schedule), "svg"))
-def sync_references(ifc, collector, drawing_tool, drawing=None):
+def sync_references(
+ ifc: tool.Ifc, collector: tool.Collector, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
+) -> None:
if not drawing_tool.has_annotation(drawing):
return
@@ -437,11 +471,13 @@ def sync_references(ifc, collector, drawing_tool, drawing=None):
drawing_tool.sync_object_representation(reference_obj)
-def select_assigned_product(drawing, context):
+def select_assigned_product(drawing: tool.Drawing, context: bpy.types.Context) -> None:
drawing.select_assigned_product(context)
-def activate_drawing_view(ifc, blender, drawing_tool, drawing):
+def activate_drawing_view(
+ ifc: tool.Ifc, blender: tool.Blender, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
+) -> None:
camera = ifc.get_object(drawing)
if not camera:
camera = drawing_tool.import_drawing(drawing)
diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py
index d5055bf9bf..64fa9bf40f 100644
--- a/src/blenderbim/blenderbim/tool/blender.py
+++ b/src/blenderbim/blenderbim/tool/blender.py
@@ -468,7 +468,7 @@ class Blender(blenderbim.core.tool.Blender):
active_object.select_set(True)
@classmethod
- def enum_property_has_valid_index(cls, props, prop_name: str, enum_items: tuple) -> bool:
+ def enum_property_has_valid_index(cls, props: bpy.types.PropertyGroup, prop_name: str, enum_items: tuple) -> bool:
"""method created for readibility and to avoid console warnings like
`pyrna_enum_to_py: current value '17' matches no enum in 'BIMModelProperties', '', 'relating_type_id'`
"""
diff --git a/src/blenderbim/blenderbim/tool/cost.py b/src/blenderbim/blenderbim/tool/cost.py
index 01a392e727..2ce904b018 100644
--- a/src/blenderbim/blenderbim/tool/cost.py
+++ b/src/blenderbim/blenderbim/tool/cost.py
@@ -1,11 +1,13 @@
import os
import bpy
+import blenderbim.core.tool
import blenderbim.tool as tool
import ifcopenshell.util.date
import ifcopenshell.util.cost
import ifcopenshell.util.unit
import blenderbim.bim.helper
import json
+from typing import Optional
class Cost(blenderbim.core.tool.Cost):
@@ -163,7 +165,7 @@ class Cost(blenderbim.core.tool.Cost):
return
@classmethod
- def load_cost_item_types(cls, cost_item=None):
+ def load_cost_item_types(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
if not cost_item:
cost_item = cls.get_highlighted_cost_item()
if not cost_item:
diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py
index a223186670..d2a8f96aca 100644
--- a/src/blenderbim/blenderbim/tool/drawing.py
+++ b/src/blenderbim/blenderbim/tool/drawing.py
@@ -51,11 +51,14 @@ from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT
from lxml import etree
from mathutils import Vector, Matrix
from fractions import Fraction
-from typing import Optional, Union, Iterable, Any
+from typing import Optional, Union, Iterable, Any, Literal
from pathlib import Path
class Drawing(blenderbim.core.tool.Drawing):
+ ANNOTATION_DATA_TYPE = Literal["empty", "curve", "mesh"]
+ DOCUMENT_TYPE = Literal["SCHEDULE", "REFERENCE"]
+
@classmethod
def canonicalise_class_name(cls, name):
return re.sub("[^0-9a-zA-Z]+", "", name)
@@ -68,11 +71,11 @@ class Drawing(blenderbim.core.tool.Drawing):
)
@classmethod
- def get_annotation_data_type(cls, object_type):
+ def get_annotation_data_type(cls, object_type: str) -> ANNOTATION_DATA_TYPE:
return ANNOTATION_TYPES_DATA[object_type][3]
@classmethod
- def create_annotation_object(cls, drawing, object_type):
+ def create_annotation_object(cls, drawing: ifcopenshell.entity_instance, object_type: str) -> bpy.types.Object:
data_type = cls.get_annotation_data_type(object_type)
obj = annotation.Annotator.get_annotation_obj(drawing, object_type, data_type)
if object_type == "FILL_AREA":
@@ -298,15 +301,15 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.is_editing_sheets = False
@classmethod
- def disable_editing_text(cls, obj):
+ def disable_editing_text(cls, obj: bpy.types.Object) -> None:
obj.BIMTextProperties.is_editing = False
@classmethod
- def disable_editing_assigned_product(cls, obj):
+ def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
obj.BIMAssignedProductProperties.is_editing_product = False
@classmethod
- def enable_editing(cls, obj):
+ def enable_editing(cls, obj: bpy.types.Object) -> None:
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
@@ -330,11 +333,11 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.is_editing_sheets = True
@classmethod
- def enable_editing_text(cls, obj):
+ def enable_editing_text(cls, obj: bpy.types.Object) -> None:
obj.BIMTextProperties.is_editing = True
@classmethod
- def enable_editing_assigned_product(cls, obj):
+ def enable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
obj.BIMAssignedProductProperties.is_editing_product = True
@classmethod
@@ -428,7 +431,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return location
@classmethod
- def get_path_filename(cls, path):
+ def get_path_filename(cls, path: str) -> str:
return os.path.splitext(os.path.basename(path))[0]
@classmethod
@@ -483,7 +486,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return ""
@classmethod
- def get_name(cls, element):
+ def get_name(cls, element: ifcopenshell.entity_instance) -> Union[str, None]:
return element.Name
@classmethod
@@ -563,7 +566,7 @@ class Drawing(blenderbim.core.tool.Drawing):
ifcopenshell.util.element.remove_deep2(ifc_file, literal)
@classmethod
- def synchronise_ifc_and_text_attributes(cls, obj):
+ def synchronise_ifc_and_text_attributes(cls, obj: bpy.types.Object) -> None:
literals = cls.get_text_literal(obj, return_list=True)
literals_attributes = cls.export_text_literal_attributes(obj)
defined_ifc_ids = [l.ifc_definition_id for l in obj.BIMTextProperties.literals]
@@ -784,7 +787,7 @@ class Drawing(blenderbim.core.tool.Drawing):
new.ifc_definition_id = drawing.id() # Last, to prevent unnecessary prop callbacks
@classmethod
- def import_documents(cls, document_type):
+ def import_documents(cls, document_type: DOCUMENT_TYPE) -> None:
dprops = bpy.context.scene.DocProperties
if document_type == "SCHEDULE":
documents_collection = dprops.schedules
@@ -845,7 +848,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return next(s for s in props.sheets[: props.active_sheet_index + 1][::-1] if s.is_sheet)
@classmethod
- def import_text_attributes(cls, obj):
+ def import_text_attributes(cls, obj: bpy.types.Object) -> None:
props = obj.BIMTextProperties
props.literals.clear()
@@ -863,7 +866,7 @@ class Drawing(blenderbim.core.tool.Drawing):
props.font_size = str(text_data["FontSize"])
@classmethod
- def import_assigned_product(cls, obj):
+ def import_assigned_product(cls, obj: bpy.types.Object) -> None:
element = tool.Ifc.get_entity(obj)
product = cls.get_assigned_product(element)
if product:
@@ -934,7 +937,7 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.should_draw_decorations = True
@classmethod
- def update_text_value(cls, obj):
+ def update_text_value(cls, obj: bpy.types.Object) -> None:
props = obj.BIMTextProperties
literals = cls.get_text_literal(obj, return_list=True)
cls.import_text_attributes(obj)
@@ -943,7 +946,7 @@ class Drawing(blenderbim.core.tool.Drawing):
props.literals[i].value = cls.replace_text_literal_variables(literal.Literal, product)
@classmethod
- def update_text_size_pset(cls, obj):
+ def update_text_size_pset(cls, obj: bpy.types.Object) -> None:
"""updates pset `EPset_Annotation.Classes` value
based on current font size from `obj.BIMTextProperties.font_size`
"""
@@ -1522,7 +1525,7 @@ class Drawing(blenderbim.core.tool.Drawing):
tool.Geometry.record_object_position(obj)
@classmethod
- def get_document_references(cls, document):
+ def get_document_references(cls, document: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
if tool.Ifc.get_schema() == "IFC2X3":
return document.DocumentReferences or []
return document.HasDocumentReferences or []
@@ -1553,7 +1556,9 @@ class Drawing(blenderbim.core.tool.Drawing):
return reference.Description
@classmethod
- def generate_reference_attributes(cls, reference: ifcopenshell.entity_instance, **attributes: Any) -> dict[str, Any]:
+ def generate_reference_attributes(
+ cls, reference: ifcopenshell.entity_instance, **attributes: Any
+ ) -> dict[str, Any]:
"""will automatically convert attributes below for IFC2X3 compatibility:
- Identification -> ItemReference
@@ -1635,23 +1640,22 @@ class Drawing(blenderbim.core.tool.Drawing):
base_elements = set(ifc_file.by_type("IfcElement") + ifc_file.by_type("IfcSpatialElement"))
elements = {e for e in (elements & base_elements) if e.is_a() != "IfcSpace"}
-
updated_set = set()
for i in elements:
# exclude annotations to avoid including annotations from other drawings
- if not i.is_a("IfcAnnotation"):
+ if not i.is_a("IfcAnnotation"):
updated_set.add(i)
- #add aggregate too, if element is host by one
+ # add aggregate too, if element is host by one
if i.Decomposes:
aggregate = i.Decomposes[0].RelatingObject
- #remove IfcProject for class iterator. See https://github.com/IfcOpenShell/IfcOpenShell/issues/4361#issuecomment-2081223615
- if not aggregate.is_a("IfcProject"):
+ # remove IfcProject for class iterator. See https://github.com/IfcOpenShell/IfcOpenShell/issues/4361#issuecomment-2081223615
+ if not aggregate.is_a("IfcProject"):
updated_set.add(aggregate)
- # After the iteration is complete, update elements with updated set
+ # After the iteration is complete, update elements with updated set
elements.update(updated_set)
-
+
# add annotations from the current drawing
annotations = tool.Drawing.get_group_elements(tool.Drawing.get_drawing_group(drawing))
elements.update(annotations)
@@ -1694,7 +1698,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return reference.ReferencedDocument
@classmethod
- def select_assigned_product(cls, context):
+ def select_assigned_product(cls, context: bpy.types.Context) -> None:
obj = context.active_object
element = tool.Ifc.get_entity(obj)
product = cls.get_assigned_product(element)
@@ -1713,7 +1717,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return True if (camera and camera.data.type == "ORTHO") else False
@classmethod
- def is_active_drawing(cls, drawing):
+ def is_active_drawing(cls, drawing: ifcopenshell.entity_instance) -> bool:
return drawing.id() == bpy.context.scene.DocProperties.active_drawing_id
@classmethod
diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py
index 2d81ba415a..8031433e21 100644
--- a/src/blenderbim/blenderbim/tool/geometry.py
+++ b/src/blenderbim/blenderbim/tool/geometry.py
@@ -90,7 +90,7 @@ class Geometry(blenderbim.core.tool.Geometry):
bpy.data.meshes.remove(data)
@classmethod
- def delete_ifc_object(cls, obj):
+ def delete_ifc_object(cls, obj: bpy.types.Object) -> None:
element = tool.Ifc.get_entity(obj)
if not element:
return
diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py
index 4025d37d39..d0c63912d4 100644
--- a/src/blenderbim/blenderbim/tool/model.py
+++ b/src/blenderbim/blenderbim/tool/model.py
@@ -23,6 +23,7 @@ import collections
import collections.abc
import numpy as np
import ifcopenshell
+import ifcopenshell.util.element
import ifcopenshell.util.unit
import ifcopenshell.util.placement
import ifcopenshell.util.representation
@@ -468,7 +469,7 @@ class Model(blenderbim.core.tool.Model):
has_deleted_opening = True
@classmethod
- def get_material_layer_parameters(cls, element):
+ def get_material_layer_parameters(cls, element: ifcopenshell.entity_instance) -> dict[str, Any]:
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
layer_set_direction = "AXIS2"
offset = 0.0
diff --git a/src/blenderbim/blenderbim/tool/spatial.py b/src/blenderbim/blenderbim/tool/spatial.py
index 68c1d8c0e8..101d17e454 100644
--- a/src/blenderbim/blenderbim/tool/spatial.py
+++ b/src/blenderbim/blenderbim/tool/spatial.py
@@ -31,6 +31,7 @@ import json
from math import pi
from mathutils import Vector, Matrix
from shapely import Polygon, MultiPolygon
+from typing import Generator
class Spatial(blenderbim.core.tool.Spatial):
@@ -187,14 +188,14 @@ class Spatial(blenderbim.core.tool.Spatial):
]
@classmethod
- def get_selected_products(cls):
+ def get_selected_products(cls) -> Generator[ifcopenshell.entity_instance, None, None]:
for obj in bpy.context.selected_objects:
entity = tool.Ifc.get_entity(obj)
if entity and entity.is_a("IfcProduct"):
yield entity
@classmethod
- def get_selected_product_types(cls):
+ def get_selected_product_types(cls) -> Generator[ifcopenshell.entity_instance, None, None]:
for obj in bpy.context.selected_objects:
entity = tool.Ifc.get_entity(obj)
if entity and entity.is_a("IfcTypeProduct"):
diff --git a/src/ifcopenshell-python/ifcopenshell/util/cost.py b/src/ifcopenshell-python/ifcopenshell/util/cost.py
index 4d15ee8f33..44852b6e9c 100644
--- a/src/ifcopenshell-python/ifcopenshell/util/cost.py
+++ b/src/ifcopenshell-python/ifcopenshell/util/cost.py
@@ -17,13 +17,15 @@
# along with IfcOpenShell. If not, see .
import lark
+import ifcopenshell
+from typing import Optional, Union
arithmetic_operator_symbols = {"ADD": "+", "DIVIDE": "/", "MULTIPLY": "*", "SUBTRACT": "-"}
symbol_arithmetic_operators = {"+": "ADD", "/": "DIVIDE", "*": "MULTIPLY", "-": "SUBTRACT"}
-def get_primitive_applied_value(applied_value):
+def get_primitive_applied_value(applied_value: Union[ifcopenshell.entity_instance, float, None]) -> float:
if not applied_value:
return 0.0
elif isinstance(applied_value, float):
@@ -32,17 +34,21 @@ def get_primitive_applied_value(applied_value):
return applied_value.wrappedValue
elif applied_value.is_a("IfcMeasureWithUnit"):
return applied_value.ValueComponent
- assert False, "Applied value {applied_value} not implemented"
+ assert False, f"Applied value {applied_value} not implemented"
-def get_total_quantity(root_element):
+def get_total_quantity(root_element: ifcopenshell.entity_instance) -> Union[float, None]:
+ # 3 IfcPhysicalQuantity Value
if root_element.is_a("IfcCostItem"):
return sum([q[3] for q in root_element.CostQuantities or []]) or None
elif root_element.is_a("IfcConstructionResource"):
- return root_element.BaseQuantity[3] if root_element.BaseQuantity else 1.0
+ quantity = root_element.BaseQuantity
+ return quantity[3] if quantity else 1.0
-def calculate_applied_value(root_element, cost_value, category_filter=None):
+def calculate_applied_value(
+ root_element: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance, category_filter=None
+) -> float:
if cost_value.ArithmeticOperator and cost_value.Components:
component_values = []
for component in cost_value.Components:
@@ -75,11 +81,11 @@ def calculate_applied_value(root_element, cost_value, category_filter=None):
return sum_child_root_elements(root_element, category_filter=cost_value.Category)
else:
return get_primitive_applied_value(cost_value.AppliedValue)
- return 0
+ return 0.0
-def sum_child_root_elements(root_element, category_filter=None):
- result = 0
+def sum_child_root_elements(root_element: ifcopenshell.entity_instance, category_filter: Optional[str] = None) -> float:
+ result = 0.0
for rel in root_element.IsNestedBy:
for child_root_element in rel.RelatedObjects:
if root_element.is_a("IfcCostItem"):
@@ -99,14 +105,14 @@ def sum_child_root_elements(root_element, category_filter=None):
return result
-def serialise_cost_value(cost_value):
+def serialise_cost_value(cost_value: ifcopenshell.entity_instance) -> str:
result = _serialise_cost_value(cost_value)
if result and result[0] == "(" and result[-1] == ")":
return result[1:-1]
return result
-def _serialise_cost_value(cost_value):
+def _serialise_cost_value(cost_value: ifcopenshell.entity_instance) -> str:
value = ""
if cost_value.ArithmeticOperator and cost_value.Components:
operator = arithmetic_operator_symbols[cost_value.ArithmeticOperator]
@@ -133,7 +139,7 @@ def _serialise_cost_value(cost_value):
return value
-def serialise_applied_value(applied_value):
+def serialise_applied_value(applied_value: ifcopenshell.entity_instance) -> str:
if applied_value.is_a("IfcMonetaryMeasure"):
return str(applied_value.wrappedValue)
return "?"