""" FastAPI OpenAPI First — strict OpenAPI-first application bootstrap for FastAPI. FastAPI OpenAPI First is a **contract-first infrastructure library** that enforces OpenAPI as the single source of truth for FastAPI services. The library removes decorator-driven routing and replaces it with deterministic, spec-driven application assembly. Every HTTP route, method, and operation is defined in OpenAPI first and bound to Python handlers explicitly via operationId. The package is intentionally minimal and layered. Each module has a single responsibility and exposes explicit contracts rather than convenience facades. ---------------------------------------------------------------------- Architecture Overview ---------------------------------------------------------------------- The library is structured around three core responsibilities: - loader: load and validate OpenAPI 3.x specifications (JSON/YAML) - binder: bind OpenAPI operations to FastAPI routes via operationId - app: OpenAPI-first FastAPI application bootstrap - errors: explicit error hierarchy for contract violations The package root acts as a **namespace**, not a facade. Consumers are expected to import functionality explicitly from the appropriate module. ---------------------------------------------------------------------- Installation ---------------------------------------------------------------------- Install using pip: pip install fastapi-openapi-first Or with Poetry: poetry add fastapi-openapi-first Runtime dependencies are intentionally minimal: - fastapi - openapi-spec-validator - pyyaml (optional, for YAML specs) The ASGI server (e.g., uvicorn) is an application-level dependency and is not bundled with this library. ---------------------------------------------------------------------- Basic Usage ---------------------------------------------------------------------- Minimal OpenAPI-first FastAPI application: from fastapi_openapi_first import app import my_service.routes as routes api = app.OpenAPIFirstApp( openapi_path="openapi.json", routes_module=routes, title="My Service", version="1.0.0", ) # Run with: # uvicorn my_service.main:api Handler definitions (no decorators): def get_health(): return {"status": "ok"} OpenAPI snippet: paths: /health: get: operationId: get_health responses: "200": description: OK ---------------------------------------------------------------------- Extensibility Model ---------------------------------------------------------------------- FastAPI OpenAPI First is designed to be extended via **explicit contracts**: - Users MAY extend OpenAPI loading behavior (e.g. multi-file specs) by wrapping or replacing `loader.load_openapi` - Users MAY extend route binding behavior by building on top of `binder.bind_routes` - Users MAY layer additional validation (e.g. signature checks) without modifying core modules Users SHOULD NOT rely on FastAPI decorators for routing when using this library. Mixing decorator-driven routes with OpenAPI-first routing defeats the contract guarantees and is explicitly unsupported. ---------------------------------------------------------------------- Public API Surface ---------------------------------------------------------------------- The supported public API consists of the following top-level modules: - fastapi_openapi_first.app - fastapi_openapi_first.binder - fastapi_openapi_first.loader - fastapi_openapi_first.errors Classes and functions should be imported explicitly from these modules. No individual symbols are re-exported at the package root. ---------------------------------------------------------------------- Design Guarantees ---------------------------------------------------------------------- - OpenAPI is the single source of truth - No undocumented routes can exist - No OpenAPI operation can exist without a handler - All contract violations fail at application startup - No hidden FastAPI magic or implicit behavior - Deterministic, testable application assembly - CI-friendly failure modes FastAPI OpenAPI First favors correctness, explicitness, and contract enforcement over convenience shortcuts. """ from . import app from . import binder from . import loader from . import errors __all__ = [ "app", "binder", "loader", "errors", ]