Coverage for src/homeassistant_repl/rest.py: 100%
13 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-05 13:50 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-05 13:50 +0000
1"""`hass_api()` - the opinionated one-liner for Home Assistant's REST API
2(https://developers.home-assistant.io/docs/api/rest/), parallel to
3`connect()` for the websocket-based `obj` tree. Hands back a ready-to-use
4`homeassistant_api.AsyncClient` (https://homeassistantapi.readthedocs.io)
5rather than a thin wrapper of our own - that package already covers the
6REST surface (get_state, get_states, trigger_service, get_config,
7get_logbook_entries, get_entity_histories, render a template, ...) with
8typed responses, so there's no reason to reinvent it here.
10Named `hass_api`, not `api`: `obj.mode("api")` already uses "api" for the
11cached/read-only view custom mode's `obj` can switch into, and the two are
12easy to conflate in a transcript otherwise.
13"""
15from __future__ import annotations
17from homeassistant_api import AsyncClient
18from homeassistant_api.errors import HomeassistantAPIError
20from .client import HaReplError, resolve_rest_url, resolve_token
23async def hass_api(url: str | None = None, token: str | None = None) -> AsyncClient:
24 """Connect to Home Assistant's REST API, returning a ready-to-use
25 homeassistant_api.AsyncClient - see https://homeassistantapi.readthedocs.io/en/stable/
27 `url`/`token` default to $HASS_SERVER/$HASS_TOKEN (and, inside a Home
28 Assistant add-on, the supervisor) the same way `connect()` does. The
29 underlying HTTP session stays open for the life of the process.
30 """
31 client = AsyncClient(resolve_rest_url(url), resolve_token(token))
32 try:
33 running = await client.check_api_running()
34 except (HomeassistantAPIError, OSError) as err:
35 raise HaReplError(f"Cannot reach {client.api_url}: {err}") from err
36 if not running:
37 raise HaReplError(f"{client.api_url} is not running")
38 return client