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

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. 

9 

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""" 

14 

15from __future__ import annotations 

16 

17from homeassistant_api import AsyncClient 

18from homeassistant_api.errors import HomeassistantAPIError 

19 

20from .client import HaReplError, resolve_rest_url, resolve_token 

21 

22 

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/ 

26 

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