55 lines
1.6 KiB
Python
55 lines
1.6 KiB
Python
#!/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()) |