forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Subclass a
DataUpdateCoordinator
for Ridwell (home-assistant#85644)
- Loading branch information
Showing
11 changed files
with
123 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
"""Define a Ridwell coordinator.""" | ||
from __future__ import annotations | ||
|
||
import asyncio | ||
from datetime import timedelta | ||
from typing import cast | ||
|
||
from aioridwell.client import async_get_client | ||
from aioridwell.errors import InvalidCredentialsError, RidwellError | ||
from aioridwell.model import RidwellAccount, RidwellPickupEvent | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady | ||
from homeassistant.helpers import aiohttp_client | ||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed | ||
|
||
from .const import LOGGER | ||
|
||
UPDATE_INTERVAL = timedelta(hours=1) | ||
|
||
|
||
class RidwellDataUpdateCoordinator( | ||
DataUpdateCoordinator[dict[str, RidwellPickupEvent]] | ||
): | ||
"""Class to manage fetching data from single endpoint.""" | ||
|
||
config_entry: ConfigEntry | ||
|
||
def __init__(self, hass: HomeAssistant, *, name: str) -> None: | ||
"""Initialize global data updater.""" | ||
# These will be filled in by async_initialize; we give them these defaults to | ||
# avoid arduous typing checks down the line: | ||
self.accounts: dict[str, RidwellAccount] = {} | ||
self.dashboard_url = "" | ||
self.user_id = "" | ||
|
||
super().__init__(hass, LOGGER, name=name, update_interval=UPDATE_INTERVAL) | ||
|
||
async def _async_update_data(self) -> dict[str, RidwellPickupEvent]: | ||
"""Fetch the latest data from the source.""" | ||
data = {} | ||
|
||
async def async_get_pickups(account: RidwellAccount) -> None: | ||
"""Get the latest pickups for an account.""" | ||
data[account.account_id] = await account.async_get_next_pickup_event() | ||
|
||
tasks = [async_get_pickups(account) for account in self.accounts.values()] | ||
results = await asyncio.gather(*tasks, return_exceptions=True) | ||
for result in results: | ||
if isinstance(result, InvalidCredentialsError): | ||
raise ConfigEntryAuthFailed("Invalid username/password") from result | ||
if isinstance(result, RidwellError): | ||
raise UpdateFailed(result) from result | ||
|
||
return data | ||
|
||
async def async_initialize(self) -> None: | ||
"""Initialize the coordinator.""" | ||
session = aiohttp_client.async_get_clientsession(self.hass) | ||
|
||
try: | ||
client = await async_get_client( | ||
self.config_entry.data[CONF_USERNAME], | ||
self.config_entry.data[CONF_PASSWORD], | ||
session=session, | ||
) | ||
except InvalidCredentialsError as err: | ||
raise ConfigEntryAuthFailed("Invalid username/password") from err | ||
except RidwellError as err: | ||
raise ConfigEntryNotReady(err) from err | ||
|
||
self.accounts = await client.async_get_accounts() | ||
await self.async_config_entry_first_refresh() | ||
|
||
self.dashboard_url = client.get_dashboard_url() | ||
self.user_id = cast(str, client.user_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,10 @@ | |
from tests.common import MockConfigEntry | ||
|
||
TEST_ACCOUNT_ID = "12345" | ||
TEST_DASHBOARD_URL = "https://www.ridwell.com/users/12345/dashboard" | ||
TEST_PASSWORD = "password" | ||
TEST_USERNAME = "[email protected]" | ||
TEST_USER_ID = "12345" | ||
|
||
|
||
@pytest.fixture(name="account") | ||
|
@@ -44,6 +46,8 @@ def client_fixture(account): | |
return Mock( | ||
async_authenticate=AsyncMock(), | ||
async_get_accounts=AsyncMock(return_value={TEST_ACCOUNT_ID: account}), | ||
get_dashboard_url=Mock(return_value=TEST_DASHBOARD_URL), | ||
user_id=TEST_USER_ID, | ||
) | ||
|
||
|
||
|
@@ -70,7 +74,10 @@ async def mock_aioridwell_fixture(hass, client, config): | |
with patch( | ||
"homeassistant.components.ridwell.config_flow.async_get_client", | ||
return_value=client, | ||
), patch("homeassistant.components.ridwell.async_get_client", return_value=client): | ||
), patch( | ||
"homeassistant.components.ridwell.coordinator.async_get_client", | ||
return_value=client, | ||
): | ||
yield | ||
|
||
|
||
|