Files
IfcOpenShell/src/bsdd/yml_to_classes.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

78 lines
2.5 KiB
Python
Raw Normal View History

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).")