diff --git a/src/bsdd/bsdd.py b/src/bsdd/bsdd.py index 2fd109674b..3ba93937e7 100644 --- a/src/bsdd/bsdd.py +++ b/src/bsdd/bsdd.py @@ -15,14 +15,368 @@ # # You should have received a copy of the GNU Lesser General Public License # along with bSDD. If not, see . +from __future__ import annotations import uuid import time -import json import urllib import requests import webbrowser import http.server +from typing import TypedDict, Literal + +Status = Literal["Preview", "Active", "Inactive"] +ClassTypes = Literal["Class", "GroupOfProperties", "AlternativeUse", "Material"] + + +class DictionaryContractV1(TypedDict): + uri: str + name: str + version: str + organizationCodeOwner: str + organizationNameOwner: str + defaultLanguageCode: str + license: str + licenseUrl: str + qualityAssuranceProcedure: str + qualityAssuranceProcedureUrl: str + status: str + moreInfoUrl: str + releaseDate: str + lastUpdatedUtc: str + + +class DictionaryResponseContractV1(TypedDict): + totalCount: int + offset: int + count: int + dictionaries: list[DictionaryContractV1] + + +class ClassListItemContractV1(TypedDict): + uri: str + code: str + name: str + classType: str + referenceCode: str + parentClassCode: str + children: list[ClassListItemContractV1] + + +class DictionaryClassesResponseContractV1(TypedDict): + uri: str + name: str + version: str + organizationCodeOwner: str + organizationNameOwner: str + defaultLanguageCode: str + license: str + licenseUrl: str + qualityAssuranceProcedure: str + qualityAssuranceProcedureUrl: str + status: str + moreInfoUrl: str + releaseDate: str + lastUpdatedUtc: str + classes: list[ClassListItemContractV1] + classesTotalCount: int + classesOffset: int + classesCount: int + + +class PropertyListItemContractV1(TypedDict): + uri: str + code: str + name: str + + +class DictionaryPropertiesResponseContractV1(TypedDict): + uri: str + name: str + version: str + organizationCodeOwner: str + organizationNameOwner: str + defaultLanguageCode: str + license: str + licenseUrl: str + qualityAssuranceProcedure: str + qualityAssuranceProcedureUrl: str + status: str + moreInfoUrl: str + releaseDate: str + lastUpdatedUtc: str + properties: list[PropertyListItemContractV1] + propertiesTotalCount: int + propertiesOffset: int + propertiesCount: int + + +class ClassReferenceContractV1(TypedDict): + uri: str + name: str + code: str + + +class ClassPropertyValueContractV1(TypedDict): + uri: str + code: str + value: str + description: str + sortNumber: int + + +class ClassPropertyContractV1(TypedDict): + name: str + uri: str + description: str + dataType: str + dimension: str + dimensionLength: int + dimensionMass: int + dimensionTime: int + dimensionElectricCurrent: int + dimensionThermodynamicTemperature: int + dimensionAmountOfSubstance: int + dimensionLuminousIntensity: int + dynamicParameterPropertyCodes: list[str] + example: str + isDynamic: bool + isRequired: bool + isWritable: bool + maxExclusive: float + maxInclusive: float + minExclusive: float + minInclusive: float + pattern: str + physicalQuantity: str + allowedValues: list[ClassPropertyValueContractV1] + predefinedValue: str + propertyCode: str + propertyDictionaryName: str + propertyUri: str + propertySet: str + propertyStatus: str + propertyValueKind: str + symbol: str + units: list[str] + qudtCodes: list[str] + + +class PropertyContractV4(TypedDict): + dictionaryUri: str + activationDateUtc: str + code: str + creatorLanguageCode: str + countriesOfUse: list[str] + countryOfOrigin: str + deActivationDateUtc: str + definition: str + deprecationExplanation: str + description: str + documentReference: str + name: str + uri: str + replacedObjectCodes: list[str] + replacingObjectCodes: list[str] + revisionDateUtc: str + revisionNumber: int + status: str + subdivisionsOfUse: list[str] + uid: str + versionDateUtc: str + versionNumber: int + visualRepresentationUri: str + connectedPropertyCodes: list[str] + dataType: str + dimension: str + dimensionLength: int + dimensionMass: int + dimensionTime: int + dimensionElectricCurrent: int + dimensionThermodynamicTemperature: int + dimensionAmountOfSubstance: int + dimensionLuminousIntensity: int + dynamicParameterPropertyCodes: list[str] + example: str + isDynamic: bool + maxExclusive: float + maxInclusive: float + methodOfMeasurement: str + minExclusive: float + minInclusive: float + pattern: str + physicalQuantity: str + allowedValues: list[PropertyValueContractV4] + propertyValueKind: str + propertyRelations: list[PropertyRelationContractV4] + textFormat: str + units: list[str] + qudtCodes: list[str] + propertyClasses: list[PropertyClassContractV4] + + +class PropertyValueContractV4(TypedDict): + uri: str + code: str + value: str + description: str + sortNumber: int + + +class PropertyRelationContractV4(TypedDict): + uri: str + relationType: str + relatedPropertyUri: str + relatedPropertyName: str + + +class PropertyClassContractV4(TypedDict): + uri: str + code: str + name: str + definition: str + description: str + propertySet: str + + +class ClassRelationContractV1(TypedDict): + uri: str + relationType: str + relatedClassUri: str + relatedClassName: str + fraction: float + + +class TextSearchResponseContractV1(TypedDict): + totalCount: int + offset: int + count: int + classes: list[TextSearchResponseClassContractV1] + dictionaries: list[TextSearchResponseDictionaryContractV1] + properties: list[TextSearchResponsePropertyContractV1] + + +class TextSearchResponseClassContractV1(TypedDict): + dictionaryUri: str + dictionaryName: str + name: str + referenceCode: str + uri: str + classType: str + description: str + parentClassName: str + relatedIfcEntityNames: list[str] + + +class TextSearchResponseDictionaryContractV1(TypedDict): + uri: str + name: str + + +class TextSearchResponsePropertyContractV1(TypedDict): + dictionaryUri: str + dictionaryName: str + uri: str + name: str + description: str + + +class ClassContractV1(TypedDict): + dictionaryUri: str + activationDateUtc: str + code: str + creatorLanguageCode: str + countriesOfUse: list[str] + countryOfOrigin: str + deActivationDateUtc: str + definition: str + deprecationExplanation: str + description: str + documentReference: str + name: str + uri: str + replacedObjectCodes: list[str] + replacingObjectCodes: list[str] + revisionDateUtc: str + revisionNumber: int + status: str + subdivisionsOfUse: list[str] + uid: str + versionDateUtc: str + versionNumber: int + visualRepresentationUri: str + classType: str + referenceCode: str + synonyms: list[str] + relatedIfcEntityNames: list[str] + parentClassReference: ClassReferenceContractV1 + classProperties: list[ClassPropertyContractV1] + classRelations: list[ClassRelationContractV1] + childClassReferences: list[ClassReferenceContractV1] + + +class SearchInDictionaryResponseContractV1(TypedDict): + totalCount: int + offset: int + count: int + dictionary: DictionarySearchResultContractV1 + + +class DictionarySearchResultContractV1(TypedDict): + name: str + uri: str + classes: list[ClassSearchResultContractV1] + + +class ClassSearchResultContractV1(TypedDict): + name: str + uri: str + referenceCode: str + classType: str + definition: str + synonyms: list[str] + + +class ClassSearchResponseContractV1(TypedDict): + totalCount: int + offset: int + count: int + classes: list[ClassSearchResponseClassContractV1] + + +class ClassSearchResponseClassContractV1(TypedDict): + dictionaryUri: str + dictionaryName: str + name: str + referenceCode: str + uri: str + classType: str + description: str + parentClassName: str + relatedIfcEntityNames: list[str] + + +class CountryContractV1(TypedDict): + code: str + name: str + + +class LanguageContractV1(TypedDict): + isoCode: str + name: str + + +class ReferenceDocumentContractV1(TypedDict): + title: str + name: str + date: str + + +class UnitContractV1(TypedDict): + code: str + name: str + symbol: str + qudtUri: str class OAuthReceiver(http.server.BaseHTTPRequestHandler): @@ -209,7 +563,7 @@ class Client: print(f"function 'Client.Unit' is deprecated, use 'Client.get_units' instead") return self.get(f"api/Unit/{version}") - def get_dictionary(self, dictionary_uri: str = "", version: int = 1): + def get_dictionary(self, dictionary_uri: str = "", version: int = 1) -> DictionaryResponseContractV1: """ Get list of available Dictionaries This API replaces Domain @@ -220,8 +574,9 @@ class Client: } return self.get(endpoint, params) - def get_classes(self, dictionary_uri: str, use_nested_classes: bool = True, class_type: str = "Class", - language_code: str = "", version: int = 1): + def get_classes(self, dictionary_uri: str, use_nested_classes: bool = True, + class_type: ClassTypes = "Class", + language_code: str = "", version: int = 1) -> DictionaryClassesResponseContractV1: """ Get Dictionary with tree of classes This API replaces Domain @@ -235,7 +590,8 @@ class Client: } return self.get(endpoint, params) - def get_properties(self, dictionary_uri: str, language_code: str = "", version: int = 1): + def get_properties(self, dictionary_uri: str, language_code: str = "", + version: int = 1) -> DictionaryPropertiesResponseContractV1: """ Get Dictionary with its properties """ @@ -248,12 +604,12 @@ class Client: def get_class(self, class_uri: str, include_class_properties: bool = True, include_child_class_reference: bool = True, include_class_relations: bool = True, - language_code: str = "", version: int = 1): + language_code: str = "", version: int = 1) -> ClassContractV1: """ Get Class details this API replaces Classification """ - endpoint = f"Dictionary/v{version}/Properties" + endpoint = f"Class/v{version}" params = { "Uri": class_uri, "includeClassProperties": include_class_properties, @@ -263,7 +619,8 @@ class Client: } return self.get(endpoint, params) - def get_property(self, uri, include_classes=False, language_code="", version: int = 4): + def get_property(self, uri, include_classes=False, language_code="", + version: int = 4) -> PropertyContractV4: """ Get Property Detail this API replaces Property @@ -277,7 +634,7 @@ class Client: } return self.get(endpoint, params) - def get_property_value(self, uri, language_code="", version: int = 2): + def get_property_value(self, uri, language_code="", version: int = 2) -> PropertyValueContractV4: """ Get Property Value details this API replaces PropertyValue @@ -289,13 +646,16 @@ class Client: } return self.get(endpoint, params) - def search_text(self, search_text: str, type_filter="All", dictionary_uris=[], version: int = 1): + def search_text(self, search_text: str, type_filter="All", dictionary_uris=None, + version: int = 1) -> TextSearchResponseContractV1: """ Search the bSDD database using free text, get list of Classes and/or Properties matching the text. Pagination options are for Classes and Properties combined. So if result consists of 10 classes and 5 properties, TotalCount will be 15. Classes will be listed first, so if you then use Offset=10 and Limit=5, you will get the 5 properties. """ + if dictionary_uris is None: + dictionary_uris = [] endpoint = f"TextSearch/v{version}" params = { "SearchText": search_text, @@ -306,7 +666,8 @@ class Client: pass def search_in_dictionary(self, dictionary_uri: str, search_text: str = "", language_code: str = "", - related_ifc_entity: str = "", version: int = "1"): + related_ifc_entity: str = "", + version: int = "1") -> SearchInDictionaryResponseContractV1: """ Search the bSDD database, get list of Classes without details. This version uses new naming and returns one Dictionary instead of a list with always one Dictionary. @@ -321,12 +682,17 @@ class Client: } return self.get(endpoint, params) - def search_class(self, search_text: str, dictionary_uris=[], related_ifc_entities=[], version: int = 1): + def search_class(self, search_text: str, dictionary_uris=None, related_ifc_entities=None, + version: int = 1) -> ClassSearchResponseContractV1: """ Search the bSDD database using free text, get list of Classes matching the text and optional additional filters. this API replaces ClassificationSearch """ + if related_ifc_entities is None: + related_ifc_entities = [] + if dictionary_uris is None: + dictionary_uris = [] endpoint = f"Class/Search/v{version}" params = { "SearchText": search_text, @@ -335,7 +701,7 @@ class Client: } return self.get(endpoint, params) - def get_countries(self, version: int = 1): + def get_countries(self, version: int = 1) -> list[CountryContractV1]: """ Get list of all Countries this API replaces Country @@ -344,7 +710,7 @@ class Client: params = {} return self.get(endpoint, params) - def get_languages(self, version: int = 1): + def get_languages(self, version: int = 1) -> list[LanguageContractV1]: """ Get list of available Languages this API replaces Language @@ -353,7 +719,7 @@ class Client: params = {} return self.get(endpoint, params) - def get_reference_documents(self, version: int = 1): + def get_reference_documents(self, version: int = 1) -> list[ReferenceDocumentContractV1]: """ Get list of all ReferenceDocuments this API replaces Country @@ -362,7 +728,7 @@ class Client: params = {} return self.get(endpoint, params) - def get_units(self, version: int = 1): + def get_units(self, version: int = 1) -> list[UnitContractV1]: """ Get list of all Units this API replaces Unit @@ -373,7 +739,6 @@ class Client: def apply_ifc_classification_properties(ifc_file, element, classificationProperties): - import ifcopenshell import ifcopenshell.api import ifcopenshell.util.element