docs.py
1 from typing import Any, Type, cast 2 3 from pydantic import BaseConfig, BaseModel 4 from uvicorn.protocols.http.h11_impl import STATUS_PHRASES 5 6 from ..exceptions.api_exception import APIException 7 8 9 def responses(default: type, *args: Type[APIException]) -> dict[int | str, dict[str, Any]]: 10 exceptions: dict[int, list[Type[APIException]]] = {} 11 for exc in args: 12 exceptions.setdefault(exc.status_code, []).append(exc) 13 14 out: dict[int | str, dict[str, Any]] = {} 15 for code, excs in exceptions.items(): 16 examples = {} 17 for i, exc in enumerate(excs): 18 name = exc.__name__ if len(excs) == 1 else f"{exc.__name__} ({i + 1}/{len(excs)})" 19 examples[name] = {"description": exc.description, "value": {"detail": exc.detail}} 20 21 out[code] = {"description": STATUS_PHRASES[code], "content": {"application/json": {"examples": examples}}} 22 23 return out | {200: {"model": default}} 24 25 26 def get_example(arg: Type[BaseModel]) -> dict[str, Any]: 27 return cast(dict[str, dict[str, Any]], arg.Config.schema_extra)["example"] 28 29 30 def example(*args: Type[BaseModel], **kwargs: Any) -> Type[BaseConfig]: 31 ex = dict(e for arg in args for e in get_example(arg).items()) 32 return cast(Type[BaseConfig], type("Config", (BaseConfig,), {"schema_extra": {"example": ex | kwargs}})) 33 34 35 def add_endpoint_links_to_openapi_docs(openapi_schema: dict[str, Any]) -> None: 36 anchors: dict[str, str] = { 37 f"{method.upper()} {name}": f"docs#/{route['tags'][0]}/{route['operationId']}" 38 for name, path in openapi_schema["paths"].items() 39 for method, route in path.items() 40 } 41 42 def replace(text: str) -> str: 43 for endpoint, anchor in anchors.items(): 44 text = text.replace(f"`{endpoint}`", f"[`{endpoint}`]({anchor})") 45 return text 46 47 def add_links(schema: Any) -> Any: 48 if isinstance(schema, dict): 49 for k, v in schema.items(): 50 schema[k] = add_links(v) 51 elif isinstance(schema, list): 52 for i, v in enumerate(schema): 53 schema[i] = add_links(v) 54 elif isinstance(schema, str): 55 schema = replace(schema) 56 return schema 57 58 add_links(openapi_schema)