From 30551cb288b532e52bb927ca86274580eccd5fe0 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 18 Mar 2026 19:34:56 +0500 Subject: [PATCH] typing --- src/bcf/bcf/v3/bcfapi.py | 6 +-- .../bonsai/bim/module/drawing/gizmos.py | 2 +- .../bonsai/bim/module/georeference/prop.py | 8 ++- src/bonsai/bonsai/bim/module/model/profile.py | 54 +++++++++++++------ .../module/structural/load_decoration_data.py | 3 +- src/bonsai/bonsai/tool/bsdd.py | 6 ++- .../ifcopenshell/__init__.py | 6 ++- 7 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/bcf/bcf/v3/bcfapi.py b/src/bcf/bcf/v3/bcfapi.py index 3ac85b9685..368c294cd0 100644 --- a/src/bcf/bcf/v3/bcfapi.py +++ b/src/bcf/bcf/v3/bcfapi.py @@ -34,8 +34,8 @@ client_id, client_secret = "", "" class OAuthReceiver(http.server.BaseHTTPRequestHandler): def do_GET(self) -> None: query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) - self.server.auth_code = query.get("code", [""])[0] # type: ignore - self.server.auth_state = query.get("state", [""])[0] # type: ignore + self.server.auth_code = query.get("code", [""])[0] + self.server.auth_state = query.get("state", [""])[0] self.send_response(200) self.send_header("Content-type", "text/plain") self.end_headers() @@ -255,7 +255,7 @@ class BcfClient: project_id: str = "", topics: str = "", query_string: Optional[str] = None, - ) -> list[Any]: + ) -> None: # return self.get( # f"/projects/{project_id}/topics", # { diff --git a/src/bonsai/bonsai/bim/module/drawing/gizmos.py b/src/bonsai/bonsai/bim/module/drawing/gizmos.py index 7f3a53ddf4..d350cf80ee 100644 --- a/src/bonsai/bonsai/bim/module/drawing/gizmos.py +++ b/src/bonsai/bonsai/bim/module/drawing/gizmos.py @@ -1285,7 +1285,7 @@ class SnapManager: continue coords = np.empty(vertex_count * 3, dtype=np.float32) - mesh.vertices.foreach_get("co", coords) # type: ignore[arg-type] + mesh.vertices.foreach_get("co", coords) coords = coords.reshape(-1, 3) matrix = np.array(obj_eval.matrix_world, dtype=np.float32) diff --git a/src/bonsai/bonsai/bim/module/georeference/prop.py b/src/bonsai/bonsai/bim/module/georeference/prop.py index da92edf4e6..9b1f8d5f4d 100644 --- a/src/bonsai/bonsai/bim/module/georeference/prop.py +++ b/src/bonsai/bonsai/bim/module/georeference/prop.py @@ -139,7 +139,9 @@ def update_local_coordinates(self: "BIMGeoreferenceProperties", context: bpy.typ tool.Georeference.set_coordinates( "blender", ifcopenshell.util.geolocation.enh2xyz( - *local_coordinates, + local_coordinates[0], + local_coordinates[1], + local_coordinates[2], float(props.blender_offset_x), float(props.blender_offset_y), float(props.blender_offset_z), @@ -162,7 +164,9 @@ def update_map_coordinates(self: "BIMGeoreferenceProperties", context: bpy.types tool.Georeference.set_coordinates( "blender", ifcopenshell.util.geolocation.enh2xyz( - *local_coordinates, + local_coordinates[0], + local_coordinates[1], + local_coordinates[2], float(props.blender_offset_x), float(props.blender_offset_y), float(props.blender_offset_z), diff --git a/src/bonsai/bonsai/bim/module/model/profile.py b/src/bonsai/bonsai/bim/module/model/profile.py index f759d40a94..63c3f8dfa4 100644 --- a/src/bonsai/bonsai/bim/module/model/profile.py +++ b/src/bonsai/bonsai/bim/module/model/profile.py @@ -18,7 +18,7 @@ import copy from math import atan2, degrees, pi, radians -from typing import Any, Literal, Optional, Union +from typing import TYPE_CHECKING, Any, Literal, Optional, Union import bpy import ifcopenshell @@ -49,7 +49,7 @@ ProfileFrom2PointsReturn = Union[dict[str, Any], None] class DumbProfileGenerator: - def __init__(self, relating_type): + def __init__(self, relating_type: ifcopenshell.entity_instance): self.relating_type = relating_type self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) @@ -201,7 +201,7 @@ class DumbProfileGenerator: class DumbProfileRegenerator: - def regenerate_from_profile_def(self, profile): + def regenerate_from_profile_def(self, profile: ifcopenshell.entity_instance) -> None: self.file = tool.Ifc.get() objs = [] if not profile: @@ -221,7 +221,7 @@ class DumbProfileRegenerator: for element in self.get_element_types_using_profile(profile): tool.Model.mark_thumbnail_for_update(element) - def regenerate_from_profile(self, usecase_path, ifc_file, settings): + def regenerate_from_profile(self, usecase_path: str, ifc_file: ifcopenshell.file, settings: dict[str, Any]) -> None: self.file = ifc_file objs = [] profile = settings["profile"].Profile @@ -233,7 +233,7 @@ class DumbProfileRegenerator: objs.append(obj) DumbProfileRecalculator().recalculate(objs) - def get_elements_using_profile(self, profile): + def get_elements_using_profile(self, profile: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: results = [] profile_sets = [ mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile") @@ -252,7 +252,7 @@ class DumbProfileRegenerator: results.extend(rel.RelatedObjects) return results - def get_element_types_using_profile(self, profile): + def get_element_types_using_profile(self, profile: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: results = [] profile_sets = [ mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile") @@ -269,12 +269,18 @@ class ExtendProfile(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.extend_profile" bl_label = "Extend Profile" bl_options = {"REGISTER", "UNDO"} - join_type: bpy.props.StringProperty() + join_type: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration] + items=[("-", "Unjoin", ""), ("L", "L", ""), ("V", "V", ""), ("T", "T", "")], + default="-", + ) + + if TYPE_CHECKING: + join_type: Literal["-", "L", "V", "T"] def _execute(self, context): selected_objs = context.selected_objects joiner = DumbProfileJoiner() - if not self.join_type: + if self.join_type == "-": for obj in selected_objs: joiner.unjoin(obj) return {"FINISHED"} @@ -626,11 +632,15 @@ class DumbProfileJoiner: if connection1 == "ATEND": if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: plane = self.get_profile_plane(profile2, furthest_plane) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) self.body[1] = intersect else: plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) max_dim = self.get_max_bound_box_dimension(profile1) self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) @@ -673,11 +683,15 @@ class DumbProfileJoiner: elif connection1 == "ATSTART": if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: plane = self.get_profile_plane(profile2, furthest_plane) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) self.body[0] = intersect else: plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) max_dim = self.get_max_bound_box_dimension(profile1) self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) @@ -721,7 +735,9 @@ class DumbProfileJoiner: if connection1 == "ATEND": if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) self.body[1] = intersect else: plane = self.get_profile_plane( @@ -729,7 +745,9 @@ class DumbProfileJoiner: furthest_plane if is_relating else closest_plane, z_inwards=False if is_relating else True, ) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) max_dim = self.get_max_bound_box_dimension(profile1) self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.clippings.append( @@ -742,7 +760,9 @@ class DumbProfileJoiner: elif connection1 == "ATSTART": if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal: plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) self.body[0] = intersect else: plane = self.get_profile_plane( @@ -750,7 +770,9 @@ class DumbProfileJoiner: furthest_plane if is_relating else closest_plane, z_inwards=False if is_relating else True, ) - intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.translation, plane.col[2].to_3d()) + intersect = mathutils.geometry.intersect_line_plane( + axis1[0], axis1[1], plane.translation, plane.col[2].to_3d() + ) max_dim = self.get_max_bound_box_dimension(profile1) self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim)) self.clippings.append( diff --git a/src/bonsai/bonsai/bim/module/structural/load_decoration_data.py b/src/bonsai/bonsai/bim/module/structural/load_decoration_data.py index 132c305ad1..dc05fab89c 100644 --- a/src/bonsai/bonsai/bim/module/structural/load_decoration_data.py +++ b/src/bonsai/bonsai/bim/module/structural/load_decoration_data.py @@ -28,6 +28,7 @@ import ifcopenshell.util.representation import ifcopenshell.util.unit import ifcopenshell.util.unit as ifcunit import numpy as np +import numpy.typing as npt from mathutils import Vector import bonsai.tool as tool @@ -478,7 +479,7 @@ class ShaderInfo: """get the args to the point shader""" location = np.array(location) indices = [] - direction_dict = { + direction_dict: dict[str, tuple[npt.NDArray, ...]] = { "fx": (np.array((1, 0, 0)), np.array((0, 1, 0)), np.array((0, 0, 1))), "fy": (np.array((0, 1, 0)), np.array((1, 0, 0)), np.array((0, 0, 1))), "fz": (np.array((0, 0, 1)), np.array((0, 1, 0)), np.array((1, 0, 0))), diff --git a/src/bonsai/bonsai/tool/bsdd.py b/src/bonsai/bonsai/tool/bsdd.py index 74d9926f15..2d9c5605bf 100644 --- a/src/bonsai/bonsai/tool/bsdd.py +++ b/src/bonsai/bonsai/tool/bsdd.py @@ -32,6 +32,8 @@ import bonsai.core.tool import bonsai.tool as tool if TYPE_CHECKING: + from bsdd.bsdd import ClassContractV1, ClassPropertyContractV1, PropertyContractV5 + from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary @@ -39,8 +41,8 @@ class Bsdd(bonsai.core.tool.Bsdd): default_identifier_url = "https://identifier.buildingsmart.org" default_api_url = "https://api.bsdd.buildingsmart.org/api/" client = bsdd.Client() - bsdd_classes: dict[str, dict] = {} - bsdd_properties: dict[str, dict] = {} + bsdd_classes: dict[str, ClassContractV1] = {} + bsdd_properties: dict[str, ClassPropertyContractV1 | PropertyContractV5] = {} @classmethod def identifier_url(cls) -> str: diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index 998eb6e5de..28a3512e2e 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -199,11 +199,13 @@ def open( for ty in bypass_types: f.bypass_type(ty) if mmap: - f.initialize(str(path.absolute()), mmap=mmap) + # mmap parameter is only available for builds with USE_MMAP, not used in our main builds + f.initialize(str(path.absolute()), mmap=mmap) # type: ignore[unknown-argument] else: f.initialize(str(path.absolute())) elif mmap: - f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap) + # mmap parameter is only available for builds with USE_MMAP, not used in our main builds + f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap) # type: ignore[unknown-argument] else: f = ifcopenshell_wrapper.open(str(path.absolute())) return file(f)