Plugins (DomainSpec / DomainRegistry)
Declarative model for HaClient's typed domain accessors. Built-in
domains register on import; third-party packages can ship additional
domains via the haclient.domains entry point. See the
Custom domains and plugins guide
for the end-to-end workflow.
plugins
Domain plugin registry and accessor base.
Adding a new domain to HaClient is done by creating an Entity subclass
and registering a DomainSpec. The core never imports specific domains;
it iterates the spec registry instead.
A DomainAccessor is the object returned by ha.<domain> (e.g.
ha.light or ha.scene). It provides:
__call__(name)and__getitem__(name)for entity lookup.- Domain-level operations registered by the spec via
operations(legacy third-party path) or via typed subclass methods (preferred path).
Domains with collection-level operations should subclass DomainAccessor
and register the subclass via DomainSpec.accessor_cls. This keeps the
public API statically typed without requiring # type: ignore workarounds
or private _factory access from outside the accessor.
Third-party plugins can ship additional domains by exposing an entry
point under the haclient.domains group; see
DomainRegistry.load_entry_points.
DomainEventHandler
module-attribute
DomainEventHandler = Callable[['Entity', str, dict[str, Any]], None]
Per-domain handler invoked for non-state_changed events.
Receives the entity instance, the event_type string, and the raw event
data dictionary. Used by domains that need direct event routing (e.g.
the timer domain consuming timer.finished / timer.cancelled).
DomainSpec
dataclass
Bases: Generic[E]
Declarative description of a Home Assistant domain.
Built-in domains live in haclient.domains.* and register a spec at
import time. Third-party packages can register additional domains via
the haclient.domains entry-point group.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The HA domain name (e.g. |
entity_cls |
type[Entity]
|
The entity class instantiated for this domain. |
accessor |
str
|
Attribute name on the |
event_subscriptions |
tuple of str
|
Additional HA event types this domain wants delivered, beyond
the always-on |
on_event |
callable or None
|
Per-domain event handler (see |
operations |
dict
|
Legacy dynamic operation dict kept for third-party plugin
compatibility. Built-in domains with collection-level operations
should prefer |
accessor_cls |
type[DomainAccessor] or None
|
Optional typed |
Source code in src/haclient/core/plugins.py
50 51 52 53 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 | |
accessor_name
accessor_name() -> str
Return the accessor attribute name (defaults to name).
Source code in src/haclient/core/plugins.py
90 91 92 | |
DomainAccessor
Bases: Generic[E]
Runtime facade for one domain.
Returned by HAClient.<accessor>. Exposes:
- Lookup by short name:
ha.light("kitchen")orha.light["kitchen"]. - Domain-level operations either via typed subclass methods (preferred) or
via legacy dynamic binding of
spec.operationsentries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DomainSpec
|
The spec describing this domain. |
required |
factory
|
EntityFactoryProtocol
|
Factory used to create entity instances on demand. |
required |
Source code in src/haclient/core/plugins.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
spec
property
spec: DomainSpec[E]
Return the underlying DomainSpec.
factory
property
factory: EntityFactoryProtocol
Return the EntityFactoryProtocol used to create entities.
Subclasses use this to access factory.services and
factory.state without reaching into private internals.
__call__
__call__(name: str) -> E
Return the entity with short name, creating it if needed.
Source code in src/haclient/core/plugins.py
160 161 162 | |
__getitem__
__getitem__(name: str) -> E
Return the entity with short name, creating it if needed.
Source code in src/haclient/core/plugins.py
164 165 166 | |
all
all() -> list[E]
Return every entity currently registered for this domain.
Returns:
| Type | Description |
|---|---|
list of Entity
|
All entities whose id starts with |
Source code in src/haclient/core/plugins.py
168 169 170 171 172 173 174 175 176 | |
EntityFactoryProtocol
Structural type used by DomainAccessor.
Defined as a regular class to keep imports simple. Concrete
EntityFactory lives in haclient.core.factory.
Source code in src/haclient/core/plugins.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
get_or_create
get_or_create(spec: DomainSpec[Any], name: str) -> Any
Return the entity for spec/name, creating it on first use.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DomainSpec
|
The spec describing the entity's domain. |
required |
name
|
str
|
Short entity name or full |
required |
Returns:
| Type | Description |
|---|---|
Entity
|
The (possibly newly created) entity instance. |
Source code in src/haclient/core/plugins.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |
in_domain
in_domain(spec: DomainSpec[Any]) -> list[Any]
Return every registered entity belonging to spec's domain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DomainSpec
|
The spec describing the domain to enumerate. |
required |
Returns:
| Type | Description |
|---|---|
list of Entity
|
All entities currently in the registry whose id starts with
|
Source code in src/haclient/core/plugins.py
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
DomainRegistry
Mutable registry of DomainSpec keyed by domain name.
Built-in domains register on import (see haclient.domains.__init__).
Third-party domains can be discovered via entry points using
load_entry_points.
Source code in src/haclient/core/plugins.py
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | |
shared
classmethod
shared() -> DomainRegistry
Return the process-wide shared registry instance.
Built-in domain modules use this when they register at import
time. HAClient reads from the same instance unless a custom
registry is passed explicitly.
Source code in src/haclient/core/plugins.py
233 234 235 236 237 238 239 240 241 242 243 | |
register
register(spec: DomainSpec[Any]) -> None
Register spec, raising on duplicate domain names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DomainSpec
|
The spec to register. |
required |
Raises:
| Type | Description |
|---|---|
HAClientError
|
If a spec with the same |
Source code in src/haclient/core/plugins.py
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | |
unregister
unregister(name: str) -> None
Remove the spec registered under name, if any.
Source code in src/haclient/core/plugins.py
272 273 274 | |
get
get(name: str) -> DomainSpec[Any]
Return the spec registered for name or raise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The HA domain name to look up. |
required |
Returns:
| Type | Description |
|---|---|
DomainSpec
|
The registered spec. |
Raises:
| Type | Description |
|---|---|
HAClientError
|
If no domain name is registered. |
Source code in src/haclient/core/plugins.py
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | |
names
names() -> list[str]
Return all registered domain names.
Source code in src/haclient/core/plugins.py
307 308 309 | |
filter
filter(names: Iterable[str]) -> list[DomainSpec[Any]]
Return only the specs whose names are in names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
names
|
iterable of str
|
Allowed domain names. Unknown names are silently ignored. |
required |
Returns:
| Type | Description |
|---|---|
list of DomainSpec
|
Registered specs filtered to the requested subset, in registration order. |
Source code in src/haclient/core/plugins.py
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | |
load_entry_points
load_entry_points(group: str = 'haclient.domains') -> list[str]
Discover and load third-party domain plugins.
Each entry point is loaded inside a try/except so a single
broken plugin cannot prevent the rest from loading. The names
of the entry points that loaded successfully are returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group
|
str
|
The entry-point group name. Defaults to |
'haclient.domains'
|
Returns:
| Type | Description |
|---|---|
list of str
|
Names of the entry points that loaded without raising. |
Source code in src/haclient/core/plugins.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | |
register_domain
register_domain(spec: DomainSpec[Any]) -> DomainSpec[Any]
Register spec on the shared registry.
This is the canonical entry point for both built-in and third-party domain modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DomainSpec
|
The spec to register. |
required |
Returns:
| Type | Description |
|---|---|
DomainSpec
|
The same spec, for convenience. |
Source code in src/haclient/core/plugins.py
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |