ResolverContext

What you’ll learn

  • Use diwire.resolver_context to avoid passing Container everywhere.

  • Understand binding behavior and explicit resolver requirements.

Unbound error

Run locally

uv run python examples/ex_10_resolver_context/01_unbound_error.py
"""Focused example: unbound ``ResolverContext`` usage error."""

from __future__ import annotations

from diwire import ResolverContext
from diwire.exceptions import DIWireResolverNotSetError


def main() -> None:
    context = ResolverContext()

    try:
        context.resolve(str)
    except DIWireResolverNotSetError as error:
        print(f"unbound_error={type(error).__name__}")  # => unbound_error=DIWireResolverNotSetError


if __name__ == "__main__":
    main()

Bound resolution

Run locally

uv run python examples/ex_10_resolver_context/02_bound_resolution.py
"""Focused example: bound resolver resolution through ResolverContext."""

from __future__ import annotations

from dataclasses import dataclass

from diwire import Container, ResolverContext


@dataclass(slots=True)
class Service:
    value: str


def main() -> None:
    context = ResolverContext()
    container = Container(resolver_context=context)
    container.add_instance(Service("bound"), provides=Service)

    with container.compile():
        resolved = context.resolve(Service)
        print(f"bound_resolve_ok={resolved.value == 'bound'}")  # => bound_resolve_ok=True


if __name__ == "__main__":
    main()

Inject wrappers

Run locally

uv run python examples/ex_10_resolver_context/03_inject_wrappers.py
"""Focused example: ``@resolver_context.inject`` on function and method."""

from __future__ import annotations

from dataclasses import dataclass

from diwire import Container, Injected, resolver_context


@dataclass(slots=True)
class Message:
    value: str


def main() -> None:
    container = Container()
    container.add_instance(Message(value="context-message"), provides=Message)

    @resolver_context.inject
    def read_function(message: Injected[Message]) -> str:
        return message.value

    class Handler:
        @resolver_context.inject
        def read_method(self, message: Injected[Message]) -> str:
            return message.value

    handler = Handler()

    print(
        f"inject_function_ok={read_function() == 'context-message'}"
    )  # => inject_function_ok=True
    print(
        f"inject_method_ok={handler.read_method() == 'context-message'}"
    )  # => inject_method_ok=True


if __name__ == "__main__":
    main()

use_resolver_context=False

Run locally

uv run python examples/ex_10_resolver_context/04_use_resolver_context_false.py
"""Focused example: ``use_resolver_context=False`` inject requires explicit resolver."""

from __future__ import annotations

from dataclasses import dataclass

from diwire import (
    Container,
    DependencyRegistrationPolicy,
    Injected,
    MissingPolicy,
    ResolverContext,
    Scope,
)
from diwire.exceptions import DIWireResolverNotSetError


@dataclass(slots=True)
class Message:
    value: str


def _bound_self(method: object) -> object | None:
    return getattr(method, "__self__", None)


def main() -> None:
    context = ResolverContext()
    container = Container(
        missing_policy=MissingPolicy.ERROR,
        dependency_registration_policy=DependencyRegistrationPolicy.IGNORE,
        resolver_context=context,
        use_resolver_context=False,
    )
    container.add_instance(Message("legacy"), provides=Message)

    @context.inject(scope=Scope.REQUEST)
    def read_message(message: Injected[Message]) -> str:
        return message.value

    print(
        f"fallback_resolve_ok={context.resolve(Message).value == 'legacy'}"
    )  # => fallback_resolve_ok=True

    try:
        read_message()
    except DIWireResolverNotSetError as error:
        print(
            f"inject_missing_explicit_error={type(error).__name__}"
        )  # => inject_missing_explicit_error=DIWireResolverNotSetError

    with container.enter_scope(Scope.REQUEST) as request_scope:
        print(
            f"inject_explicit_ok={read_message(diwire_resolver=request_scope) == 'legacy'}"
        )  # => inject_explicit_ok=True

    compiled = container.compile()
    print(f"rebind_enabled={_bound_self(container.resolve) is compiled}")  # => rebind_enabled=True


if __name__ == "__main__":
    main()