linkd.solver

class AutoInjecting(func: Callable[..., Awaitable[t.Any]], self_: t.Any = None, _cached_pos_or_kw_params: list[tuple[str, t.Any]] | None = None, _cached_kw_only_params: dict[str, t.Any] | None = None)[source]

Wrapper for a callable that implements dependency injection. When called, resolves the required dependencies and calls the original callable. Supports both synchronous and asynchronous functions, however this cannot be called synchronously - synchronous functions will need to be awaited.

You should generally never have to instantiate this yourself - you should instead use one of the decorators that applies this to the target automatically.

See also

with_di()

class DependencyInjectionManager[source]

Class which contains dependency injection functionality.

async close() None[source]

Close the default dependency injection context. This must be called if you wish the teardown functions for any dependencies registered for the default registry to be called.

Returns:

None

enter_context(context: context_.Context = 'linkd.contexts.default', /) AsyncIterator[Container][source]

Context manager that ensures a dependency injection context is available for the nested operations.

Parameters:

context – The context to enter. If a container for the given context already exists, it will be returned and a new container will not be created.

Yields:

Container – The container that has been entered.

Example

# Enter a specific context ('manager' is your DependencyInjectionManager instance)
async with manager.enter_context(linkd.Contexts.DEFAULT):
    await some_function_that_needs_dependencies()

Note

If you want to enter multiple contexts - i.e. a command context that requires the default context to be available first - you should call this once for each context that is needed.

async with (
    manager.enter_context(linkd.Contexts.DEFAULT),
    manager.enter_context(SOME_COMMAND_CONTEXT)
):
    ...
registry_for(context: Context, /) Registry[source]

Get the dependency registry for the given context. Creates one if necessary.

Parameters:

context – The injection context to get the registry for.

Returns:

The dependency registry for the given context.

property default_container: Container | None

The container being used to provide dependencies for the DEFAULT context. This will be None until the first time any injection context is entered.

with_di(func: AsyncFnT) AsyncFnT[source]
with_di(func: Callable[P, R]) Callable[P, Coroutine[t.Any, t.Any, R]]

Decorator that enables dependency injection on the decorated function. If dependency injection has been disabled globally then this function does nothing and simply returns the object that was passed in.

Parameters:

func – The function to enable dependency injection for.

Returns:

The function with dependency injection enabled, or the same function if DI has been disabled globally.

Warning

Dependency injection relies on a context being available when the function is called. Refer to library documentation for which flows will have a dependency injection context set-up for you automatically. Otherwise, you will have to set up the context yourself using the helper context manager enter_context().

INJECTED: Final[Any] = <linkd.Marker: 'INJECTED'>

Flag value used to explicitly mark that a function parameter should be dependency-injected.

This exists to stop type checkers complaining that function arguments are not provided when calling dependency-injection enabled functions.

Example

@linkd.with_di
async def foo(bar: SomeClass = linkd.INJECTED) -> None:
    ...

# Type-checker shouldn't error that a parameter is missing
await foo()