#!/usr/bin/env python """Generate openapi.json from the routers in {root}/src/routers/*. Usage (from anywhere, with the build's venv): python scripts/dump_openapi.py [--src SRC] [--out OUT] [--title TITLE] """ import argparse import importlib import json import pkgutil import sys from pathlib import Path from fastapi import APIRouter, FastAPI ROOT = Path(__file__).resolve().parent.parent def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--src", type=Path, default=ROOT / "src") parser.add_argument("--out", type=Path, default=ROOT / "openapi.json") parser.add_argument("--title", default=ROOT.name) args = parser.parse_args() src = args.src.resolve() routers_dir = src / "routers" if not routers_dir.is_dir(): print(f"No routers directory found at {routers_dir}", file=sys.stderr) return 1 # Makes `import models`, `import routers.x` and similar work sys.path.insert(0, str(src)) app = FastAPI(title=args.title) seen = set() for mod_info in pkgutil.walk_packages([str(routers_dir)], prefix="routers."): if mod_info.ispkg: continue module = importlib.import_module(mod_info.name) for obj in vars(module).values(): # Only include routers defined in this module, not ones it merely imports if isinstance(obj, APIRouter) and id(obj) not in seen: seen.add(id(obj)) app.include_router(obj) # Write straight to the file so stray prints during import can't corrupt the JSON args.out.write_text(json.dumps(app.openapi(), indent=2), encoding="utf-8") print(f"Wrote {args.out} ({len(seen)} routers)") return 0 if __name__ == "__main__": sys.exit(main())