Skip to content

alluka#

A type based dependency injection framework for Python 3.9+.

Injected module-attribute #

Injected = Annotated[_T, TYPE]

Type alias used to declare a keyword argument as requiring an injected type.

If a union (e.g. typing.Union[A, B], A | B, typing.Optional[A]) is passed then each type in the union will be tried separately rather than the literal type, allowing for resolving A | B to the value set by set_type_dependency(B, ...).

If a union has None as one of its types (including Optional[T]) then None will be passed for the parameter if none of the types could be resolved using the linked client.

Note

This is a typing.Annotated alias and the behaviour for nested Annotated types may be found at the docs for it typing.Annotated.

AllukaError #

Bases: Exception

Base class for the custom errors raised by Alluka.

AsyncSelfInjecting #

Bases: AsyncSelfInjecting[_CallbackSigT]

Deprecated class for marking async functions as self-injecting.

deprecated

This is deprecated as of v0.2.0, Use Client.auto_inject_async.

__init__ #

__init__(client, callback)

Initialise a self injecting callback.

Parameters:

  • client (Client) –

    The injection client to use to resolve dependencies.

  • callback (CallbackSig) –

    The callback to make self-injecting.

    This may be sync or async.

Raises:

  • ValueError

    If callback has any injected arguments which can only be passed positionally.

BasicContext #

Bases: CachingContext

Deprecated alias of alluka.CachingContext.

deprecated

This is deprecated as of v0.3.0. use alluka.Context or alluka.CachingContext. alluka.OverridingContext should be used as a replacement for the undocumented type special casing.

call_with_async_di async #

call_with_async_di(callback, /, *args, **kwargs)

Asynchronously call a function with the current DI context.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to call.

    This may be sync or async.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

call_with_di #

call_with_di(callback, /, *args, **kwargs)

Call a function with the current DI context.

Parameters:

  • callback (Callable[..., _T]) –

    The callback to call.

    This must be sync.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

CachingContext #

Bases: Context

Basic implementation of alluka.abc.Context with callback result caching.

__init__ #

__init__(client)

Initialise a caching injection context.

Parameters:

  • client (Client) –

    The injection client this context is bound to.

call_with_async_di async #

call_with_async_di(callback, /, *args, **kwargs)

Asynchronously call a function with the current DI context.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to call.

    This may be sync or async.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

call_with_di #

call_with_di(callback, /, *args, **kwargs)

Call a function with the current DI context.

Parameters:

  • callback (Callable[..., _T]) –

    The callback to call.

    This must be sync.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

Client #

Bases: Client

Standard implementation of a dependency injection client.

This is used to track type dependencies and execute callbacks.

__init__ #

__init__(*, introspect_annotations=True)

Initialise an injector client.

auto_inject #

auto_inject(callback)

Wrap a function to make calls to it always inject dependencies.

Examples:

@client.auto_inject
def callback(dep: Injected[Type]) -> None:
    ...

callback()  # The requested dependencies will be passed.

Parameters:

  • callback (Callable[_P, _T]) –

    The callback to wrap with DI.

Returns:

  • Callable

    The wrapped auto injecting callback.

auto_inject_async #

auto_inject_async(callback)

Wrap an async function to make calls to it always inject dependencies.

Examples:

@client.auto_inject_async
async def callback(dep: Injected[Type]) -> None:
    ...

await callback()  # The requested dependencies will be passed.

Parameters:

  • callback (Callable[_P, _CoroT[_T]]) –

    The callback to wrap with DI.

Returns:

  • Callable

    The wrapped auto injecting callback.

call_with_async_di async #

call_with_async_di(callback, /, *args, **kwargs)

Call a function with async dependency injection.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to call.

    This may be sync or async.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

call_with_di #

call_with_di(callback, /, *args, **kwargs)

Call a function with sync dependency injection.

Parameters:

  • callback (Callable[..., _T]) –

    The callback to call.

    This must be sync.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

set_make_context #

set_make_context(make_context)

Set the callback used to make DI contexts for this client.

Parameters:

  • make_context (Callable[[Self], Context]) –

    Callback to use to create DI contexts.

Returns:

  • Self

    The client to enable chained calls.

Context #

Bases: Context

Basic implementation of alluka.abc.Context without caching.

__init__ #

__init__(client)

Initialise an injection context.

Parameters:

  • client (Client) –

    The injection client this context is bound to.

cache_result #

cache_result(callback, value)

Cache the result of a callback within the scope of this context.

Whether this does anything or is a noop is implementation detail.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to cache the result of.

  • value (_T) –

    The value to cache.

call_with_async_di async #

call_with_async_di(callback, /, *args, **kwargs)

Asynchronously call a function with the current DI context.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to call.

    This may be sync or async.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

call_with_di #

call_with_di(callback, /, *args, **kwargs)

Call a function with the current DI context.

Parameters:

  • callback (Callable[..., _T]) –

    The callback to call.

    This must be sync.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

get_cached_result #

get_cached_result(callback, /, *, default=_NO_VALUE)

Get the cached result of a callback.

This will always raise/default for context implementations with no caching.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to get the cached result of.

  • default (_NoValueOr[_DefaultT], default: _NO_VALUE ) –

    The default value to return if the callback is not cached.

Returns:

  • _T | _DefaultT

    The cached result of the callback if found.

    If the callback's result hasn't been cached or caching isn't implementing then this will return the value of default if it is provided.

Raises:

  • KeyError

    If no value was found when no default was provided.

InjectedDescriptor #

Bases: Generic[_T]

Descriptor used to a declare keyword-argument as requiring an injected dependency.

This is the type returned by alluka.inject.

callback instance-attribute #

callback = callback

The callback to use to resolve the parameter's value.

If this is None then this is a type dependency.

type instance-attribute #

type = type

The type to use to resolve the parameter's value.

If both this and callback are None, then this is a type dependency and the type will be inferred from the parameter's annotation.

__init__ #

__init__(*, callback=None, type=None)

Initialise an injection default descriptor.

Note

If neither type or callback is provided, an injected type will be inferred from the argument's annotation.

Parameters:

  • callback (Optional[CallbackSig[_T]], default: None ) –

    The callback to use to resolve the dependency.

    If this callback has no type dependencies then this will still work without an injection context but this can be overridden using alluka.abc.Client.set_callback_override.

  • type (Optional[_TypeT[_T]], default: None ) –

    The type of the dependency to resolve.

    If a union (e.g. typing.Union[A, B], A | B, typing.Optional[A]) is passed for type then each type in the union will be tried separately after the litarl union type is tried, allowing for resolving A | B to the value set by set_type_dependency(B, ...).

    If a union has None as one of its types (including Optional[T]) then None will be passed for the parameter if none of the types could be resolved using the linked client.

Raises:

  • ValueError

    If both callback and type are provided.

MissingDependencyError #

Bases: AllukaError

Error raised when a dependency couldn't be found.

dependency_type instance-attribute #

dependency_type = dependency_type

Type of the missing dependency.

message instance-attribute #

message = message

The error's message.

__init__ #

__init__(message, dependency_type)

Initialise a missing dependency error.

Parameters:

  • message (str) –

    The error message.

OverridingContext #

Bases: Context

Context which exists to override an existing context with special-cased type-dependencies.

Examples:

def other_callback(value: alluka.Inject[Type]) -> None:
    ...

def callback(ctx: alluka.Inject[alluka.abc.Context]) -> None:
    ctx = alluka.OverridingContext(ctx).set_type_dependency(Type, value)

    ctx.call_with_di(other_callback)
client = alluka.abc.Client().set_type_dependency(Type, value)
ctx = alluka.OverridingContext.from_client(client).set_type_dependency(OtherType, value)

__init__ #

__init__(context)

Initialise an overriding context.

While this is designed to wrap an existing context, OverridingContext.from_client can be used to create this from an alluka client.

Parameters:

  • context (Context) –

    The context to wrap.

call_with_async_di async #

call_with_async_di(callback, /, *args, **kwargs)

Asynchronously call a function with the current DI context.

Parameters:

  • callback (CallbackSig[_T]) –

    The callback to call.

    This may be sync or async.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

call_with_di #

call_with_di(callback, /, *args, **kwargs)

Call a function with the current DI context.

Parameters:

  • callback (Callable[..., _T]) –

    The callback to call.

    This must be sync.

  • *args (Any, default: () ) –

    Positional arguments to pass to the callback.

  • **kwargs (Any, default: {} ) –

    Keyword arguments to pass to the callback.

Returns:

  • _T

    The result of the callback.

Raises:

  • MissingDependencyError

    If any of the callback's required type dependencies aren't implemented by the client.

  • SyncOnlyError

    If the callback or any of its callback dependencies are async.

from_client classmethod #

from_client(client)

Create an overriding context from an injection client.

This will wrap the context returned by Client.make_context.

Parameters:

  • client (Client) –

    The alluka client to make an overriding context for.

Returns:

set_type_dependency #

set_type_dependency(type_, value)

Add a context specific type dependency.

Parameters:

  • type_ (type[_T]) –

    The type of the dependency to add an implementation for.

  • value (_T) –

    The value of the dependency.

Returns:

  • Self

    The context to allow chaining.

SelfInjecting #

Bases: SelfInjecting[_SyncCallbackT]

Deprecated class for marking functions as self-injecting.

deprecated

This is deprecated as of v0.2.0, Use Client.auto_inject.

__init__ #

__init__(client, callback)

Initialise a sync self injecting callback.

Parameters:

  • client (Client) –

    The injection client to use to resolve dependencies.

  • callback (Callable) –

    The callback to make self-injecting.

Raises:

  • ValueError

    If callback has any injected arguments which can only be passed positionally.

SyncOnlyError #

Bases: AllukaError

Error raised when trying to execute async DI in a sync context.

inject #

inject(*, callback=None, type=None)

Declare a keyword-argument as requiring an injected dependency.

This may be assigned to an argument's default value to declare injection or as a part of its Annotated metadata.

Note

If neither type nor callback is provided, an injected type will be inferred from the argument's annotation.

Examples:

async def callback(
    # Here we require an implementation of the type `Component` to be
    # injected.
    injected_type: Component = alluka.inject(type=Component)
    # Here we inject an out-of-scope callback which itself is taking
    # advantage of type injectioallukan.
    callback_result: ResultT = alluka.inject(callback=injected_callback)
) -> None:
    raise NotImplementedError

...
# where client is an `alluka.Client` instance.
result = await client.call_with_async_di(callback)

Parameters:

  • callback (Optional[CallbackSig[_T]], default: None ) –

    The callback to use to resolve the dependency.

    If this callback has no type dependencies then this will still work without an injection context but this can be overridden using alluka.abc.Client.set_callback_override.

  • type (Any, default: None ) –

    The type of the dependency to resolve.

    If a union (e.g. typing.Union[A, B], A | B, typing.Optional[A]) is passed for type then each type in the union will be tried separately rather than the literal type, allowing for resolving A | B to the value set by set_type_dependency(B, ...).

    If a union has None as one of its types (including Optional[T]) then None will be passed for the parameter if none of the types could be resolved using the linked client.

Raises:

  • ValueError

    If both type and callback are provided.