Source code for action0.service.markers
"""Marker objects used to steer injection: :py:class:`Named`, :py:class:`Ref`, ``injected``."""
from dataclasses import dataclass
from typing import Any
[docs]
@dataclass(frozen=True)
class Named:
"""Qualifier for type annotations: inject the service registered under a specific name.
Use it inside :py:data:`typing.Annotated` when several services provide
the same type and the parameter needs a particular one::
def __init__(self, db: Annotated[Database, Named("replica")]) -> None: ...
"""
name: str
"""The service name to resolve."""
[docs]
@dataclass(frozen=True)
class Ref:
"""Late-bound reference to another service, usable as a parameter value.
Put a ``Ref`` into the ``params`` mapping of a registration (or use the
``!ref`` tag in YAML) and it is replaced with the referenced service when
the depending service is built::
registry.register(ReportJob, params={"db": Ref("db.replica")})
:param key: the service name, or a type to resolve the default
implementation for.
"""
key: "str | type[Any]"
"""The service name or type to resolve when the value is needed."""
class _Injected:
"""Sentinel type for the :py:data:`injected` default value."""
def __repr__(self) -> str:
"""Return a readable placeholder for error messages and debugging."""
return "<injected>"
#: Default value marking a parameter to be filled in by
#: :py:meth:`action0.service.registry.Registry.inject`. Typed as ``Any`` so it
#: can be used as the default for a parameter of any annotated type::
#:
#: @registry.inject
#: def send_report(report: str, mailer: Mailer = injected) -> None: ...
injected: Any = _Injected()