Add swagger-drogon generator
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from .models import Route
|
||||
|
||||
|
||||
ROUTE_RE = re.compile(
|
||||
r"ADD_METHOD_TO\(\s*([A-Za-z_]\w*)::([A-Za-z_]\w*)\s*,\s*"
|
||||
r'"([^"]+)"\s*,\s*drogon::([A-Za-z]+)\s*\)',
|
||||
re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
|
||||
REQUIRED_METADATA = {"tags", "summary", "description", "auth", "body", "response"}
|
||||
|
||||
|
||||
def parse_metadata(header: Path, text: str, route_start: int) -> dict[str, str]:
|
||||
prefix = text[:route_start].rstrip()
|
||||
if not prefix.endswith("*/"):
|
||||
raise ValueError(f"{header}: route is missing an openapi metadata block")
|
||||
|
||||
comment_start = prefix.rfind("/*")
|
||||
if comment_start == -1:
|
||||
raise ValueError(f"{header}: route is missing an openapi metadata block")
|
||||
|
||||
block = prefix[comment_start + 2:-2]
|
||||
metadata: dict[str, str] = {}
|
||||
in_openapi_block = False
|
||||
|
||||
for raw_line in block.splitlines():
|
||||
line = raw_line.strip()
|
||||
if line.startswith("*"):
|
||||
line = line[1:].strip()
|
||||
if not line:
|
||||
continue
|
||||
if line == "openapi:":
|
||||
in_openapi_block = True
|
||||
continue
|
||||
if not in_openapi_block:
|
||||
continue
|
||||
|
||||
match = re.match(r"([A-Za-z_]+):\s*(.+)", line)
|
||||
if match:
|
||||
metadata[match.group(1)] = match.group(2).strip()
|
||||
|
||||
missing = sorted(REQUIRED_METADATA - metadata.keys())
|
||||
if missing:
|
||||
names = ", ".join(missing)
|
||||
raise ValueError(f"{header}: openapi metadata block is missing: {names}")
|
||||
|
||||
return metadata
|
||||
|
||||
|
||||
def parse_routes(controllers_dir: Path) -> list[Route]:
|
||||
routes: list[Route] = []
|
||||
for header in sorted(controllers_dir.glob("*.h")):
|
||||
text = header.read_text(encoding="utf-8")
|
||||
for match in ROUTE_RE.finditer(text):
|
||||
controller, handler, raw_path, drogon_method = match.groups()
|
||||
routes.append(
|
||||
Route(
|
||||
controller=controller,
|
||||
handler=handler,
|
||||
raw_path=raw_path,
|
||||
http_method=drogon_method.lower(),
|
||||
metadata=parse_metadata(header, text, match.start()),
|
||||
header=header,
|
||||
)
|
||||
)
|
||||
return routes
|
||||
|
||||
|
||||
def parse_tags(value: str) -> list[str]:
|
||||
return [tag.strip() for tag in value.split(",") if tag.strip()]
|
||||
Reference in New Issue
Block a user