Initial extracted documentation set

This commit is contained in:
Rodin
2026-06-01 21:42:05 +00:00
commit a23e494026
16 changed files with 1414 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
# Starlette source notes
Repo: `encode/starlette`
Local checkout: `/home/ubuntu/repos/rodin-sources/starlette`
## Why this repo was chosen
- FastAPI inherits key runtime behavior from Starlette. Starlette is the right source for conventions around app assembly, middleware ordering, lifespan, and request state.
- Valuable here because it distinguishes framework guarantees from habits that only appear in sample apps.
## Repeated patterns
### 1) App construction keeps routing, middleware, exception handlers, and lifespan as separate inputs
- `starlette/applications.py:22-55` defines the constructor with distinct parameters for routes, middleware, exception handlers, and lifespan.
- `tests/test_applications.py:139-157` builds one app by explicitly passing routes, exception handlers, middleware, and lifespan together.
Why chosen:
- This separation exists both in the public constructor and in the main integration-style test app.
Implication for synthesis:
- Treat app assembly concerns as separate layers; do not blur middleware, routing, error handling, and startup resources into one module-level setup blob.
### 2) Middleware ordering is intentional and framework-enforced
- `starlette/applications.py:35-40` documents that `ServerErrorMiddleware` is outermost and `ExceptionMiddleware` innermost.
- `starlette/applications.py:68-77` shows the actual stack construction: framework error middleware, then user middleware, then framework exception middleware around the router.
- `starlette/applications.py:98-101` forbids adding middleware after the application has started.
Why chosen:
- This is stronger than a docs recommendation; it is constructor/runtime behavior.
Caveat / counterexample:
- User middleware is not the whole stack. If a synthesized convention says "middleware runs in the order you add it," that is incomplete because Starlette wraps user middleware with framework-owned layers.
Implication for synthesis:
- When discussing middleware order, mention Starlette's outer/inner framework layers explicitly.
- Avoid recommendations that rely on mutating middleware after startup.
### 3) Lifespan is the preferred resource boundary, and `asynccontextmanager` is the clearest shape
- `starlette/applications.py:46-48` says lifespan replaces `on_startup`/`on_shutdown`; use one style or the other, not both.
- `tests/test_applications.py:394-409` shows the preferred shape: an `@asynccontextmanager` lifespan marks startup before `yield` and cleanup after `yield`, with both verified by entering/exiting the client context.
- `tests/test_applications.py:108-114` defines lifespan state by yielding `{"count": 1}`.
- `tests/test_applications.py:241-244` verifies request handlers can consume that state via `request.state`.
Why chosen:
- This combines constructor guidance with working tests for startup/cleanup and state propagation.
Caveat / counterexample:
- `tests/test_applications.py:421-459` still supports async/sync generator lifespan forms, but those tests are under a deprecation-warning filter. For future-facing synthesis, prefer `@asynccontextmanager`, not raw generator lifespans.
Implication for synthesis:
- Recommend lifespan for DB pools, clients, caches, and other app resources.
- Note that lifespan can yield structured state for handlers instead of relying on import-time globals.
## Strong citation candidates
- Constructor-level separation of app assembly concerns: `starlette/applications.py:22-55`
- Middleware stack ordering is framework-defined: `starlette/applications.py:68-77`
- Cannot add middleware after startup: `starlette/applications.py:98-101`
- Lifespan replaces startup/shutdown hooks: `starlette/applications.py:46-48`
- Preferred `@asynccontextmanager` lifespan behavior: `tests/test_applications.py:394-409`
## Pattern candidates supported by this repo
- separate routes, middleware, exception handlers, and lifespan at app assembly time
- preserve middleware ordering intentionally, including framework-owned outer/inner layers
- prefer lifespan over startup/shutdown hooks for resource management
- use lifespan-yielded state instead of import-time globals for app-scoped data