Use runtime_data in google (#144331)

* Use runtime_data in google

* Quality scale
This commit is contained in:
epenet 2025-05-06 16:55:04 +02:00 committed by GitHub
parent 1447392847
commit 253217958b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 45 additions and 53 deletions

View File

@ -14,7 +14,6 @@ from gcal_sync.model import DateOrDatetime, Event
import voluptuous as vol
import yaml
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_ENTITIES,
@ -34,8 +33,6 @@ from homeassistant.helpers.entity import generate_entity_id
from .api import ApiAuthImpl, get_feature_access
from .const import (
DATA_SERVICE,
DATA_STORE,
DOMAIN,
EVENT_DESCRIPTION,
EVENT_END_DATE,
@ -50,7 +47,7 @@ from .const import (
EVENT_TYPES_CONF,
FeatureAccess,
)
from .store import LocalCalendarStore
from .store import GoogleConfigEntry, GoogleRuntimeData, LocalCalendarStore
_LOGGER = logging.getLogger(__name__)
@ -139,11 +136,8 @@ ADD_EVENT_SERVICE_SCHEMA = vol.All(
)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: GoogleConfigEntry) -> bool:
"""Set up Google from a config entry."""
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {}
# Validate google_calendars.yaml (if present) as soon as possible to return
# helpful error messages.
try:
@ -181,9 +175,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
calendar_service = GoogleCalendarService(
ApiAuthImpl(async_get_clientsession(hass), session)
)
hass.data[DOMAIN][entry.entry_id][DATA_SERVICE] = calendar_service
hass.data[DOMAIN][entry.entry_id][DATA_STORE] = LocalCalendarStore(
hass, entry.entry_id
entry.runtime_data = GoogleRuntimeData(
service=calendar_service,
store=LocalCalendarStore(hass, entry.entry_id),
)
if entry.unique_id is None:
@ -207,27 +201,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
def async_entry_has_scopes(entry: ConfigEntry) -> bool:
def async_entry_has_scopes(entry: GoogleConfigEntry) -> bool:
"""Verify that the config entry desired scope is present in the oauth token."""
access = get_feature_access(entry)
token_scopes = entry.data.get("token", {}).get("scope", [])
return access.scope in token_scopes
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: GoogleConfigEntry) -> bool:
"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_reload_entry(hass: HomeAssistant, entry: GoogleConfigEntry) -> None:
"""Reload config entry if the access options change."""
if not async_entry_has_scopes(entry):
await hass.config_entries.async_reload(entry.entry_id)
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_remove_entry(hass: HomeAssistant, entry: GoogleConfigEntry) -> None:
"""Handle removal of a local storage."""
store = LocalCalendarStore(hass, entry.entry_id)
await store.async_remove()

View File

@ -17,7 +17,6 @@ from oauth2client.client import (
)
from homeassistant.components.application_credentials import AuthImplementation
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers import config_entry_oauth2_flow
from homeassistant.helpers.event import (
@ -27,6 +26,7 @@ from homeassistant.helpers.event import (
from homeassistant.util import dt as dt_util
from .const import CONF_CALENDAR_ACCESS, DEFAULT_FEATURE_ACCESS, FeatureAccess
from .store import GoogleConfigEntry
_LOGGER = logging.getLogger(__name__)
@ -155,7 +155,7 @@ class DeviceFlow:
self._listener()
def get_feature_access(config_entry: ConfigEntry) -> FeatureAccess:
def get_feature_access(config_entry: GoogleConfigEntry) -> FeatureAccess:
"""Return the desired calendar feature access."""
if config_entry.options and CONF_CALENDAR_ACCESS in config_entry.options:
return FeatureAccess[config_entry.options[CONF_CALENDAR_ACCESS]]

View File

@ -37,7 +37,6 @@ from homeassistant.components.calendar import (
extract_offset,
is_offset_reached,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_ID, CONF_ENTITIES, CONF_NAME, CONF_OFFSET
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
@ -52,7 +51,6 @@ from . import (
CONF_SEARCH,
CONF_TRACK,
DEFAULT_CONF_OFFSET,
DOMAIN,
YAML_DEVICES,
get_calendar_info,
load_config,
@ -60,8 +58,6 @@ from . import (
)
from .api import get_feature_access
from .const import (
DATA_SERVICE,
DATA_STORE,
EVENT_END_DATE,
EVENT_END_DATETIME,
EVENT_IN,
@ -72,6 +68,7 @@ from .const import (
FeatureAccess,
)
from .coordinator import CalendarQueryUpdateCoordinator, CalendarSyncUpdateCoordinator
from .store import GoogleConfigEntry
_LOGGER = logging.getLogger(__name__)
@ -109,7 +106,7 @@ class GoogleCalendarEntityDescription(CalendarEntityDescription):
def _get_entity_descriptions(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: GoogleConfigEntry,
calendar_item: Calendar,
calendar_info: Mapping[str, Any],
) -> list[GoogleCalendarEntityDescription]:
@ -202,12 +199,12 @@ def _get_entity_descriptions(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: GoogleConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the google calendar platform."""
calendar_service = hass.data[DOMAIN][config_entry.entry_id][DATA_SERVICE]
store = hass.data[DOMAIN][config_entry.entry_id][DATA_STORE]
calendar_service = config_entry.runtime_data.service
store = config_entry.runtime_data.store
try:
result = await calendar_service.async_list_calendars()
except ApiException as err:

View File

@ -11,12 +11,7 @@ from gcal_sync.api import GoogleCalendarService
from gcal_sync.exceptions import ApiException, ApiForbiddenException
import voluptuous as vol
from homeassistant.config_entries import (
SOURCE_REAUTH,
ConfigEntry,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult, OptionsFlow
from homeassistant.core import callback
from homeassistant.helpers import config_entry_oauth2_flow
from homeassistant.helpers.aiohttp_client import async_get_clientsession
@ -38,6 +33,7 @@ from .const import (
CredentialType,
FeatureAccess,
)
from .store import GoogleConfigEntry
_LOGGER = logging.getLogger(__name__)
@ -240,7 +236,7 @@ class OAuth2FlowHandler(
@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
config_entry: GoogleConfigEntry,
) -> OptionsFlow:
"""Create an options flow."""
return OptionsFlowHandler()

View File

@ -9,9 +9,7 @@ DOMAIN = "google"
CONF_CALENDAR_ACCESS = "calendar_access"
CONF_CREDENTIAL_TYPE = "credential_type"
DATA_CALENDARS = "calendars"
DATA_SERVICE = "service"
DATA_CONFIG = "config"
DATA_STORE = "store"
class FeatureAccess(Enum):

View File

@ -14,12 +14,13 @@ from gcal_sync.sync import CalendarEventSyncManager
from gcal_sync.timeline import Timeline
from ical.iter import SortableItemValue
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util import dt as dt_util
from .store import GoogleConfigEntry
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
@ -47,12 +48,12 @@ def _truncate_timeline(timeline: Timeline, max_events: int) -> Timeline:
class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
"""Coordinator for calendar RPC calls that use an efficient sync."""
config_entry: ConfigEntry
config_entry: GoogleConfigEntry
def __init__(
self,
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: GoogleConfigEntry,
sync: CalendarEventSyncManager,
name: str,
) -> None:
@ -108,12 +109,12 @@ class CalendarQueryUpdateCoordinator(DataUpdateCoordinator[list[Event]]):
for limitations in the calendar API for supporting search.
"""
config_entry: ConfigEntry
config_entry: GoogleConfigEntry
def __init__(
self,
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: GoogleConfigEntry,
calendar_service: GoogleCalendarService,
name: str,
calendar_id: str,

View File

@ -4,11 +4,10 @@ import datetime
from typing import Any
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.util import dt as dt_util
from .const import DATA_STORE, DOMAIN
from .store import GoogleConfigEntry
TO_REDACT = {
"id",
@ -40,7 +39,7 @@ def redact_store(data: dict[str, Any]) -> dict[str, Any]:
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry
hass: HomeAssistant, config_entry: GoogleConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
payload: dict[str, Any] = {
@ -49,7 +48,7 @@ async def async_get_config_entry_diagnostics(
"system_timezone": str(datetime.datetime.now().astimezone().tzinfo),
}
store = hass.data[DOMAIN][config_entry.entry_id][DATA_STORE]
data = await store.async_load()
payload["store"] = redact_store(data)
store = config_entry.runtime_data.store
if data := await store.async_load():
payload["store"] = redact_store(data)
return payload

View File

@ -40,11 +40,7 @@ rules:
to increase functionality such as checking for the specific contents
of a unique id assigned to a config entry.
docs-actions: done
runtime-data:
status: todo
comment: |
The integration stores config entry data in `hass.data` and should be
updated to use `runtime_data`.
runtime-data: done
# Silver
log-when-unavailable: done

View File

@ -2,11 +2,14 @@
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import Any
from gcal_sync.api import GoogleCalendarService
from gcal_sync.store import CalendarStore
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.storage import Store
@ -19,6 +22,16 @@ STORAGE_VERSION = 1
# Buffer writes every few minutes (plus guaranteed to be written at shutdown)
STORAGE_SAVE_DELAY_SECONDS = 120
type GoogleConfigEntry = ConfigEntry[GoogleRuntimeData]
@dataclass
class GoogleRuntimeData:
"""Google runtime data."""
service: GoogleCalendarService
store: LocalCalendarStore
class LocalCalendarStore(CalendarStore):
"""Storage for local persistence of calendar and event data."""