From eac4e80ee9cbeeb3484f8a44e9f1828839c7eba9 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 25 Jul 2024 16:41:02 +0500 Subject: [PATCH] typing --- src/blenderbim/blenderbim/core/bsdd.py | 38 +++++++++++++++++--- src/blenderbim/blenderbim/core/tool.py | 1 + src/blenderbim/blenderbim/tool/bsdd.py | 36 ++++++++++++------- src/bsdd/bsdd.py | 4 +-- src/ifcopenshell-python/ifcopenshell/file.py | 6 ++-- 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/src/blenderbim/blenderbim/core/bsdd.py b/src/blenderbim/blenderbim/core/bsdd.py index cb55e07b8a..3d4093e0a0 100644 --- a/src/blenderbim/blenderbim/core/bsdd.py +++ b/src/blenderbim/blenderbim/core/bsdd.py @@ -1,4 +1,32 @@ -def get_class_properties(client, bsdd): +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2021 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# 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 typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + import bpy + import ifcopenshell + import bsdd + import blenderbim.tool as tool + + +def get_class_properties(client: bsdd.Client, bsdd: tool.Bsdd) -> None: bsdd.clear_class_psets() data = bsdd.get_active_class_data(client) pset_dict = bsdd.get_property_dict(data) @@ -7,7 +35,7 @@ def get_class_properties(client, bsdd): bsdd.create_class_psets(pset_dict) -def load_bsdd(client, bsdd): +def load_bsdd(client: bsdd.Client, bsdd: tool.Bsdd) -> None: bsdd.clear_domains() if bsdd.should_load_preview_domains: dictionaries = bsdd.get_dictionaries(client) @@ -16,15 +44,15 @@ def load_bsdd(client, bsdd): bsdd.create_dictionaries(dictionaries) -def search_class(keyword: str, client, bsdd): +def search_class(keyword: str, client: bsdd.Client, bsdd: tool.Bsdd) -> None: bsdd.clear_classes() if len(keyword) < 3: return related_entities = bsdd.get_related_ifc_entities(keyword) active_dictionary_uri = bsdd.get_active_dictionary_uri() - classes: dict = bsdd.search_class(client, keyword, [active_dictionary_uri], related_entities) + classes = bsdd.search_class(client, keyword, [active_dictionary_uri], related_entities) bsdd.create_classes(classes) -def set_active_bsdd_dictionary(name: str, uri: str, bsdd): +def set_active_bsdd_dictionary(name: str, uri: str, bsdd: tool.Bsdd) -> None: bsdd.set_active_bsdd(name, uri) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 1b31080047..cf835226ce 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -139,6 +139,7 @@ class Brick: def clear_breadcrumbs(cls, split_screen=False): pass +@interface class Bsdd: def clear_class_psets(cls): pass def clear_classes(cls): pass diff --git a/src/blenderbim/blenderbim/tool/bsdd.py b/src/blenderbim/blenderbim/tool/bsdd.py index 6626a3953c..264413de1a 100644 --- a/src/blenderbim/blenderbim/tool/bsdd.py +++ b/src/blenderbim/blenderbim/tool/bsdd.py @@ -2,10 +2,11 @@ import blenderbim.core.tool import blenderbim.tool as tool import bpy import json +import bsdd +from typing import Any, Union, Optional class Bsdd(blenderbim.core.tool.Bsdd): - @classmethod def clear_class_psets(cls) -> None: bpy.context.scene.BIMBSDDProperties.classification_psets.clear() @@ -19,7 +20,7 @@ class Bsdd(blenderbim.core.tool.Bsdd): bpy.context.scene.BIMBSDDProperties.domains.clear() @classmethod - def create_class_psets(cls, pset_dict: dict): + def create_class_psets(cls, pset_dict: dict[str, dict[str, Any]]) -> None: props = bpy.context.scene.BIMBSDDProperties data_type_map = { "String": "string", @@ -39,7 +40,7 @@ class Bsdd(blenderbim.core.tool.Bsdd): new2.data_type = data_type_map[data["data_type"]] @classmethod - def create_classes(cls, class_dict): + def create_classes(cls, class_dict: list[bsdd.ClassSearchResponseClassContractV1]) -> None: props = bpy.context.scene.BIMBSDDProperties for _class in sorted(class_dict, key=lambda c: c["referenceCode"]): prop = props.classifications.add() @@ -51,7 +52,7 @@ class Bsdd(blenderbim.core.tool.Bsdd): prop.domain_namespace_uri = _class["dictionaryUri"] @classmethod - def create_dictionaries(cls, dictionaries: dict): + def create_dictionaries(cls, dictionaries: list[bsdd.DictionaryContractV1]) -> None: props = bpy.context.scene.BIMBSDDProperties for dictionary in sorted(dictionaries, key=lambda d: d["name"]): new = props.domains.add() @@ -63,7 +64,7 @@ class Bsdd(blenderbim.core.tool.Bsdd): new.version = dictionary["version"] @classmethod - def get_active_class_data(cls, client): + def get_active_class_data(cls, client: bsdd.Client) -> Union[bsdd.ClassContractV1, dict]: prop = bpy.context.scene.BIMBSDDProperties bsdd_classification = prop.classifications[prop.active_classification_index] if not bsdd_classification: @@ -75,15 +76,15 @@ class Bsdd(blenderbim.core.tool.Bsdd): return bpy.context.scene.BIMBSDDProperties.active_uri @classmethod - def get_dictionaries(cls, client, status=None) -> list: + def get_dictionaries(cls, client: bsdd.Client, status: Optional[str] = None) -> list[bsdd.DictionaryContractV1]: response = client.get_dictionary() dicts = response.get("dictionaries") or [] if status is not None: - dicts = filter(lambda d: d["status"] == status, dicts) + dicts = list(filter(lambda d: d["status"] == status, dicts)) return dicts @classmethod - def get_property_dict(cls, class_data: dict): + def get_property_dict(cls, class_data: Union[bsdd.ClassContractV1, dict]) -> Union[dict[str, dict[str, Any]], None]: properties = class_data.get("classProperties", None) if not properties: return None @@ -108,9 +109,11 @@ class Bsdd(blenderbim.core.tool.Bsdd): return psets @classmethod - def get_related_ifc_entities(cls, keyword): + def get_related_ifc_entities(cls, keyword: str) -> list[str]: active_object = bpy.context.active_object related_ifc_entities = [] + # TODO: keyword length seems to be already double-checked in core. + # And {"FINISHED"} return value is never used. if len(keyword) < 3: return {"FINISHED"} if cls.should_filter_ifc_class() and active_object: @@ -120,13 +123,20 @@ class Bsdd(blenderbim.core.tool.Bsdd): return related_ifc_entities @classmethod - def search_class(cls, client, keyword, dictionary_uris, related_ifc_entities) -> dict: - response = client.search_class(keyword, dictionary_uris=dictionary_uris, - related_ifc_entities=related_ifc_entities) + def search_class( + cls, + client: bsdd.Client, + keyword: str, + dictionary_uris: Union[list[str], None], + related_ifc_entities: Union[list[str], None], + ) -> list[bsdd.ClassSearchResponseClassContractV1]: + response = client.search_class( + keyword, dictionary_uris=dictionary_uris, related_ifc_entities=related_ifc_entities + ) return response.get("classes", []) @classmethod - def set_active_bsdd(cls, name, uri): + def set_active_bsdd(cls, name: str, uri: str) -> None: props = bpy.context.scene.BIMBSDDProperties props.active_domain = name props.active_uri = uri diff --git a/src/bsdd/bsdd.py b/src/bsdd/bsdd.py index 31c87ecdcb..6effc6b5c2 100644 --- a/src/bsdd/bsdd.py +++ b/src/bsdd/bsdd.py @@ -725,8 +725,8 @@ class Client: def search_class( self, search_text: str, - dictionary_uris=None, - related_ifc_entities=None, + dictionary_uris: Optional[list[str]] = None, + related_ifc_entities: Optional[list[str]] = None, version: int = 1, offset: int = 0, limit: int = 100, diff --git a/src/ifcopenshell-python/ifcopenshell/file.py b/src/ifcopenshell-python/ifcopenshell/file.py index a7cc478011..7ab7cd1174 100644 --- a/src/ifcopenshell-python/ifcopenshell/file.py +++ b/src/ifcopenshell-python/ifcopenshell/file.py @@ -24,7 +24,7 @@ import zipfile import functools import ifcopenshell from pathlib import Path -from typing import Optional, Any, Union, Callable, Generator +from typing import Optional, Any, Union, Callable, Generator, Literal from . import ifcopenshell_wrapper from .entity_instance import entity_instance @@ -406,7 +406,7 @@ class file: return e @property - def schema(self) -> str: + def schema(self) -> Literal["IFC2X3", "IFC4", "IFC4X3"]: """General IFC schema version: IFC2X3, IFC4, IFC4X3.""" prefixes = ("IFC", "X", "_ADD", "_TC") reg = "".join(f"(?P<{s}>{s}\d+)?" for s in prefixes) @@ -668,5 +668,5 @@ class file: return file(ifcopenshell_wrapper.read(s)) @staticmethod - def from_pointer(v): + def from_pointer(v) -> "file": return file_dict.get(v)()