oag-fastapi-server 0.5.1

FastAPI server stub generator for oag
Documentation

oag-fastapi-server

Python FastAPI server generator for OpenAPI 3.x specs.

Takes an IrSpec from oag-core and produces FastAPI route stubs with Pydantic v2 models.

Layout

This generator currently supports modular layout only. It produces separate files per concern:

File Description
models.py Pydantic v2 models for all schemas (request/response bodies)
routes.py FastAPI route stubs with proper type annotations
sse.py Server-Sent Events utilities using StreamingResponse
main.py FastAPI app entry point

When scaffold generation is enabled (default), these are also created:

File Description
pyproject.toml uv-compatible project config with FastAPI and uvicorn dependencies
conftest.py pytest fixture with async httpx test client (optional, scaffold.tests)
test_routes.py Per-operation pytest tests (optional, scaffold.tests)

When scaffold.tests is enabled (default), pyproject.toml includes a [dependency-groups] section (PEP 735) with pytest, pytest-asyncio, and httpx as dev dependencies. The generated tests cover:

  • Route existence (not 404)
  • Stub returns 500 (NotImplementedError)
  • Input validation returns 422 (for operations with request body)
  • Unknown path returns 404

Key features

  • Pydantic v2 models — All OpenAPI schemas are converted to Pydantic models with proper field types, descriptions, and validation
  • Type-safe routes — Every FastAPI route is fully annotated with request/response types
  • SSE streaming — Server-Sent Events endpoints use StreamingResponse with async generators (no external dependencies)
  • uv-compatiblepyproject.toml uses PEP 735 dependency groups; run with uv sync && uv run pytest
  • Absolute imports — Generated code uses absolute imports (from models import ...) so tests work without package installation
  • Stub implementation — Routes raise NotImplementedError; you fill in the business logic

Generated route structure

For a GET /pets operation, the generator produces:

@router.get("/pets", response_model=list[Pet])
async def list_pets(
    limit: int | None = Query(default=None, description="How many items to return"),
) -> list[Pet]:
    """
    List all pets
    """
    # TODO: Implement this endpoint
    raise NotImplementedError

For SSE endpoints (detected by text/event-stream content type), the generator produces:

@router.get("/chat/stream", response_class=StreamingResponse)
async def stream_chat(
    message: str = Query(..., description="The message to send"),
) -> StreamingResponse:
    """
    Stream chat responses via SSE
    """
    async def event_generator():
        # TODO: Implement your SSE logic here
        yield "data: Example event\n\n"

    return StreamingResponse(event_generator(), media_type="text/event-stream")

Depends on

  • oag-core — parser, IR, and CodeGenerator trait

Part of oag