From 27aee31adf4a82088388ec4f246de68b364da69f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 26 Aug 2024 17:23:51 +0500 Subject: [PATCH] typing --- src/bonsai/bonsai/bim/ifc.py | 2 ++ src/bonsai/bonsai/core/debug.py | 15 ++++++++++++--- src/bonsai/bonsai/core/geometry.py | 1 + src/bonsai/bonsai/tool/debug.py | 18 ++++++++++++------ src/bonsai/test/bim/test_feature.py | 17 +++++++++-------- .../ifcopenshell/express/__init__.py | 8 +++++++- 6 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/bonsai/bonsai/bim/ifc.py b/src/bonsai/bonsai/bim/ifc.py index da67773ace..f652abb487 100644 --- a/src/bonsai/bonsai/bim/ifc.py +++ b/src/bonsai/bonsai/bim/ifc.py @@ -140,6 +140,8 @@ class IfcStore: def update_cache(): if not IfcStore.cache: return + assert IfcStore.cache_path + assert IfcStore.file ifc_key = IfcStore.path + IfcStore.file.wrapped_data.header.file_name.time_stamp ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest() new_cache_path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5") diff --git a/src/bonsai/bonsai/core/debug.py b/src/bonsai/bonsai/core/debug.py index 94f78d4a9f..ccf569798c 100644 --- a/src/bonsai/bonsai/core/debug.py +++ b/src/bonsai/bonsai/core/debug.py @@ -17,15 +17,24 @@ # along with Bonsai. If not, see . -def parse_express(debug, filename): +from __future__ import annotations +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + import bpy + import ifcopenshell + import bonsai.tool as tool + + +def parse_express(debug: tool.Debug, filename: str) -> None: debug.add_schema_identifier(debug.load_express(filename)) -def purge_hdf5_cache(debug): +def purge_hdf5_cache(debug: tool.Debug) -> None: debug.purge_hdf5_cache() -def purge_unused_elements(ifc, debug, ifc_class): +def purge_unused_elements(ifc, debug: tool.Debug, ifc_class: str) -> int: ifc_file = ifc.get() unused_elements = [i for i in ifc_file.by_type(ifc_class) if ifc_file.get_total_inverses(i) == 0] unused_elements_amount = len(unused_elements) diff --git a/src/bonsai/bonsai/core/geometry.py b/src/bonsai/bonsai/core/geometry.py index 73625af636..7476c56381 100644 --- a/src/bonsai/bonsai/core/geometry.py +++ b/src/bonsai/bonsai/core/geometry.py @@ -122,6 +122,7 @@ def switch_representation( return entity = ifc.get_entity(obj) + assert entity current_obj_data = geometry.get_object_data(obj) if not current_obj_data and geometry.is_text_literal(representation): diff --git a/src/bonsai/bonsai/tool/debug.py b/src/bonsai/bonsai/tool/debug.py index 17125a2113..41923bd908 100644 --- a/src/bonsai/bonsai/tool/debug.py +++ b/src/bonsai/bonsai/tool/debug.py @@ -19,31 +19,37 @@ import os import bpy import ifcopenshell.express +import ifcopenshell.express.schema +import ifcopenshell.express.schema_class +import ifcopenshell.util.element import bonsai.core.tool import bonsai.tool as tool from bonsai.bim.ifc import IfcStore +from mathutils import Vector class Debug(bonsai.core.tool.Debug): @classmethod - def add_schema_identifier(cls, schema): + def add_schema_identifier(cls, schema: ifcopenshell.express.schema_class.SchemaClass) -> None: IfcStore.schema_identifiers.append(schema.schema_name) @classmethod - def load_express(cls, filename): + def load_express(cls, filename: str) -> ifcopenshell.express.schema_class.SchemaClass: schema = ifcopenshell.express.parse(filename) ifcopenshell.register_schema(schema) return schema @classmethod - def purge_hdf5_cache(cls): + def purge_hdf5_cache(cls) -> None: cache_dir = os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache") filelist = [f for f in os.listdir(cache_dir) if f.endswith(".h5")] for f in filelist: os.remove(os.path.join(cache_dir, f)) @classmethod - def debug_geometry(cls, verts=[], edges=[], name="Debug"): + def debug_geometry( + cls, verts: list[Vector] = [], edges: list[tuple[int, int]] = [], name: str = "Debug" + ) -> bpy.types.Object: mesh = bpy.data.meshes.new("Debug") mesh.from_pydata(verts, edges, []) obj = bpy.data.objects.new(name, mesh) @@ -51,13 +57,13 @@ class Debug(bonsai.core.tool.Debug): return obj @classmethod - def remove_unused_elements(cls, elements): + def remove_unused_elements(cls, elements: list[ifcopenshell.entity_instance]) -> None: ifc_file = tool.Ifc.get() for element in elements: ifcopenshell.util.element.remove_deep2(ifc_file, element) @classmethod - def print_unused_elements_stats(cls, requested_ifc_class="", ignore_classes=tuple()): + def print_unused_elements_stats(cls, requested_ifc_class: str = "", ignore_classes: tuple[str] = tuple()) -> int: ifc_file = tool.Ifc.get() # get list of ifc classes used in model diff --git a/src/bonsai/test/bim/test_feature.py b/src/bonsai/test/bim/test_feature.py index c0d9438755..0d3194154f 100644 --- a/src/bonsai/test/bim/test_feature.py +++ b/src/bonsai/test/bim/test_feature.py @@ -33,7 +33,7 @@ from pytest_bdd import scenarios, given, when, then, parsers from mathutils import Vector from math import radians from pathlib import Path -from typing import Union +from typing import Union, Any scenarios("feature") @@ -49,18 +49,18 @@ webbrowser.open = lambda x: True class PanelSpy: - def __init__(self, panel): + def __init__(self, panel: type[bpy.types.Panel]): self.is_spy_dirty = True self.panel = panel def refresh_spy(self): if self.is_spy_dirty: self.is_spy_dirty = False - self.spied_attr = None - self.spied_labels = [] - self.spied_props = [] - self.spied_operators = [] - self.spied_lists = [] + self.spied_attr: Union[str, None] = None + self.spied_labels: list[str] = [] + self.spied_props: list[dict[str, Any]] = [] + self.spied_operators: list[dict[str, Any]] = [] + self.spied_lists: list[dict[str, Any]] = [] self.panel.draw(self, bpy.context) def __getattr__(self, attr): @@ -91,6 +91,7 @@ class PanelSpy: return self elif self.spied_attr == "prop": props, name = args + props: bpy.types.bpy_struct text = kwargs.get("text", props.bl_rna.properties[name].name) icon = kwargs.get("icon", None) prop_type = props.bl_rna.properties[name].type @@ -152,7 +153,7 @@ class TemplateListSpy: panel_name_cache = {} -panel_spy = None +panel_spy: PanelSpy = None def replace_variables(value): diff --git a/src/ifcopenshell-python/ifcopenshell/express/__init__.py b/src/ifcopenshell-python/ifcopenshell/express/__init__.py index d7a0ceebc4..91aa35fd82 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/express/__init__.py @@ -16,9 +16,14 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +from __future__ import annotations import os import sys import subprocess +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import schema_class d = os.path.abspath(os.path.dirname(__file__)) sys.path.append(d) @@ -30,8 +35,9 @@ if not os.path.exists(exp_parser_fn): subprocess.call([sys.executable, "bootstrap.py"], cwd=d, stdout=f) -def parse(fn): +def parse(fn: str) -> schema_class.SchemaClass: import express_parser import schema_class + mapping = express_parser.parse(fn) return schema_class.SchemaClass(mapping, schema_class.LateBoundSchemaInstantiator).code