diff --git a/src/bonsai/bonsai/bim/module/drawing/gizmos.py b/src/bonsai/bonsai/bim/module/drawing/gizmos.py index 99db87d08d..53a4c8328e 100644 --- a/src/bonsai/bonsai/bim/module/drawing/gizmos.py +++ b/src/bonsai/bonsai/bim/module/drawing/gizmos.py @@ -82,7 +82,15 @@ import math from collections.abc import Callable, Iterator from dataclasses import dataclass from enum import Enum -from typing import Any, ClassVar, Literal, Optional, Protocol, runtime_checkable +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Literal, + Optional, + Protocol, + runtime_checkable, +) import blf import bpy @@ -105,6 +113,9 @@ from mathutils.kdtree import KDTree import bonsai.tool as tool from bonsai.bim.module.drawing.shaders import ExtrusionGuidesShader +if TYPE_CHECKING: + import bmesh + SNAP_POINT_SIZE = 10.0 SNAP_POINT_COLOR = (1.0, 0.5, 0.0, 1.0) SNAP_MAX_RADIUS = 50.0 @@ -2035,7 +2046,9 @@ class TexturedQuadGizmoMixin(StaticTrisGizmoMixin): def setup(self) -> None: super().setup() - from bonsai.bim.module.drawing import gizmo_textures + from bonsai.bim.module.drawing import ( + gizmo_textures, # ty: ignore[unresolved-import] + ) self._quad_batch = batch_for_shader( gizmo_textures.get_shader(), @@ -2044,7 +2057,9 @@ class TexturedQuadGizmoMixin(StaticTrisGizmoMixin): ) def draw(self, context: bpy.types.Context) -> None: - from bonsai.bim.module.drawing import gizmo_textures + from bonsai.bim.module.drawing import ( + gizmo_textures, # ty: ignore[unresolved-import] + ) texture = gizmo_textures.get_icon_texture(self.icon_name) if texture is None: diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 6cdb8bb80f..2bcc620424 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -981,7 +981,9 @@ class CreateDrawing(bpy.types.Operator): # Specifically for PLAN_VIEW and REFLECTED_PLAN_VIEW, any Plan context is also prioritised. contexts = self.get_linework_contexts(ifc, target_view) self.serialize_contexts_elements(ifc, tree, contexts, "body", drawing_elements, target_view, link_matrix) - self.serialize_contexts_elements(ifc, tree, contexts, "annotation", drawing_elements, target_view, link_matrix) + self.serialize_contexts_elements( + ifc, tree, contexts, "annotation", drawing_elements, target_view, link_matrix + ) if tool.Ifc.get() == ifc and self.camera_element not in drawing_elements: with profile("Camera element"): diff --git a/src/bonsai/bonsai/bim/module/model/__init__.py b/src/bonsai/bonsai/bim/module/model/__init__.py index 3bfb1accea..d59cd6d260 100644 --- a/src/bonsai/bonsai/bim/module/model/__init__.py +++ b/src/bonsai/bonsai/bim/module/model/__init__.py @@ -27,6 +27,7 @@ import bonsai.tool as tool from . import ( array, covering, + decorator, door, external, grid, diff --git a/src/bonsai/bonsai/bim/module/model/mep.py b/src/bonsai/bonsai/bim/module/model/mep.py index 723ac75e46..2a906d4ec4 100644 --- a/src/bonsai/bonsai/bim/module/model/mep.py +++ b/src/bonsai/bonsai/bim/module/model/mep.py @@ -38,6 +38,7 @@ import numpy as np from ifcopenshell.util.shape_builder import ShapeBuilder from mathutils import Matrix, Vector +import bonsai.core.geometry import bonsai.core.root import bonsai.tool as tool from bonsai.bim.module.drawing import gizmos as gizmo diff --git a/src/bonsai/bonsai/bim/module/model/railing.py b/src/bonsai/bonsai/bim/module/model/railing.py index 825cc339ac..353ade10d2 100644 --- a/src/bonsai/bonsai/bim/module/model/railing.py +++ b/src/bonsai/bonsai/bim/module/model/railing.py @@ -138,7 +138,7 @@ def update_bbim_railing_pset(element: ifcopenshell.entity_instance, railing_data def generate_wall_mounted_handrail_preview( obj: bpy.types.Object, - props: "BIMRailingProperties", + props: "prop.BIMRailingProperties", path_data: dict[str, Any], si_conversion: float, ) -> None: @@ -860,7 +860,9 @@ class GizmoRailingSchematic(bpy.types.GizmoGroup, gizmo.BaseSchematicGizmoGroup) terminal_world = anchor + billboard_rot @ view_rotation @ terminal_local self.terminal_gizmo.matrix_basis = gizmo.billboarded_at(terminal_world, billboard_rot, 0.18) - def update_editing_gizmos(self, context: bpy.types.Context, mw: "Matrix", props: "BIMRailingProperties") -> None: + def update_editing_gizmos( + self, context: bpy.types.Context, mw: "Matrix", props: "prop.BIMRailingProperties" + ) -> None: """Hide the pen gizmo while polyline path-edit is active; reposition the cycle icon. The base class shows the pen gizmo whenever ``is_editing`` is False, diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index 55ccff20a8..ed37fcb3b7 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -302,23 +302,25 @@ def add_drawing( context=drawing.get_body_context(), ifc_representation_class=None, ) - + drawings_parent_group = None for group in ifc.get().by_type("IfcGroup"): if group.Name == "DRAWINGS" and group.ObjectType == "DRAWINGS": drawings_parent_group = group break - + if not drawings_parent_group: drawings_parent_group = ifc.run("group.add_group") - ifc.run("group.edit_group", group=drawings_parent_group, attributes={"Name": "DRAWINGS", "ObjectType": "DRAWINGS"}) - + ifc.run( + "group.edit_group", group=drawings_parent_group, attributes={"Name": "DRAWINGS", "ObjectType": "DRAWINGS"} + ) + group = ifc.run("group.add_group") ifc.run("group.edit_group", group=group, attributes={"Name": drawing_name, "ObjectType": "DRAWING"}) ifc.run("group.assign_group", group=group, products=[element]) - + ifc.run("group.assign_group", group=drawings_parent_group, products=[group]) - + collector.assign(camera) pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing") if drawing.get_unit_system() == "METRIC": @@ -355,7 +357,7 @@ def add_drawing( if document.Name == "DRAWINGS" and document.Scope == "DRAWINGS": drawings_parent_document = document break - + if not drawings_parent_document: drawings_parent_document = ifc.run("document.add_information") if ifc.get_schema() == "IFC2X3": @@ -363,7 +365,7 @@ def add_drawing( else: attributes = {"Identification": "DRAWINGS", "Name": "DRAWINGS", "Scope": "DRAWINGS"} ifc.run("document.edit_information", information=drawings_parent_document, attributes=attributes) - + information = ifc.run("document.add_information", parent=drawings_parent_document) uri = drawing.get_default_drawing_path(drawing_name) reference = ifc.run("document.add_reference", information=information) @@ -392,17 +394,19 @@ def duplicate_drawing( drawing_tool.set_name(new_drawing, drawing_name) group = drawing_tool.get_drawing_group(new_drawing) ifc.run("group.unassign_group", group=group, products=[new_drawing]) - + drawings_parent_group = None for parent_group in ifc.get().by_type("IfcGroup"): if parent_group.Name == "DRAWINGS" and parent_group.ObjectType == "DRAWINGS": drawings_parent_group = parent_group break - + if not drawings_parent_group: drawings_parent_group = ifc.run("group.add_group") - ifc.run("group.edit_group", group=drawings_parent_group, attributes={"Name": "DRAWINGS", "ObjectType": "DRAWINGS"}) - + ifc.run( + "group.edit_group", group=drawings_parent_group, attributes={"Name": "DRAWINGS", "ObjectType": "DRAWINGS"} + ) + new_group = ifc.run("group.add_group") ifc.run("group.edit_group", group=new_group, attributes={"Name": drawing_name, "ObjectType": "DRAWING"}) ifc.run("group.assign_group", group=new_group, products=[new_drawing]) @@ -427,7 +431,7 @@ def duplicate_drawing( if document.Name == "DRAWINGS" and document.Scope == "DRAWINGS": drawings_parent_document = document break - + if not drawings_parent_document: drawings_parent_document = ifc.run("document.add_information") if ifc.get_schema() == "IFC2X3": diff --git a/src/bonsai/bonsai/core/product.py b/src/bonsai/bonsai/core/product.py index 4eaddc833d..ae6d5e8a21 100644 --- a/src/bonsai/bonsai/core/product.py +++ b/src/bonsai/bonsai/core/product.py @@ -50,14 +50,15 @@ def copy_z_rotation_to_selected( flip: bool = False, ) -> int: """Apply ``active``'s Z-Euler rotation to each target.""" - source_z = surveyor.get_z_rotation(active) + source_z = surveyor.get_z_rotation(active) # ty: ignore[missing-argument] if flip: source_z += math.pi rotated = 0 for obj in targets: - if abs(_z_rotation_diff(surveyor.get_z_rotation(obj), source_z)) < Z_ROTATION_ALIGNMENT_TOLERANCE: + target_z = surveyor.get_z_rotation(obj) # ty: ignore[missing-argument] + if abs(_z_rotation_diff(target_z, source_z)) < Z_ROTATION_ALIGNMENT_TOLERANCE: continue - surveyor.set_z_rotation(obj, source_z) + surveyor.set_z_rotation(obj, source_z) # ty: ignore[missing-argument] rotated += 1 if ifc.get_entity(obj) is not None: bonsai.core.geometry.edit_object_placement(ifc, geometry, surveyor, obj=obj) diff --git a/src/bonsai/bonsai/core/tool.py b/src/bonsai/bonsai/core/tool.py index 3aa8d7408f..7056e5ec34 100644 --- a/src/bonsai/bonsai/core/tool.py +++ b/src/bonsai/bonsai/core/tool.py @@ -804,7 +804,7 @@ class Profile: @interface class Parametric: - def get_geom_generation(cls) -> int: pass + def get_geom_generation(cls): pass def refresh_post_commit(cls, operator) -> None: pass diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index ecfc23e0f6..f54633c3cc 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -59,6 +59,7 @@ from ifcopenshell.util.shape_builder import ShapeBuilder, np_to_3d from mathutils import Matrix, Vector import bonsai.core.geometry +import bonsai.core.model import bonsai.core.tool import bonsai.tool as tool from bonsai.bim import import_ifc diff --git a/src/bonsai/test/bim/module/model/test_array_batch_recut.py b/src/bonsai/test/bim/module/model/test_array_batch_recut.py index d4b1ff2bf6..fc257884f8 100644 --- a/src/bonsai/test/bim/module/model/test_array_batch_recut.py +++ b/src/bonsai/test/bim/module/model/test_array_batch_recut.py @@ -35,6 +35,7 @@ from unittest.mock import Mock, patch import bpy import ifcopenshell +import ifcopenshell.api.pset import pytest import bonsai.tool as tool diff --git a/src/bonsai/test/bim/module/model/test_array_duplicate_batched.py b/src/bonsai/test/bim/module/model/test_array_duplicate_batched.py index d8dc931336..3cf23dbd24 100644 --- a/src/bonsai/test/bim/module/model/test_array_duplicate_batched.py +++ b/src/bonsai/test/bim/module/model/test_array_duplicate_batched.py @@ -37,6 +37,8 @@ from unittest.mock import patch import bpy import ifcopenshell +import ifcopenshell.api.pset +import ifcopenshell.util.element import pytest import bonsai.tool as tool diff --git a/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py b/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py index 55d325d76c..327e71e34a 100644 --- a/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py +++ b/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py @@ -146,7 +146,9 @@ def test_fit_flow_segments_with_single_segment_dispatches_obstruction(): mep.tool.Model, "get_flow_segment_profile", return_value=segment_profile ), patch.object(mep.MEPAddObstruction, "_execute", return_value=None) as obstruction, patch.object( mep.MEPAddBend, "_execute", return_value=None - ) as bend, patch.object(mep.MEPAddTransition, "_execute", return_value=None) as transition: + ) as bend, patch.object( + mep.MEPAddTransition, "_execute", return_value=None + ) as transition: mep.FitFlowSegments._execute(op, context=context) assert obstruction.call_count == 1 @@ -178,7 +180,9 @@ def test_fit_flow_segments_refuses_mixed_pipe_and_duct(): mep.tool.Model, "get_flow_segment_profile", return_value=profile ), patch.object(mep.MEPAddObstruction, "_execute", return_value=None) as obstruction, patch.object( mep.MEPAddBend, "_execute", return_value=None - ) as bend, patch.object(mep.MEPAddTransition, "_execute", return_value=None) as transition: + ) as bend, patch.object( + mep.MEPAddTransition, "_execute", return_value=None + ) as transition: mep.FitFlowSegments._execute(op, context=context) obstruction.assert_not_called() diff --git a/src/bonsai/test/bim/module/model/test_mep_segment_edition.py b/src/bonsai/test/bim/module/model/test_mep_segment_edition.py index 2451ceb7e2..ecadf11d45 100644 --- a/src/bonsai/test/bim/module/model/test_mep_segment_edition.py +++ b/src/bonsai/test/bim/module/model/test_mep_segment_edition.py @@ -173,8 +173,9 @@ def test_gizmo_group_class_wiring(gizmo_cls_name, bl_idname, is_element_predicat predicate = getattr(tool.Parametric, is_element_predicate) fake_element = Mock() fake_element.is_a.return_value = True - with patch.object(tool.Parametric, is_element_predicate, side_effect=predicate) as p, patch.object( - tool.System, "has_parametric_body", return_value=True + with ( + patch.object(tool.Parametric, is_element_predicate, side_effect=predicate) as p, + patch.object(tool.System, "has_parametric_body", return_value=True), ): cls.is_element_type(fake_element) assert p.called, f"{gizmo_cls_name}.is_element_type did not delegate to Parametric.{is_element_predicate}" diff --git a/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py b/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py index d67f258eaa..5a4b4f244e 100644 --- a/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py +++ b/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py @@ -139,6 +139,5 @@ def test_every_cancel_ops_entry_has_a_real_preview_propertygroup() -> None: orphaned = [attr for attr, _op in preview_base.PREVIEW_CANCEL_OPS if attr not in declared_attrs] assert not orphaned, ( "PREVIEW_CANCEL_OPS contains entries whose PointerProperty child no longer " - f"exists on {UMBRELLA_CLASS}. Drop the stale tuple(s):\n " - + "\n ".join(orphaned) + f"exists on {UMBRELLA_CLASS}. Drop the stale tuple(s):\n " + "\n ".join(orphaned) ) diff --git a/src/bonsai/test/modal/test_modal.py b/src/bonsai/test/modal/test_modal.py index 1ea6b1dbd5..1dd7055033 100644 --- a/src/bonsai/test/modal/test_modal.py +++ b/src/bonsai/test/modal/test_modal.py @@ -24,6 +24,7 @@ import time import bpy import ifcopenshell +import ifcopenshell.util.element import pytest from bonsai import tool as tool diff --git a/src/bonsai/test/tool/test_model.py b/src/bonsai/test/tool/test_model.py index e1b4601663..34ea117da0 100644 --- a/src/bonsai/test/tool/test_model.py +++ b/src/bonsai/test/tool/test_model.py @@ -23,6 +23,7 @@ import bpy import ifcopenshell import ifcopenshell.api.geometry import ifcopenshell.api.material +import ifcopenshell.api.pset import ifcopenshell.api.root import ifcopenshell.api.style import ifcopenshell.api.type diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 9f39547d43..fcfc0d119c 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -57,7 +57,8 @@ class CsvHeader(TypedDict): # Formula Formula: NotRequired[str] - #QuantityClass: NotRequired[str] + # QuantityClass: NotRequired[str] + # Currently we assume that if column is not part of the main header, # then it is a cost value category. So here we list any additional column @@ -97,7 +98,8 @@ class CostItem(TypedDict): Query: Union[str, None] Formula: Union[str, None] - #QuantityClass: Union[str, None] + # QuantityClass: Union[str, None] + class Csv2Ifc: # Inputs. @@ -420,7 +422,7 @@ class Csv2Ifc: products=results, formula=cost_item["Formula"], ifc_class=ifc_quantity_class, - ) + ) self.create_cost_items(cost_item["children"], cost_item["ifc"]) diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index 85b310b9ce..12c6cd6b84 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -231,7 +231,7 @@ def open( kwargs = {"mmap": mmap} if logger is not None: kwargs["logger"] = logger - f = ifcopenshell_wrapper.open(str(path.absolute()), **kwargs) # ty: ignore[unknown-argument] + f = ifcopenshell_wrapper.open(str(path.absolute()), **kwargs) else: f = ifcopenshell_wrapper.open(str(path.absolute()), False, *((logger,) if logger is not None else ())) return file(f) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_curve.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_curve.py index 3f71ddbbdd..74129e6fce 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_curve.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_curve.py @@ -22,8 +22,6 @@ import numpy as np import ifcopenshell import ifcopenshell.api.alignment import ifcopenshell.geom -import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper -import ifcopenshell.util.unit from ifcopenshell import entity_instance from ifcopenshell.api.alignment._get_segment_endpoint import _get_segment_endpoint from ifcopenshell.api.alignment._update_zero_length_segment_placement import _update_zero_length_segment_placement diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py index 2e643272d5..c143754568 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_segment_to_layout.py @@ -22,28 +22,11 @@ import numpy as np import ifcopenshell import ifcopenshell.api.alignment -from ifcopenshell.api.alignment import _map_alignment_cant_segment from ifcopenshell.api.alignment._update_zero_length_segment_placement import _update_zero_length_segment_placement import ifcopenshell.api.nest -import ifcopenshell.api.pset -import ifcopenshell.geom -import ifcopenshell.util.alignment -import ifcopenshell.util.unit -from ifcopenshell import entity_instance, ifcopenshell_wrapper +from ifcopenshell import entity_instance from ifcopenshell.api.alignment._add_segment_to_curve import _add_segment_to_curve from ifcopenshell.api.alignment._get_segment_endpoint import _get_segment_endpoint -from ifcopenshell.api.alignment._get_segment_start_point_label import ( - _get_segment_start_point_label, -) -from ifcopenshell.api.alignment._map_alignment_cant_segment import ( - _map_alignment_cant_segment, -) -from ifcopenshell.api.alignment._map_alignment_horizontal_segment import ( - _map_alignment_horizontal_segment, -) -from ifcopenshell.api.alignment._map_alignment_vertical_segment import ( - _map_alignment_vertical_segment, -) def _add_segment_to_layout( diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py index 72302cc40e..75717ba793 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_add_zero_length_segment.py @@ -18,11 +18,7 @@ import ifcopenshell import ifcopenshell.api.alignment -import ifcopenshell.util.alignment from ifcopenshell import entity_instance -from ifcopenshell.api.alignment._get_segment_start_point_label import ( - _get_segment_start_point_label, -) def _add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance) -> None: diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/_get_segment_endpoint.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/_get_segment_endpoint.py index 29b2d0be8a..86f07f5a32 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/_get_segment_endpoint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/_get_segment_endpoint.py @@ -18,6 +18,7 @@ import ifcopenshell.api.alignment +import ifcopenshell.geom from ifcopenshell import entity_instance, ifcopenshell_wrapper from ifcopenshell.api.alignment._map_alignment_segment import _map_alignment_segment from typing import Union diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py index 621712e093..6c81234894 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_stationing_referent.py @@ -58,7 +58,11 @@ def add_stationing_referent( if on_basis_curve is None: on_basis_curve = True - curve = ifcopenshell.api.alignment.get_basis_curve(alignment) if on_basis_curve else ifcopenshell.api.alignment.get_curve(alignment) + curve = ( + ifcopenshell.api.alignment.get_basis_curve(alignment) + if on_basis_curve + else ifcopenshell.api.alignment.get_curve(alignment) + ) object_placement = None representation = None diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py index e5f9b4bd8a..cbd19c2d12 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/add_zero_length_segment.py @@ -23,18 +23,8 @@ import ifcopenshell.api.alignment from ifcopenshell.api.alignment._get_segment_endpoint import _get_segment_endpoint from ifcopenshell.api.alignment._update_zero_length_segment_placement import _update_zero_length_segment_placement import ifcopenshell.api.nest -import ifcopenshell.ifcopenshell_wrapper as wrapper import ifcopenshell.util.unit from ifcopenshell import entity_instance -from ifcopenshell.api.alignment._get_segment_start_point_label import ( - _get_segment_start_point_label, -) -from ifcopenshell.api.alignment._map_alignment_horizontal_segment import ( - _map_alignment_horizontal_segment, -) -from ifcopenshell.api.alignment._map_alignment_vertical_segment import ( - _map_alignment_vertical_segment, -) from ifcopenshell.api.alignment._update_curve_segment_transition_code import ( _update_curve_segment_transition_code, ) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py index 5d7d105ec8..a1b7734af6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py @@ -87,9 +87,7 @@ def create( _create_geometric_representation(file, alignment) referent_name = ifcopenshell.util.alignment.station_as_string(file, start_station) - referent = ifcopenshell.api.alignment.add_stationing_referent( - file, referent_name, alignment, 0.0, start_station - ) + referent = ifcopenshell.api.alignment.add_stationing_referent(file, referent_name, alignment, 0.0, start_station) for layout in alignment_layouts: _add_zero_length_segment(file, layout) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_layout_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_layout_segment.py index 433f220754..cd2cc099ef 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_layout_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_layout_segment.py @@ -21,9 +21,7 @@ from typing import Union import numpy as np import ifcopenshell -import ifcopenshell.api.alignment -import ifcopenshell.geom -from ifcopenshell import entity_instance, ifcopenshell_wrapper +from ifcopenshell import entity_instance from ifcopenshell.api.alignment._add_segment_to_layout import _add_segment_to_layout diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py index 9c08f479be..f4db3e4b4e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py @@ -73,7 +73,10 @@ def distance_along_from_station(file: ifcopenshell.file, alignment: entity_insta return station - start_station stations = [ - (_distance_along_of_referent(referent), ifcopenshell.util.element.get_pset(referent, name="Pset_Stationing", prop="Station")) + ( + _distance_along_of_referent(referent), + ifcopenshell.util.element.get_pset(referent, name="Pset_Stationing", prop="Station"), + ) for referent in referent_nest.RelatedObjects ] stations.sort(key=lambda entry: entry[0]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_curve_segment.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_curve_segment.py index a9b9308d67..210249f43b 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/get_curve_segment.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/get_curve_segment.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . -from collections.abc import Sequence from ifcopenshell import entity_instance diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/update_end_point.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/update_end_point.py index 0349a99783..a772a16c77 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/update_end_point.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/update_end_point.py @@ -19,6 +19,7 @@ import numpy as np import ifcopenshell +import ifcopenshell.api.alignment import ifcopenshell.util.placement from ifcopenshell import entity_instance diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py index e5722f809a..76cdb3187d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py @@ -117,7 +117,7 @@ def assign_cost_item_quantity( "products": products or [], "prop_name": prop_name, "formula": formula, - "ifc_class" : ifc_class + "ifc_class": ifc_class, } return usecase.execute() @@ -134,7 +134,7 @@ class Usecase: continue self.assign_cost_control(related_object=product, cost_item=self.settings["cost_item"]) if self.settings["formula"]: - tree = ast.parse(self.settings["formula"], mode = "eval") + tree = ast.parse(self.settings["formula"], mode="eval") collector = VariableExtractor() collector.visit(tree) variables = collector.variables @@ -144,10 +144,10 @@ class Usecase: value = getter(product, variable) if value is None: - print( - f"WARNING: Variable '{variable}' in product '{product.Name}' " - f"is missing (None). Check Pset/Qset or property name." - ) + print( + f"WARNING: Variable '{variable}' in product '{product.Name}' " + f"is missing (None). Check Pset/Qset or property name." + ) elif value == 0: print( f"WARNING: Variable '{variable}' in product '{product.Name}' " @@ -159,7 +159,9 @@ class Usecase: new_quantity = None for quantity in self.quantities: - if quantity.Formula == self.settings["formula"] and len(self.settings["products"]) == 1: #Todo improve it + if ( + quantity.Formula == self.settings["formula"] and len(self.settings["products"]) == 1 + ): # Todo improve it new_quantity = quantity self.settings["ifc_class"] = quantity.is_a() continue @@ -184,23 +186,23 @@ class Usecase: self.update_cost_item_count() def get_value_from_pset( - self, - product:ifcopenshell.entity_instance, - v: str, + self, + product: ifcopenshell.entity_instance, + v: str, ) -> float: pset_name = v.split(".")[0] pset = ifcopenshell.util.element.get_pset(product, pset_name) pset_property_name = v.split(".")[1] - return (pset or {}).get(pset_property_name,None) + return (pset or {}).get(pset_property_name, None) def get_value_from_qset( - self, - product:ifcopenshell.entity_instance, - v: str, + self, + product: ifcopenshell.entity_instance, + v: str, ) -> float: - qtos = ifcopenshell.util.element.get_psets(product, qtos_only = True) + qtos = ifcopenshell.util.element.get_psets(product, qtos_only=True) quantities = next(iter(qtos.values()), {}) - return (quantities or {}).get(v,None) + return (quantities or {}).get(v, None) def assign_cost_control( self, related_object: ifcopenshell.entity_instance, cost_item: ifcopenshell.entity_instance @@ -243,6 +245,7 @@ class Usecase: count += 1 quantity[3] = count + OPERATORS = { ast.Add: operator.add, ast.Sub: operator.sub, @@ -252,18 +255,20 @@ OPERATORS = { ast.USub: operator.neg, } + def build_full_name(node): - #used for variables with dots + # used for variables with dots parts = [] while isinstance(node, ast.Attribute): - parts.append(node.attr) - node = node.value + parts.append(node.attr) + node = node.value if isinstance(node, ast.Name): parts.append(node.id) return ".".join(reversed(parts)) + class VariableExtractor(ast.NodeVisitor): def __init__(self): self.variables = set() @@ -274,6 +279,7 @@ class VariableExtractor(ast.NodeVisitor): def visit_Attribute(self, node): self.variables.add(build_full_name(node)) + class FormulaEvaluator(ast.NodeVisitor): def __init__(self, values): self.values = values @@ -281,7 +287,7 @@ class FormulaEvaluator(ast.NodeVisitor): def visit_BinOp(self, node): left = self.visit(node.left) right = self.visit(node.right) - return OPERATORS[type(node.op)](left, right) + return OPERATORS[type(node.op)](left, right) # ty: ignore[too-many-positional-arguments] def visit_Name(self, node): return self.values[node.id] diff --git a/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py b/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py index e87b833410..5a8e0e044a 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py +++ b/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py @@ -221,8 +221,7 @@ for id in to_emit: statements.append("%s << %s" % (id, stmt)) if __name__ == "__main__": - print( - r""" + print(r""" # This file is generated by IfcOpenShell ifcexpressparser bootstrap.py from __future__ import annotations @@ -261,6 +260,4 @@ if __name__ == "__main__": mdl = importlib.import_module(output) mdl.Generator(m).emit() sys.stdout.write(m.schema.name) -""" - % ("\n ".join(statements)) - ) +""" % ("\n ".join(statements))) diff --git a/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py b/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py index 36302d1229..38fa867778 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py +++ b/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py @@ -695,6 +695,7 @@ codegen_rule("MOD", lambda context: "%") codegen_rule("TRUE", lambda context: "True") codegen_rule("FALSE", lambda context: "False") + def _dotted_name(node: ast.AST): """Return dotted name for Name/Attribute chains, else None.""" if isinstance(node, ast.Name): @@ -704,6 +705,7 @@ def _dotted_name(node: ast.AST): return f"{base}.{node.attr}" if base else node.attr return None + class AttributeGetattrTransformer(ast.NodeTransformer): def visit_Attribute(self, node): parents = [] @@ -720,7 +722,7 @@ class AttributeGetattrTransformer(ast.NodeTransformer): if isinstance(node.ctx, ast.Store): return node - if _dotted_name(node) in ('ifcopenshell.create_entity', 'str.lower'): + if _dotted_name(node) in ("ifcopenshell.create_entity", "str.lower"): return node if node.attr.startswith("__"): diff --git a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py index dd1e96c889..3981dbc421 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py +++ b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py @@ -363,24 +363,18 @@ class EarlyBoundCodeWriter: ) ) - self.statements[self.statements.index("{factory_placeholder}")] = ( - """ + self.statements[self.statements.index("{factory_placeholder}")] = """ class %(schema_name)s_instance_factory : public IfcParse::instance_factory { virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const { %(instance_mapping)s } }; -""" - % locals() - ) +""" % locals() "" - self.statements[self.statements.index("{string_pool_placeholder}")] = ( - """ + self.statements[self.statements.index("{string_pool_placeholder}")] = """ const std::string strings[] = {%s}; -""" - % ",".join(map(lambda s: '"%s"s' % s, self.strings)) - ) +""" % ",".join(map(lambda s: '"%s"s' % s, self.strings)) def __str__(self): return "\n".join(self.statements) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/app.py b/src/ifcopenshell-python/ifcopenshell/geom/app.py index fa07f3f2b8..d6bab207f1 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/app.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/app.py @@ -145,8 +145,7 @@ class configuration: config.set( "snippets", "print all wall ids", - self.config_encode( - """ + self.config_encode(""" ########################################################################### # A simple script that iterates over all walls in the current model # # and prints their Globally unique IDs (GUIDS) to the console window # @@ -154,15 +153,13 @@ class configuration: for wall in model.by_type("IfcWall"): print ("wall with global id: "+str(wall.GlobalId)) -""".lstrip() - ), +""".lstrip()), ) config.set( "snippets", "print properties of current selection", - self.config_encode( - """ + self.config_encode(""" ########################################################################### # A simple script that iterates over all IfcPropertySets of the currently # # selected object and prints them to the console # @@ -180,8 +177,7 @@ if selection: for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties: print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue)) print ("\\n") -""".lstrip() - ), +""".lstrip()), ) with open(conf_file, "w") as configfile: config.write(configfile) diff --git a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi index 3345eee5a6..20ab01b980 100644 --- a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi +++ b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi @@ -1697,10 +1697,16 @@ class uninitialized_tag: ... def arrange_polygons(settings, polygons): ... def clear_schemas(): ... -def construct_iterator(geometry_library, settings, file, num_threads): ... -def construct_iterator_with_include_exclude(geometry_library, settings, file, elems, include, num_threads): ... -def construct_iterator_with_include_exclude_globalid(geometry_library, settings, file, elems, include, num_threads): ... -def construct_iterator_with_include_exclude_id(geometry_library, settings, file, elems, include, num_threads): ... +def construct_iterator(geometry_library, settings, file, num_threads, logger=...): ... +def construct_iterator_with_include_exclude( + geometry_library, settings, file, elems, include, num_threads, logger=... +): ... +def construct_iterator_with_include_exclude_globalid( + geometry_library, settings, file, elems, include, num_threads, logger=... +): ... +def construct_iterator_with_include_exclude_id( + geometry_library, settings, file, elems, include, num_threads, logger=... +): ... def convert_loop_to_function_item(loop): ... def create_box(*args): ... def create_epeck(*args): ... @@ -1717,8 +1723,8 @@ def line_segments_to_polygons(s, eps, segments): ... def map_shape(settings, instance): ... def nary_union(sequence): ... def new_IfcBaseClass(schema_identifier: str, name: str) -> entity_instance: ... -def open(fn: str, readonly: bool = False) -> file: ... -def parse_ifcxml(filename): ... +def open(fn: str, readonly: bool = False, logger=...) -> file: ... +def parse_ifcxml(filename, logger=...): ... def polygons_to_svg(*args): ... def read(data): ... def register_schema(arg1): ... diff --git a/src/ifcopenshell-python/ifcopenshell/util/alignment.py b/src/ifcopenshell-python/ifcopenshell/util/alignment.py index 1b90ac7c5f..db2ba8e54f 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/alignment.py +++ b/src/ifcopenshell-python/ifcopenshell/util/alignment.py @@ -56,7 +56,7 @@ def append_zero_length_segments(file: ifcopenshell.file) -> ifcopenshell.file: for alignment in alignments: layouts = ifcopenshell.api.alignment.get_alignment_layouts(alignment) for layout in layouts: - ifcopenshell.api.alignment.add_zero_length_segment(patched_file, layout, include_referent=False) + ifcopenshell.api.alignment.add_zero_length_segment(patched_file, layout) curve = ifcopenshell.api.alignment.get_layout_curve(layout) if curve: ifcopenshell.api.alignment.add_zero_length_segment(patched_file, curve) diff --git a/src/ifcopenshell-python/ifcopenshell/util/cost.py b/src/ifcopenshell-python/ifcopenshell/util/cost.py index fc3de44455..4354e49e90 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/cost.py +++ b/src/ifcopenshell-python/ifcopenshell/util/cost.py @@ -355,8 +355,7 @@ def get_cost_rate( class CostValueUnserialiser: def parse(self, formula: str): - l = lark.Lark( - """start: formula + l = lark.Lark("""start: formula formula: operand (operator operand)* operand: value | category "(" formula ")" value: NUMBER? @@ -393,8 +392,7 @@ class CostValueUnserialiser: NEWLINE: (CR? LF)+ %ignore WS // Disregard spaces in text - """ - ) + """) start = l.parse(formula) return self.get_formula(start.children[0]) diff --git a/src/ifcopenshell-python/ifcopenshell/util/selector.py b/src/ifcopenshell-python/ifcopenshell/util/selector.py index d67292fb1d..abaa4e4119 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/selector.py +++ b/src/ifcopenshell-python/ifcopenshell/util/selector.py @@ -39,8 +39,7 @@ import ifcopenshell.util.shape import ifcopenshell.util.system import ifcopenshell.util.unit -filter_elements_grammar = lark.Lark( - """start: filter_group +filter_elements_grammar = lark.Lark("""start: filter_group filter_group: facet_list ("+" facet_list)* facet_list: facet ("," facet)* @@ -111,11 +110,9 @@ filter_elements_grammar = lark.Lark( NEWLINE: (CR? LF)+ %ignore WS // Disregard spaces in text -""" -) +""") -get_element_grammar = lark.Lark( - """start: keys +get_element_grammar = lark.Lark("""start: keys keys: key ("." key)* key: quoted_string | regex_string | unquoted_string @@ -130,11 +127,9 @@ get_element_grammar = lark.Lark( WS: /[ \\t\\f\\r\\n]/+ %ignore WS // Disregard spaces in text - """ -) + """) -format_grammar = lark.Lark( - """start: expression +format_grammar = lark.Lark("""start: expression ?expression: add_sub ?add_sub: mul_div @@ -193,8 +188,7 @@ format_grammar = lark.Lark( NEWLINE: (CR? LF)+ %ignore WS // Disregard spaces in text -""" -) +""") class FormatTransformer(lark.Transformer): diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_representation.py b/src/ifcopenshell-python/test/api/alignment/test_create_representation.py index 3d9bb3be7f..0fd0b2dc41 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_representation.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_representation.py @@ -21,9 +21,12 @@ import math import pytest import ifcopenshell +import ifcopenshell.api.aggregate import ifcopenshell.api.alignment +import ifcopenshell.api.context +import ifcopenshell.api.spatial import ifcopenshell.api.unit -import numpy as np +import ifcopenshell.util.unit def test_create_representation(): diff --git a/src/ifcopenshell-python/test/test_parse.py b/src/ifcopenshell-python/test/test_parse.py index 1a0a379e93..189556c31f 100644 --- a/src/ifcopenshell-python/test/test_parse.py +++ b/src/ifcopenshell-python/test/test_parse.py @@ -1,5 +1,6 @@ import ifcopenshell + def test_skip_over_non_entity_instance(): data = """ ISO-10303-21; diff --git a/src/ifcopenshell-python/test/test_rules.py b/src/ifcopenshell-python/test/test_rules.py index b387e17574..ae981abf00 100644 --- a/src/ifcopenshell-python/test/test_rules.py +++ b/src/ifcopenshell-python/test/test_rules.py @@ -46,4 +46,4 @@ def test_file(filename): if __name__ == "__main__": - pytest.main(["-sx", __file__, '--import-mode=importlib']) + pytest.main(["-sx", __file__, "--import-mode=importlib"]) diff --git a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py index 2645bcc86e..6aba19516b 100644 --- a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py +++ b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py @@ -111,7 +111,7 @@ class Patcher(ifcpatch.BasePatcher): if element.is_a("IfcProject"): proj = self.new.add(element) for ctx in element.RepresentationContexts or (): - for coop in getattr(ctx, 'HasCoordinateOperation', ()): + for coop in getattr(ctx, "HasCoordinateOperation", ()): self.new.add(coop) return proj return ifcopenshell.api.project.append_asset( diff --git a/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py b/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py index adeda0b669..1375f4e241 100644 --- a/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py +++ b/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py @@ -33,9 +33,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): Points=point_list, Segments=segments, ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) return curve def test_run_without_segments(self): @@ -80,9 +78,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): Points=point_list, Segments=[self.file.createIfcLineIndex((1, 2, 3, 4, 1))], ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) ifcpatch.execute( {"input": "input.ifc", "file": self.file, "recipe": "DowngradeIndexedPolyCurve", "arguments": []} ) @@ -110,9 +106,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): self.file.createIfcLineIndex((3, 4)), ], ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) ifcpatch.execute( {"input": "input.ifc", "file": self.file, "recipe": "DowngradeIndexedPolyCurve", "arguments": []} )