Resolve all components¶
What you’ll learn¶
Collect a tuple of implementations with
All[T](base + named components).Preserve deterministic ordering by registration slot.
Run locally¶
uv run python examples/ex_22_all_components/01_all_components.py
Example¶
"""Resolve all implementations with ``All[T]`` (base + components).
This module demonstrates how to collect a plugin stack by combining:
- the plain registration for a base type ``T`` (if present), and
- all component registrations keyed as ``Annotated[T, Component(...)]``.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Annotated, Protocol, TypeAlias
from diwire import All, Component, Container, Injected, resolver_context
class EventHandler(Protocol):
def handle(self, event: str) -> str: ...
@dataclass(frozen=True, slots=True)
class BaseHandler:
def handle(self, event: str) -> str:
return f"base:{event}"
@dataclass(frozen=True, slots=True)
class LoggingHandler:
def handle(self, event: str) -> str:
return f"logging:{event}"
@dataclass(frozen=True, slots=True)
class MetricsHandler:
def handle(self, event: str) -> str:
return f"metrics:{event}"
Logging: TypeAlias = Annotated[EventHandler, Component("logging")]
Metrics: TypeAlias = Annotated[EventHandler, Component("metrics")]
def main() -> None:
container = Container()
container.add(BaseHandler, provides=EventHandler)
container.add(LoggingHandler, provides=Logging)
container.add(MetricsHandler, provides=Metrics)
handlers = container.resolve(All[EventHandler])
print(
[handler.handle("evt") for handler in handlers],
) # => ['base:evt', 'logging:evt', 'metrics:evt']
@resolver_context.inject
def dispatch(event: str, handlers: Injected[All[EventHandler]]) -> tuple[str, ...]:
return tuple(handler.handle(event) for handler in handlers)
print(dispatch("evt")) # => ('base:evt', 'logging:evt', 'metrics:evt')
if __name__ == "__main__":
main()