You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 839b719
Browse filesBrowse the repository at this point in the historyBrowse files
feat: add provider.derive(fn) to inject a value computed from another provider (#733)
settings.derive(lambda s: s.db_dsn) is a provider of fn(value). Type
checkers infer s from the source. It is never cached, has no scope of its
own and resolves at its source's effective scope, so it works inline in
kwargs in any group and an override of the source reaches it. An exception
raised by fn propagates unchanged, with a note naming the derived provider.
The class is private (_Derived) and lives in providers/abstract.py,
because the derive method on AbstractProvider needs it, and a separate
module would create an import cycle.
Closes#730
Copy file name to clipboardExpand all lines: docs/migration/from-dependency-injector.md
+1-2Lines changed: 1 addition & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,7 +82,7 @@ Use this table as the index for the rest of the guide. "No direct equivalent" ro
82
82
|`Delegate` and the `Delegated*` providers (`DelegatedFactory`, `DelegatedSingleton`, ...) | A creator parameter annotated `Container`, resolving the provider later |[§4](#4-migrate-the-dependency-graph)|
83
83
|`Selector`| No direct equivalent |[§11](#11-no-direct-equivalent)|
84
84
|`Aggregate` / `FactoryAggregate`| No direct equivalent |[§11](#11-no-direct-equivalent)|
85
-
|`.provided` (attribute / item / method-call access on a provider) |No direct equivalent |[§11](#11-no-direct-equivalent)|
85
+
|`.provided` (attribute / item / method-call access on a provider) |`provider.derive(fn)`, e.g. `provider.derive(lambda value: value.attr)`|[Derived values](../providers/factories.md#derived-values)|
86
86
|`@inject` + `Provide[...]` + `container.wire(modules=[...])` (web) |`FromDI(T)` from the framework integration |[§6](#6-wiring-replacement), [§8](#8-framework-integration-and-routes)|
|`DeclarativeContainer`|`Group` (schema) + `Container(groups=[...])` (runtime), checked with `.validate()`|[§2](#2-key-conceptual-shifts)|
@@ -358,7 +358,6 @@ A handful of `dependency-injector` features have no direct port. Workarounds:
358
358
- For `ThreadLocalSingleton`, register an uncached `Factory` whose creator reads the object from a module-level `threading.local()` and creates and stores it there on a thread's first call. A cached `Factory` can't do this, because it caches one object for the whole container.
359
359
- For `Selector`, write a creator function that takes whatever the selector depended on and returns the chosen object. If the choice is static (e.g. one implementation per environment), `Alias` may be cleaner.
360
360
- For `Aggregate` / `FactoryAggregate`, resolve each candidate provider individually (by type or by reference) and dispatch on the key yourself in a small creator function, rather than injecting the whole aggregate object.
361
-
- For `.provided` (attribute / item / method-call access on a provider, e.g. `service.provided.value`), resolve the parent inside the consuming creator and access the attribute, item, or method result there, or expose a dedicated `Factory` whose creator returns just that piece.
362
361
-`modern-di` has no general-purpose injection decorator to replace `@inject` + `Provide[...]` on non-framework functions. Call `container.resolve(T)` explicitly at the call site, or expose the function through a framework integration and use `FromDI(T)`.
363
362
- Providers are not partially applied callables. In `dependency-injector`, calling a provider with extra arguments (`container.some_factory(extra_arg)`) merges them with the declared ones for that one call. `modern-di`'s `resolve()` and `resolve_provider()` take no arguments, so every creator argument must come from its type, from `kwargs`, or from a default. Move a static value into `kwargs=`. For a value that varies per call site, use a `ContextProvider` set on the container you resolve from, or a deeper-scoped dependency.
|`provider.bind(T)`|`providers.Factory(..., bound_type=T)`; add an `Alias` per extra type |[§4](#4-migrate-the-dependency-graph)|
@@ -367,7 +367,6 @@ On routes, `FromDI(T)` replaces both `fastapi.Depends(Container.provider)` and `
367
367
A handful of `that-depends` features have no direct port. Workarounds:
368
368
369
369
- For `Selector`, write a creator function that takes whatever the selector depended on and returns the chosen object. If the choice is static (e.g. one implementation per environment), `Alias` may be cleaner.
370
-
- For `AttrGetter` (`provider.attr` syntax), resolve the parent inside the consuming creator and access the attribute there, or expose a dedicated `Factory` whose creator returns the attribute.
371
370
- For `ThreadLocalSingleton`, register an uncached `Factory` whose creator reads the object from a module-level `threading.local()` and creates and stores it there on a thread's first call. A cached `Factory` can't do this, because it caches one object for the whole container.
372
371
-`modern-di` has no general-purpose injection decorator to replace `@inject` + `Provide[...]` on non-framework functions. Call `container.resolve(T)` explicitly at the call site, or expose the function through a framework integration and use `FromDI(T)`.
373
372
- For `BaseContainer.resolve(func)` and `resolver(func)`, which call `func` with its parameters filled by name, register `func` as a `Factory` with `bound_type=None` and call `container.resolve_provider(...)` on it. Its parameters are then wired by type, not by name.
0 commit comments