65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""Export the composed HTTP API schema without touching the operator's data root."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import tempfile
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from gewu.bootstrap.app import create_local_app
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DESTINATION = ROOT / "schema" / "v1" / "openapi.json"
|
|
|
|
|
|
def componentize_record_schema(
|
|
name: str, record_schema: dict[str, Any], components: dict[str, Any]
|
|
) -> None:
|
|
definitions = record_schema.pop("$defs", {})
|
|
|
|
def rewrite_local_refs(value: Any) -> Any:
|
|
if isinstance(value, list):
|
|
return [rewrite_local_refs(item) for item in value]
|
|
if not isinstance(value, dict):
|
|
return value
|
|
rewritten = {key: rewrite_local_refs(item) for key, item in value.items() if key != "$defs"}
|
|
reference = rewritten.get("$ref")
|
|
if isinstance(reference, str) and reference.startswith("#/$defs/"):
|
|
definition_name = reference.removeprefix("#/$defs/")
|
|
rewritten["$ref"] = f"#/components/schemas/{name}__{definition_name}"
|
|
return rewritten
|
|
|
|
for definition_name, definition in definitions.items():
|
|
component_name = f"{name}__{definition_name}"
|
|
components.setdefault(component_name, rewrite_local_refs(definition))
|
|
components.setdefault(name, rewrite_local_refs(record_schema))
|
|
|
|
|
|
def main() -> None:
|
|
previous_data_root = os.environ.get("GEWU_DATA_ROOT")
|
|
with tempfile.TemporaryDirectory(prefix="gewu-openapi-") as temporary:
|
|
os.environ["GEWU_DATA_ROOT"] = str(Path(temporary) / "data")
|
|
try:
|
|
schema: dict[str, Any] = create_local_app().openapi()
|
|
finally:
|
|
if previous_data_root is None:
|
|
os.environ.pop("GEWU_DATA_ROOT", None)
|
|
else:
|
|
os.environ["GEWU_DATA_ROOT"] = previous_data_root
|
|
schema_components = schema.setdefault("components", {}).setdefault("schemas", {})
|
|
for record_schema in sorted((ROOT / "schema" / "v1" / "records").glob("*.schema.json")):
|
|
component_name = record_schema.name.removesuffix(".schema.json")
|
|
schema_value = json.loads(record_schema.read_text(encoding="utf-8"))
|
|
componentize_record_schema(component_name, schema_value, schema_components)
|
|
DESTINATION.parent.mkdir(parents=True, exist_ok=True)
|
|
DESTINATION.write_text(
|
|
json.dumps(schema, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|