bsdd - update classes according to the latest API

Also added yml_to_classes.py script that can extract the classes automatically
This commit is contained in:
Andrej730
2024-09-20 14:50:31 +05:00
parent aeeae7365f
commit 18476ec7f3
2 changed files with 114 additions and 0 deletions
+37
View File
@@ -35,13 +35,17 @@ ClassTypes = Literal["Class", "GroupOfProperties", "AlternativeUse", "Material"]
# and should be typed with NotRequired.
# Use yml_to_classes.py to update classes.
class DictionaryContractV1(TypedDict):
code: str
uri: str
name: str
version: str
organizationCodeOwner: str
organizationNameOwner: str
defaultLanguageCode: str
isLatestVersion: bool
isVerified: bool
license: str
licenseUrl: str
qualityAssuranceProcedure: str
@@ -50,6 +54,7 @@ class DictionaryContractV1(TypedDict):
moreInfoUrl: str
releaseDate: str
lastUpdatedUtc: str
availableLanguages: list[CodeNameDto]
class DictionaryResponseContractV1(TypedDict):
@@ -66,16 +71,20 @@ class ClassListItemContractV1(TypedDict):
classType: str
referenceCode: str
parentClassCode: str
descriptionPart: str
children: list[ClassListItemContractV1]
class DictionaryClassesResponseContractV1(TypedDict):
code: str
uri: str
name: str
version: str
organizationCodeOwner: str
organizationNameOwner: str
defaultLanguageCode: str
isLatestVersion: bool
isVerified: bool
license: str
licenseUrl: str
qualityAssuranceProcedure: str
@@ -94,15 +103,19 @@ class PropertyListItemContractV1(TypedDict):
uri: str
code: str
name: str
descriptionPart: str
class DictionaryPropertiesResponseContractV1(TypedDict):
code: str
uri: str
name: str
version: str
organizationCodeOwner: str
organizationNameOwner: str
defaultLanguageCode: str
isLatestVersion: bool
isVerified: bool
license: str
licenseUrl: str
qualityAssuranceProcedure: str
@@ -135,6 +148,7 @@ class ClassPropertyContractV1(TypedDict):
name: str
uri: str
description: str
definition: str
dataType: str
dimension: str
dimensionLength: int
@@ -159,6 +173,7 @@ class ClassPropertyContractV1(TypedDict):
predefinedValue: str
propertyCode: str
propertyDictionaryName: str
propertyDictionaryUri: str
propertyUri: str
propertySet: str
propertyStatus: str
@@ -319,6 +334,23 @@ class ClassContractV1(TypedDict):
classProperties: list[ClassPropertyContractV1]
classRelations: list[ClassRelationContractV1]
childClassReferences: list[ClassReferenceContractV1]
reverseClassRelations: list[ClassReverseRelationContractV1]
hierarchy: list[HierarchyItemContractV1]
class ClassReverseRelationContractV1(TypedDict):
relationType: str
classUri: str
className: str
fraction: float
dictionaryUri: str
class HierarchyItemContractV1(TypedDict):
level: int
name: str
code: str
uri: str
class SearchInDictionaryResponseContractV1(TypedDict):
@@ -385,6 +417,11 @@ class UnitContractV1(TypedDict):
qudtUri: str
class CodeNameDto(TypedDict):
code: str
name: str
class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self):
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
+77
View File
@@ -0,0 +1,77 @@
import yaml
import sys
from pathlib import Path
from typing import Any
type_to_python_type = {
"string": "str",
"boolean": "bool",
"array": "list",
"integer": "int",
}
def get_python_type(prop_data: dict[str, Any]) -> str:
prop_type = prop_data.get("type")
if prop_type is None:
ref = format_class(prop_data["$ref"].split("/")[-1])
return ref
elif prop_type == "number" and prop_data["format"] == "double":
python_type = "float"
else:
python_type = type_to_python_type[prop_type]
if python_type == "list":
array_type = get_python_type(prop_data["items"])
return f"{python_type}[{array_type}]"
return python_type
def format_class(class_str: str) -> str:
if "." not in class_str:
return class_str
class_name, version = class_str.split(".")
return f"{class_name}{version.upper()}"
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f'Usage: python {Path(__file__).name} "path/to/bSDD OpenAPI.yaml"')
print(
".yml file available in https://github.com/buildingSMART/bSDD/blob/master/Documentation/bSDD%20OpenAPI.yaml"
)
exit()
path = sys.argv[1]
with open(path, "r") as file:
yaml_file = yaml.safe_load(file)
class_strings: dict[str, str] = {}
for schema_name, schema_data in yaml_file["components"]["schemas"].items():
props = schema_data.get("properties", {})
if not props:
continue
class_name = format_class(schema_name)
class_header = f"class {class_name}(TypedDict):"
required = schema_data.get("required", [])
props_str = ""
for prop_name, prop_data in props.items():
python_type = get_python_type(prop_data)
# if prop_name not in required:
# python_type = f"NotRequired[{python_type}]"
props_str += f" {prop_name}: {python_type}\n"
class_strings[class_header] = props_str
# Sort classes according to bsdd.py to reduce git diff noise.
bsdd_contents = Path(__file__).with_name("bsdd.py").read_text()
# Skipping not yet implemented classes for now.
filtered_classes = list(filter(lambda x: x in bsdd_contents, class_strings))
for class_header in sorted(
filtered_classes,
key=lambda x: bsdd_contents.index(x),
):
print(class_header)
print(class_strings[class_header])
print(f"{len(filtered_classes)} classes printed ({len(class_strings)-len(filtered_classes)} skipped).")