Di
Shared dependency injection primitives.
Consumers (the event bus, and future consumers like the scheduler) use this package to inspect handler/predicate signatures, build an injection plan, and resolve kwargs at dispatch time - without needing to know about each other's source types.
See design/specs/004-extract-event-handling-di/design.md for the full architecture.
CallableInvoker
dataclass
Resolves a dependency injection plan into kwargs at call time.
Does not store or call the target callable - the caller is responsible for invoking the target with the resolved kwargs. This keeps the shared layer agnostic to how (or whether) the target is sync/async, a function, or a bound method.
Source code in src/hassette/di/invoker.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
invoke(available: dict[type, Any]) -> dict[str, Any]
Build kwargs for the target callable from available source objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
available
|
dict[type, Any]
|
Maps a source type to the live object of that type, e.g.
|
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If a param's |
Source code in src/hassette/di/invoker.py
20 21 22 23 24 25 26 27 28 29 30 | |
AnnotatedMatcher
dataclass
Matches Annotated[T, metadata] parameters.
metadata may be an AnnotationDetails instance or a bare callable extractor - bare
callables are auto-wrapped into AnnotationDetails(extractor=metadata). Any other
metadata shape emits a warning and is treated as a non-match.
Source code in src/hassette/di/matchers.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
TypeMatcher
dataclass
Matches parameters whose (unwrapped) annotation is match_type or a subclass of it.
Parameterized generics (e.g. Event[Any]) are unwrapped to their origin before the
subclass check, matching the behavior of hassette.events.type_checks.is_event_type.
Source code in src/hassette/di/matchers.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
AnnotationDetails
dataclass
Bases: Generic[T]
Details about an annotation used for dependency injection.
Source code in src/hassette/di/types.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
extractor: Callable[[T], Any]
instance-attribute
Function to extract the dependency from the source object.
converter: Callable[[Any, Any], Any] | None = None
class-attribute
instance-attribute
Optional converter function to convert the extracted value to the desired type.
source_type: type[T] | None = None
class-attribute
instance-attribute
The source type this extractor operates on, e.g. Event or ScheduledJob.
When None, the consuming matcher (e.g. AnnotatedMatcher) falls back to its own
constructor-provided source_type. Set this to override the matcher's default on a
per-annotation basis - for example, an extractor that reads from StateManager
alongside other Event-sourced extractors on the same handler.
InjectionParam
dataclass
One parameter's resolved injection plan.
Produced by a ParameterMatcher during plan building (build_injection_plan) and
consumed by CallableInvoker.invoke at dispatch time.
Source code in src/hassette/di/types.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
name: str
instance-attribute
The parameter name on the target callable.
source_type: type
instance-attribute
Key to look up in the available dict passed to CallableInvoker.invoke.
target_type: Any
instance-attribute
The annotation's type, e.g. LightState - used by consumers that convert the
extracted value (the shared layer itself does not convert).
extractor: Callable[[Any], Any]
instance-attribute
Function that pulls the value out of the source object.
converter: Callable[[Any, Any], Any] | None = None
class-attribute
instance-attribute
Optional converter carried through from AnnotationDetails.converter.
ParameterMatcher
Bases: Protocol
Protocol for matching a single inspect.Parameter to an InjectionParam.
Implementations inspect a parameter's annotation and return an InjectionParam when
they recognize it, or None when they don't. build_injection_plan tries a sequence
of matchers in order and takes the first match.
Source code in src/hassette/di/types.py
68 69 70 71 72 73 74 75 76 | |
build_injection_plan(sig: Signature, matchers: Sequence[ParameterMatcher]) -> tuple[InjectionParam, ...]
Walk a signature's parameters and build a dependency injection plan.
Each parameter is tried against matchers in order; the first matcher that returns a
non-None InjectionParam wins. Parameters without annotations, and annotated
parameters that no matcher recognizes, are silently skipped.
Raises:
| Type | Description |
|---|---|
DependencyInjectionError
|
If the signature has VAR_POSITIONAL or POSITIONAL_ONLY
parameters (see |
Source code in src/hassette/di/plan.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
validate_di_signature(signature: Signature) -> None
Validate that a signature with DI doesn't have incompatible parameter types.
Raises:
| Type | Description |
|---|---|
DependencyInjectionError
|
If signature has VAR_POSITIONAL (*args) or POSITIONAL_ONLY (/) parameters. |
Source code in src/hassette/di/plan.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
identity(x: Any) -> Any
Identity function - returns the input as-is.
Used when a parameter needs the full source object without transformation.
Source code in src/hassette/di/types.py
15 16 17 18 19 20 | |