Move Guardian coordinator to suggested location (#108182)

* Move Guardian coordinator to suggested location

* Fix coverage
This commit is contained in:
Aaron Bach 2024-01-16 15:38:20 -07:00 committed by GitHub
parent bee53f6004
commit f0a63f7189
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 85 additions and 68 deletions

View File

@ -475,6 +475,7 @@ omit =
homeassistant/components/guardian/__init__.py homeassistant/components/guardian/__init__.py
homeassistant/components/guardian/binary_sensor.py homeassistant/components/guardian/binary_sensor.py
homeassistant/components/guardian/button.py homeassistant/components/guardian/button.py
homeassistant/components/guardian/coordinator.py
homeassistant/components/guardian/sensor.py homeassistant/components/guardian/sensor.py
homeassistant/components/guardian/switch.py homeassistant/components/guardian/switch.py
homeassistant/components/guardian/util.py homeassistant/components/guardian/util.py

View File

@ -40,7 +40,7 @@ from .const import (
LOGGER, LOGGER,
SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED, SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED,
) )
from .util import GuardianDataUpdateCoordinator from .coordinator import GuardianDataUpdateCoordinator
DATA_PAIRED_SENSOR_MANAGER = "paired_sensor_manager" DATA_PAIRED_SENSOR_MANAGER = "paired_sensor_manager"

View File

@ -29,9 +29,9 @@ from .const import (
DOMAIN, DOMAIN,
SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED, SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED,
) )
from .coordinator import GuardianDataUpdateCoordinator
from .util import ( from .util import (
EntityDomainReplacementStrategy, EntityDomainReplacementStrategy,
GuardianDataUpdateCoordinator,
async_finish_entity_domain_replacements, async_finish_entity_domain_replacements,
) )

View File

@ -0,0 +1,79 @@
"""Define Guardian-specific utilities."""
from __future__ import annotations
import asyncio
from collections.abc import Callable, Coroutine
from datetime import timedelta
from typing import Any, cast
from aioguardian import Client
from aioguardian.errors import GuardianError
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import LOGGER
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}"
class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""Define an extended DataUpdateCoordinator with some Guardian goodies."""
config_entry: ConfigEntry
def __init__(
self,
hass: HomeAssistant,
*,
entry: ConfigEntry,
client: Client,
api_name: str,
api_coro: Callable[..., Coroutine[Any, Any, dict[str, Any]]],
api_lock: asyncio.Lock,
valve_controller_uid: str,
) -> None:
"""Initialize."""
super().__init__(
hass,
LOGGER,
name=f"{valve_controller_uid}_{api_name}",
update_interval=DEFAULT_UPDATE_INTERVAL,
)
self._api_coro = api_coro
self._api_lock = api_lock
self._client = client
self.config_entry = entry
self.signal_reboot_requested = SIGNAL_REBOOT_REQUESTED.format(
self.config_entry.entry_id
)
async def _async_update_data(self) -> dict[str, Any]:
"""Execute a "locked" API request against the valve controller."""
async with self._api_lock, self._client:
try:
resp = await self._api_coro()
except GuardianError as err:
raise UpdateFailed(err) from err
return cast(dict[str, Any], resp["data"])
async def async_initialize(self) -> None:
"""Initialize the coordinator."""
@callback
def async_reboot_requested() -> None:
"""Respond to a reboot request."""
self.last_update_success = False
self.async_update_listeners()
self.config_entry.async_on_unload(
async_dispatcher_connect(
self.hass, self.signal_reboot_requested, async_reboot_requested
)
)

View File

@ -1,22 +1,18 @@
"""Define Guardian-specific utilities.""" """Define Guardian-specific utilities."""
from __future__ import annotations from __future__ import annotations
import asyncio
from collections.abc import Callable, Coroutine, Iterable from collections.abc import Callable, Coroutine, Iterable
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from functools import wraps from functools import wraps
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, cast from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar
from aioguardian import Client
from aioguardian.errors import GuardianError from aioguardian.errors import GuardianError
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import LOGGER from .const import LOGGER
@ -29,6 +25,8 @@ DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}" SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}"
_P = ParamSpec("_P")
@dataclass @dataclass
class EntityDomainReplacementStrategy: class EntityDomainReplacementStrategy:
@ -63,67 +61,6 @@ def async_finish_entity_domain_replacements(
ent_reg.async_remove(old_entity_id) ent_reg.async_remove(old_entity_id)
class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
"""Define an extended DataUpdateCoordinator with some Guardian goodies."""
config_entry: ConfigEntry
def __init__(
self,
hass: HomeAssistant,
*,
entry: ConfigEntry,
client: Client,
api_name: str,
api_coro: Callable[..., Coroutine[Any, Any, dict[str, Any]]],
api_lock: asyncio.Lock,
valve_controller_uid: str,
) -> None:
"""Initialize."""
super().__init__(
hass,
LOGGER,
name=f"{valve_controller_uid}_{api_name}",
update_interval=DEFAULT_UPDATE_INTERVAL,
)
self._api_coro = api_coro
self._api_lock = api_lock
self._client = client
self.config_entry = entry
self.signal_reboot_requested = SIGNAL_REBOOT_REQUESTED.format(
self.config_entry.entry_id
)
async def _async_update_data(self) -> dict[str, Any]:
"""Execute a "locked" API request against the valve controller."""
async with self._api_lock, self._client:
try:
resp = await self._api_coro()
except GuardianError as err:
raise UpdateFailed(err) from err
return cast(dict[str, Any], resp["data"])
async def async_initialize(self) -> None:
"""Initialize the coordinator."""
@callback
def async_reboot_requested() -> None:
"""Respond to a reboot request."""
self.last_update_success = False
self.async_update_listeners()
self.config_entry.async_on_unload(
async_dispatcher_connect(
self.hass, self.signal_reboot_requested, async_reboot_requested
)
)
_P = ParamSpec("_P")
@callback @callback
def convert_exceptions_to_homeassistant_error( def convert_exceptions_to_homeassistant_error(
func: Callable[Concatenate[_GuardianEntityT, _P], Coroutine[Any, Any, Any]], func: Callable[Concatenate[_GuardianEntityT, _P], Coroutine[Any, Any, Any]],