diff --git a/README.md b/README.md index a86caae..624e837 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ uv add modern-di-flask # or: pip install modern-di-flask ## Usage -Flask has no dependency-injection system of its own, so `modern-di-flask` pairs an `@inject` decorator with inert `FromDI` markers (there is no `Depends`). `setup_di` installs a `before_request`/`teardown_appcontext` pair that builds a per-request `Scope.REQUEST` child container and closes it once the request finishes. Resolution is sync-only — the child container is closed with `close_sync()`. +Flask has no dependency-injection system of its own, so `modern-di-flask` pairs an `@inject` decorator with inert `FromDI` markers (there is no `Depends`). `setup_di` installs a `before_request`/`teardown_appcontext` pair that builds a per-request `Scope.REQUEST` child container and closes it once the request finishes. Resolution is sync-only, and the child container is closed with `close_sync()`. ```python import typing @@ -59,20 +59,20 @@ def hello(name: str, settings: typing.Annotated[Settings, FromDI(Dependencies.se return f"{settings.greeting}, {name}" -# call setup_di AFTER registering routes (required when using auto_inject) — -# it registers flask_request_provider, so validate after it rather than before container = Container(groups=[Dependencies]) setup_di(app, container) -container.validate() # optional fail-fast; flask_request_provider is registered by now +container.validate() # optional fail-fast; must come after setup_di registers its providers ``` -Pass `auto_inject=True` to `setup_di` to wire every registered view (app and blueprint routes alike) without a per-view `@inject`; because it walks `app.view_functions` at call time, `setup_di` must run after all routes are registered. `flask.Request` is resolvable within DI via the pre-built `flask_request_provider` context provider. Flask has no application-startup/shutdown hook, so the root container's shutdown is yours to own. As of modern-di 3.1 a container is **open from construction**, so no `.open()` call is needed before serving. Validation is explicit in 3.1: if you want boot-time fail-fast, call `.validate()` **after** `setup_di` (which registers `flask_request_provider`) — validating first would fail any provider with a non-optional `flask.Request` dependency, because that provider does not exist yet. Call `fetch_di_container(app).close_sync()` at your process-shutdown point; that half is still yours, since Flask has no shutdown hook to attach to. +Pass `auto_inject=True` to `setup_di` to wire every registered view (app and blueprint routes alike) without a per-view `@inject`. It walks `app.view_functions` when `setup_di` runs, so call `setup_di` after all routes are registered. `flask.Request` is resolvable within DI via the pre-built `flask_request_provider` context provider. + +A container is open from construction. To fail fast at boot, call `.validate()` after `setup_di`, which registers `flask_request_provider`. Flask has no shutdown hook, so call `fetch_di_container(app).close_sync()` at process shutdown. ## API | Symbol | Description | |---|---| -| `setup_di(app, container, *, auto_inject=False)` | Registers the container on `app.extensions`, installs the `before_request`/`teardown_appcontext` pair that builds and closes a per-request `Scope.REQUEST` child, and — if `auto_inject=True` — wraps every currently-registered view with `inject`; returns the container | +| `setup_di(app, container, *, auto_inject=False)` | Registers the container on `app.extensions`, installs the `before_request`/`teardown_appcontext` pair that builds and closes a per-request `Scope.REQUEST` child, and, if `auto_inject=True`, wraps every currently registered view with `inject`; returns the container | | `FromDI(dependency)` | Inert marker (used with `@inject`) that resolves a provider or type from the per-request child container | | `inject(view)` | Decorator for a view function; resolves its `FromDI`-annotated parameters without rewriting the function's signature. Raises `RuntimeError` naming `setup_di` when a request reaches it without `setup_di` called | | `fetch_di_container(app)` | Returns the root `Container` stored on `app.extensions` | @@ -84,7 +84,7 @@ Pass `auto_inject=True` to `setup_di` to wire every registered view (app and blu ## Part of `modern-python` -Built on [`modern-di`](https://github.com/modern-python/modern-di), a dependency-injection framework with IoC container and scopes. +Built on [`modern-di`](https://github.com/modern-python/modern-di), a dependency-injection framework with an IoC container and scopes. Browse the full list of templates and libraries in -[`modern-python`](https://github.com/modern-python) — see the org profile for the categorized index. +[`modern-python`](https://github.com/modern-python); the org profile has the categorized index.