5.3 KiB
5.3 KiB
FastAPI source notes
Repo: fastapi/fastapi
Local checkout: /home/ubuntu/repos/rodin-sources/fastapi
Why this repo was chosen
- Core framework source plus first-party docs/tests. It is the best place to separate actual repeated FastAPI conventions from tutorial folklore.
- Especially useful here because the same patterns appear in docs examples, framework internals, and tests: router composition, dependency injection, semantic exceptions, and dependency-driven test seams.
Repeated patterns
1) App assembly is declarative: app-level and router-level configuration carry shared concerns
docs_src/bigger_applications/app_an_py310/main.py:7-18creates the app with a global dependency, then includes routers with per-router prefix/tags/dependencies/responses.docs_src/bigger_applications/app_an_py310/routers/items.py:5-10shows the same concern split one level down: the router owns prefix/tags/dependencies/common responses.fastapi/applications.py:330-348documents thatFastAPI(..., dependencies=[...])applies those dependencies to every path operation, including sub-routers.
Why chosen:
- This is not a one-off tutorial style; the public constructor explicitly supports the same pattern the docs teach.
Implication for synthesis:
- Favor centralized app/router configuration for auth headers, tags, common responses, and prefixes.
- Do not describe thin handlers as a style preference only; the framework API is built to move cross-cutting concerns out of handlers.
2) Dependencies are first-class request wiring, including teardown-aware resources
docs_src/bigger_applications/app_an_py310/dependencies.py:6-13keeps request validation in dedicated dependency callables that raise HTTP errors directly.fastapi/routing.py:95-136wraps request handling in nestedAsyncExitStacks specifically so dependency setup/teardown, includingyielddependencies, participates in request lifecycle.tests/test_dependency_security_overrides.py:24-29defines a route entirely in terms ofSecurity(...)andDepends(...)collaborators.
Why chosen:
- This combines public examples with internal lifecycle machinery. Dependencies are not sugar over helper calls; they are a core execution model.
Caveat / counterexample:
fastapi/routing.py:124-130raises aFastAPIErrorif application code swallows an exception in ayielddependency and fails to re-raise. So "just hide cleanup in a dependency" is incomplete; dependency cleanup must preserve exception flow.
Implication for synthesis:
- Prefer dependencies for auth, validated request context, DB/session access, and request-scoped resources.
- Mention that
yielddependencies are appropriate when setup/teardown must be coupled to a request.
3) Handlers and dependencies raise semantic HTTP exceptions; framework handlers translate them
docs_src/bigger_applications/app_an_py310/routers/items.py:21-25raisesHTTPException(404, ...)when an item is missing.docs_src/bigger_applications/app_an_py310/routers/items.py:28-38adds operation-specific response metadata and raisesHTTPException(403, ...)for forbidden updates.fastapi/exception_handlers.py:11-26turnsHTTPExceptionandRequestValidationErrorinto HTTP responses, including a 422 JSON body for validation failures.fastapi/exception_handlers.py:13-17also shows a subtle rule: statuses that must not include a body return a bareResponse, not JSON.
Why chosen:
- The docs examples and framework exception handlers line up exactly: route code signals semantics, framework code owns response formatting.
Implication for synthesis:
- Recommend raising semantic exceptions from route/dependency code instead of hand-building error JSON in each handler.
- Note that response-body behavior is status-sensitive and partly framework-owned.
4) Preferred test seam: override dependencies, not handler internals
tests/test_dependency_security_overrides.py:24-29keeps the route signature explicit about collaborators.tests/test_dependency_security_overrides.py:44-63replaces both ordinary dependencies and security dependencies throughapp.dependency_overrides, then resets overrides after each test.
Why chosen:
- This is a repo-level testing pattern, not an incidental example.
Caveat / counterexample:
- The reset step is part of the pattern, not cleanup fluff:
tests/test_dependency_security_overrides.py:52-63clearsapp.dependency_overrides = {}after each override-based test.
Implication for synthesis:
- When describing testing conventions, emphasize overrideable dependency seams as the intended unit of substitution.
Strong citation candidates
- Global dependencies apply across sub-routers:
fastapi/applications.py:330-348 - Dependency lifecycle is request-lifecycle machinery, not style guidance:
fastapi/routing.py:95-136 yielddependency exception-swallowing failure mode:fastapi/routing.py:124-130- Central exception translation, including no-body statuses:
fastapi/exception_handlers.py:11-17
Pattern candidates supported by this repo
- centralize cross-cutting concerns in app/router configuration
- use dependencies as the main request-wiring mechanism
- use
yielddependencies for request-scoped resources with teardown - raise semantic
HTTPExceptions from handlers/dependencies and let framework handlers shape responses - test by overriding dependencies and resetting overrides explicitly