From 417e7367468cb434f63a3beb6a92cdf5df5dd006 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 27 Dec 2024 21:25:36 +0100 Subject: [PATCH] Migrate Tile to use entry.runtime_data (#134107) --- homeassistant/components/tile/__init__.py | 32 +++++-------------- homeassistant/components/tile/coordinator.py | 12 ++++++- .../components/tile/device_tracker.py | 17 +++------- homeassistant/components/tile/diagnostics.py | 11 +++---- tests/components/tile/test_config_flow.py | 2 +- 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/tile/__init__.py b/homeassistant/components/tile/__init__.py index 72aed11b4fe..5c0bbbb42ff 100644 --- a/homeassistant/components/tile/__init__.py +++ b/homeassistant/components/tile/__init__.py @@ -2,21 +2,16 @@ from __future__ import annotations -from dataclasses import dataclass - from pytile import async_login from pytile.errors import InvalidAuthError, TileError -from pytile.tile import Tile -from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import aiohttp_client from homeassistant.util.async_ import gather_with_limited_concurrency -from .const import DOMAIN -from .coordinator import TileCoordinator +from .coordinator import TileConfigEntry, TileCoordinator PLATFORMS = [Platform.DEVICE_TRACKER] DEVICE_TYPES = ["PHONE", "TILE"] @@ -26,15 +21,7 @@ DEFAULT_INIT_TASK_LIMIT = 2 CONF_SHOW_INACTIVE = "show_inactive" -@dataclass -class TileData: - """Define an object to be stored in `hass.data`.""" - - coordinators: dict[str, TileCoordinator] - tiles: dict[str, Tile] - - -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_setup_entry(hass: HomeAssistant, entry: TileConfigEntry) -> bool: """Set up Tile as config entry.""" # Tile's API uses cookies to identify a consumer; in order to allow for multiple @@ -57,24 +44,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: coordinator_init_tasks = [] for tile_uuid, tile in tiles.items(): - coordinator = coordinators[tile_uuid] = TileCoordinator(hass, client, tile) + coordinator = coordinators[tile_uuid] = TileCoordinator( + hass, entry, client, tile + ) coordinator_init_tasks.append(coordinator.async_refresh()) await gather_with_limited_concurrency( DEFAULT_INIT_TASK_LIMIT, *coordinator_init_tasks ) - hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = TileData(coordinators=coordinators, tiles=tiles) + entry.runtime_data = coordinators await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True -async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_unload_entry(hass: HomeAssistant, entry: TileConfigEntry) -> bool: """Unload a Tile config entry.""" - unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) - if unload_ok: - hass.data[DOMAIN].pop(entry.entry_id) - - return unload_ok + return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) diff --git a/homeassistant/components/tile/coordinator.py b/homeassistant/components/tile/coordinator.py index e9565210a3e..9a554c1e3ae 100644 --- a/homeassistant/components/tile/coordinator.py +++ b/homeassistant/components/tile/coordinator.py @@ -6,26 +6,36 @@ from pytile.api import API from pytile.errors import InvalidAuthError, SessionExpiredError, TileError from pytile.tile import Tile +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import LOGGER +type TileConfigEntry = ConfigEntry[dict[str, TileCoordinator]] + class TileCoordinator(DataUpdateCoordinator[None]): """Define an object to coordinate Tile data retrieval.""" - def __init__(self, hass: HomeAssistant, client: API, tile: Tile) -> None: + config_entry: TileConfigEntry + + def __init__( + self, hass: HomeAssistant, entry: TileConfigEntry, client: API, tile: Tile + ) -> None: """Initialize.""" super().__init__( hass, LOGGER, name=tile.name, + config_entry=entry, update_interval=timedelta(minutes=2), ) self.tile = tile self.client = client + self.username = entry.data[CONF_USERNAME] async def _async_update_data(self) -> None: """Update data via library.""" diff --git a/homeassistant/components/tile/device_tracker.py b/homeassistant/components/tile/device_tracker.py index a61534ffdea..6a0aae1bdf9 100644 --- a/homeassistant/components/tile/device_tracker.py +++ b/homeassistant/components/tile/device_tracker.py @@ -5,14 +5,11 @@ from __future__ import annotations import logging from homeassistant.components.device_tracker import TrackerEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_USERNAME from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.util.dt import as_utc -from . import TileCoordinator, TileData -from .const import DOMAIN +from .coordinator import TileConfigEntry, TileCoordinator from .entity import TileEntity _LOGGER = logging.getLogger(__name__) @@ -29,16 +26,12 @@ ATTR_VOIP_STATE = "voip_state" async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, entry: TileConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Tile device trackers.""" - data: TileData = hass.data[DOMAIN][entry.entry_id] async_add_entities( - [ - TileDeviceTracker(entry, data.coordinators[tile_uuid]) - for tile_uuid, tile in data.tiles.items() - ] + TileDeviceTracker(coordinator) for coordinator in entry.runtime_data.values() ) @@ -48,12 +41,12 @@ class TileDeviceTracker(TileEntity, TrackerEntity): _attr_name = None _attr_translation_key = "tile" - def __init__(self, entry: ConfigEntry, coordinator: TileCoordinator) -> None: + def __init__(self, coordinator: TileCoordinator) -> None: """Initialize.""" super().__init__(coordinator) self._attr_extra_state_attributes = {} - self._attr_unique_id = f"{entry.data[CONF_USERNAME]}_{self._tile.uuid}" + self._attr_unique_id = f"{coordinator.username}_{self._tile.uuid}" @callback def _handle_coordinator_update(self) -> None: diff --git a/homeassistant/components/tile/diagnostics.py b/homeassistant/components/tile/diagnostics.py index 22991ef24c1..9db33b737c0 100644 --- a/homeassistant/components/tile/diagnostics.py +++ b/homeassistant/components/tile/diagnostics.py @@ -5,12 +5,10 @@ from __future__ import annotations from typing import Any from homeassistant.components.diagnostics import async_redact_data -from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_UUID from homeassistant.core import HomeAssistant -from . import TileData -from .const import DOMAIN +from .coordinator import TileConfigEntry CONF_ALTITUDE = "altitude" @@ -23,11 +21,12 @@ TO_REDACT = { async def async_get_config_entry_diagnostics( - hass: HomeAssistant, entry: ConfigEntry + hass: HomeAssistant, entry: TileConfigEntry ) -> dict[str, Any]: """Return diagnostics for a config entry.""" - data: TileData = hass.data[DOMAIN][entry.entry_id] + coordinators = entry.runtime_data.values() return async_redact_data( - {"tiles": [tile.as_dict() for tile in data.tiles.values()]}, TO_REDACT + {"tiles": [coordinator.tile.as_dict() for coordinator in coordinators]}, + TO_REDACT, ) diff --git a/tests/components/tile/test_config_flow.py b/tests/components/tile/test_config_flow.py index 5ecb6eba229..70090713e47 100644 --- a/tests/components/tile/test_config_flow.py +++ b/tests/components/tile/test_config_flow.py @@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, patch import pytest from pytile.errors import InvalidAuthError, TileError -from homeassistant.components.tile import DOMAIN +from homeassistant.components.tile.const import DOMAIN from homeassistant.config_entries import SOURCE_USER from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant