Apply as a decorator
Warning
When using the provided integrations, this is automatically handled for you. Only use this if you're injecting Wireup dependencies in a framework without an integration.
Instead of retrieving services via container.get
or parameters via container.params
, you can inject them by applying the container as a decorator.
The goal is to go from this:
def awesome_function() -> None:
random = container.get(RandomService)
env_name = container.params.get("env")
with container.enter_scope() as scoped_container:
scoped_service = scoped_container.get(ScopedService)
To having the dependencies injected directly into the function.
Implementation¶
Wireup provides a decorator called wireup.inject_from_container
.
The container will enter a scope before executing the function, inject all dependencies and exit the scope once the function returns.
Warning
When injecting on decorated functions, the container will only interact with parameters annotated with Injected[T]
or Annotated[T, Inject()]
(the two are equivalent, Injected[T]
is only an alias).
from wireup import Injected
@wireup.inject_from_container(container)
def awesome_function(
service: Injected[RandomService],
scoped_service: Injected[ScopedService],
env_name: Annotated[str, Inject(param="env")]
) -> None: ...
If you have already created a scoped container elsewhere, you can supply a callable that returns it as the second argument. Wireup will use that and not enter a new scope.
scoped_container: ContextVar[ScopedSyncContainer] = ContextVar("scoped_container")
@wireup.inject_from_container(container, scoped_container.get)
def awesome_function(
service: Injected[RandomService],
scoped_service: Injected[ScopedService],
env_name: Annotated[str, Inject(param="env")]
) -> None: ...
You can also alias the decorator for a cleaner look.
scoped_container: ContextVar[ScopedSyncContainer] = ContextVar("scoped_container")
injected = wireup.inject_from_container(container, scoped_container.get)
@injected
def awesome_function(
service: Injected[RandomService],
scoped_service: Injected[ScopedService],
env_name: Annotated[str, Inject(param="env")]
) -> None: ...
Good to know¶
- This function works with both sync and async containers.
- To inject
async def
functions you need an async container created viawireup.create_async_contaier
.
Function documentation¶
wireup.inject_from_container
¶
Inject dependencies into the decorated function based on annotations.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
container |
SyncContainer | AsyncContainer
|
The main container instance created via |
required |
scoped_container_supplier |
Callable[[], ScopedSyncContainer | ScopedAsyncContainer] | None
|
An optional callable that returns the current scoped container instance. If provided, it will be used to create scoped dependencies. If not provided, the container will automatically enter a scope. Provide a scoped_container_supplier if you need to manage the container's scope manually. For example, in web frameworks, you might enter the scope at the start of a request in middleware so that other middlewares can access the scoped container if needed. |
None
|