Skip to content

Resolver module

tidi.resolver

Finds or creates dependency instances based on availability and options.

DependencyResolutionError

Bases: Exception

Unable to resolve dependency

Source code in src/tidi/resolver.py
class DependencyResolutionError(Exception):
    """Unable to resolve dependency"""

ResolverOptions dataclass

Options that control how resolving is done.

Parameters:

Name Type Description Default
use_registry bool

whether to try using the registry or not.

required
initialise_missing bool

whether to try to initialise the dependency or not.

required
Source code in src/tidi/resolver.py
@dataclass(frozen=True)
class ResolverOptions:
    """Options that control how resolving is done.

    Args:
        use_registry (bool): whether to try using the registry or not.
        initialise_missing (bool): whether to try to initialise the dependency or not.

    """

    use_registry: bool
    initialise_missing: bool

resolve_dependency(type_, resolver_options, registry=None, provider=None)

Returns a dependency according to configured options.

Parameters:

Name Type Description Default
type_ Type[T]

the type of the dependency being looked for.

required
resolver_options ResolverOptions

options dictating how to resolve the dependency.

required
registry Registry | None

an optional registry containing the dependency. Defaults to None.

None
provider Callable[..., T] | Callable[..., AbstractContextManager[T]] | None

(t.Callable[..., T] | typing.Callable[..., contextlib.AbstractContextManager[T]] | None): an optional context manager function that returns the dependency. Defaults to None.

None

Raises:

Type Description
DependencyResolutionError

if a registry is required but not provided

DependencyResolutionError

if the function doesn't know how to handle the situation

Returns:

Type Description
type requested (T)

an instance of the dependency requested.

Source code in src/tidi/resolver.py
@contextlib.contextmanager
def resolve_dependency(
    type_: t.Type[T],
    resolver_options: ResolverOptions,
    registry: Registry | None = None,
    provider: t.Callable[..., T]
    | t.Callable[..., contextlib.AbstractContextManager[T]]
    | None = None,
) -> t.Iterator[T]:
    """Returns a dependency according to configured options.

    Args:
        type_ (typing.Type[T]): the type of the dependency being looked for.
        resolver_options (ResolverOptions): options dictating how to resolve
            the dependency.
        registry (Registry | None, optional): an optional registry containing
            the dependency. Defaults to None.
        provider: (t.Callable[..., T] | typing.Callable[..., contextlib.AbstractContextManager[T]] | None):
            an optional context manager function that returns the dependency.
            Defaults to None.

    Raises:
        DependencyResolutionError: if a registry is required but not provided
        DependencyResolutionError: if the function doesn't know how to handle the situation

    Returns:
        (type requested (T)): an instance of the dependency requested.
    """
    match resolver_options:
        case ResolverOptions(use_registry=True, initialise_missing=False) if registry is not None:
            yield registry.get(type_)
        case ResolverOptions(use_registry=True, initialise_missing=False) if registry is None:
            raise DependencyResolutionError("Registry required but not provided.")
        case ResolverOptions(use_registry=True, initialise_missing=True) if registry is not None:
            obj = registry.get(type_, None)
            if obj is not None:
                yield obj
            else:
                yield from _initialise_dependency(type_, provider)
        case ResolverOptions(initialise_missing=True) if registry is None:
            yield from _initialise_dependency(type_, provider)
        case _:
            raise DependencyResolutionError("Unable to resolve dependency.")