ResolverContext¶
What you’ll learn¶
Use
diwire.resolver_contextto avoid passingContainereverywhere.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()