Partially revert google local sync for search cases (#81761)

fixes undefined
This commit is contained in:
Allen Porter 2022-11-08 02:21:13 -08:00 committed by GitHub
parent 4d1fa42a3c
commit dfab3b2651
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,11 +3,12 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from collections.abc import Iterable
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
from typing import Any from typing import Any
from gcal_sync.api import SyncEventsRequest from gcal_sync.api import GoogleCalendarService, ListEventsRequest, SyncEventsRequest
from gcal_sync.exceptions import ApiException from gcal_sync.exceptions import ApiException
from gcal_sync.model import DateOrDatetime, Event from gcal_sync.model import DateOrDatetime, Event
from gcal_sync.store import ScopedCalendarStore from gcal_sync.store import ScopedCalendarStore
@ -196,21 +197,30 @@ async def async_setup_entry(
entity_registry.async_remove( entity_registry.async_remove(
entity_entry.entity_id, entity_entry.entity_id,
) )
request_template = SyncEventsRequest( coordinator: CalendarSyncUpdateCoordinator | CalendarQueryUpdateCoordinator
calendar_id=calendar_id, if search := data.get(CONF_SEARCH):
search=data.get(CONF_SEARCH), coordinator = CalendarQueryUpdateCoordinator(
start_time=dt_util.now() + SYNC_EVENT_MIN_TIME, hass,
) calendar_service,
sync = CalendarEventSyncManager( data[CONF_NAME],
calendar_service, calendar_id,
store=ScopedCalendarStore(store, unique_id or entity_name), search,
request_template=request_template, )
) else:
coordinator = CalendarUpdateCoordinator( request_template = SyncEventsRequest(
hass, calendar_id=calendar_id,
sync, start_time=dt_util.now() + SYNC_EVENT_MIN_TIME,
data[CONF_NAME], )
) sync = CalendarEventSyncManager(
calendar_service,
store=ScopedCalendarStore(store, unique_id or entity_name),
request_template=request_template,
)
coordinator = CalendarSyncUpdateCoordinator(
hass,
sync,
data[CONF_NAME],
)
entities.append( entities.append(
GoogleCalendarEntity( GoogleCalendarEntity(
coordinator, coordinator,
@ -242,8 +252,8 @@ async def async_setup_entry(
) )
class CalendarUpdateCoordinator(DataUpdateCoordinator[Timeline]): class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
"""Coordinator for calendar RPC calls.""" """Coordinator for calendar RPC calls that use an efficient sync."""
def __init__( def __init__(
self, self,
@ -251,7 +261,7 @@ class CalendarUpdateCoordinator(DataUpdateCoordinator[Timeline]):
sync: CalendarEventSyncManager, sync: CalendarEventSyncManager,
name: str, name: str,
) -> None: ) -> None:
"""Create the Calendar event device.""" """Create the CalendarSyncUpdateCoordinator."""
super().__init__( super().__init__(
hass, hass,
_LOGGER, _LOGGER,
@ -271,6 +281,87 @@ class CalendarUpdateCoordinator(DataUpdateCoordinator[Timeline]):
dt_util.DEFAULT_TIME_ZONE dt_util.DEFAULT_TIME_ZONE
) )
async def async_get_events(
self, start_date: datetime, end_date: datetime
) -> Iterable[Event]:
"""Get all events in a specific time frame."""
if not self.data:
raise HomeAssistantError(
"Unable to get events: Sync from server has not completed"
)
return self.data.overlapping(
dt_util.as_local(start_date),
dt_util.as_local(end_date),
)
@property
def upcoming(self) -> Iterable[Event] | None:
"""Return upcoming events if any."""
if self.data:
return self.data.active_after(dt_util.now())
return None
class CalendarQueryUpdateCoordinator(DataUpdateCoordinator[list[Event]]):
"""Coordinator for calendar RPC calls.
This sends a polling RPC, not using sync, as a workaround
for limitations in the calendar API for supporting search.
"""
def __init__(
self,
hass: HomeAssistant,
calendar_service: GoogleCalendarService,
name: str,
calendar_id: str,
search: str | None,
) -> None:
"""Create the CalendarQueryUpdateCoordinator."""
super().__init__(
hass,
_LOGGER,
name=name,
update_interval=MIN_TIME_BETWEEN_UPDATES,
)
self.calendar_service = calendar_service
self.calendar_id = calendar_id
self._search = search
async def async_get_events(
self, start_date: datetime, end_date: datetime
) -> Iterable[Event]:
"""Get all events in a specific time frame."""
request = ListEventsRequest(
calendar_id=self.calendar_id,
start_time=start_date,
end_time=end_date,
search=self._search,
)
result_items = []
try:
result = await self.calendar_service.async_list_events(request)
async for result_page in result:
result_items.extend(result_page.items)
except ApiException as err:
self.async_set_update_error(err)
raise HomeAssistantError(str(err)) from err
return result_items
async def _async_update_data(self) -> list[Event]:
"""Fetch data from API endpoint."""
request = ListEventsRequest(calendar_id=self.calendar_id, search=self._search)
try:
result = await self.calendar_service.async_list_events(request)
except ApiException as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
return result.items
@property
def upcoming(self) -> Iterable[Event] | None:
"""Return the next upcoming event if any."""
return self.data
class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity): class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity):
"""A calendar event entity.""" """A calendar event entity."""
@ -279,7 +370,7 @@ class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity):
def __init__( def __init__(
self, self,
coordinator: CalendarUpdateCoordinator, coordinator: CalendarSyncUpdateCoordinator | CalendarQueryUpdateCoordinator,
calendar_id: str, calendar_id: str,
data: dict[str, Any], data: dict[str, Any],
entity_id: str, entity_id: str,
@ -352,14 +443,7 @@ class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity):
self, hass: HomeAssistant, start_date: datetime, end_date: datetime self, hass: HomeAssistant, start_date: datetime, end_date: datetime
) -> list[CalendarEvent]: ) -> list[CalendarEvent]:
"""Get all events in a specific time frame.""" """Get all events in a specific time frame."""
if not (timeline := self.coordinator.data): result_items = await self.coordinator.async_get_events(start_date, end_date)
raise HomeAssistantError(
"Unable to get events: Sync from server has not completed"
)
result_items = timeline.overlapping(
dt_util.as_local(start_date),
dt_util.as_local(end_date),
)
return [ return [
_get_calendar_event(event) _get_calendar_event(event)
for event in filter(self._event_filter, result_items) for event in filter(self._event_filter, result_items)
@ -367,14 +451,12 @@ class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity):
def _apply_coordinator_update(self) -> None: def _apply_coordinator_update(self) -> None:
"""Copy state from the coordinator to this entity.""" """Copy state from the coordinator to this entity."""
if (timeline := self.coordinator.data) and ( if api_event := next(
api_event := next( filter(
filter( self._event_filter,
self._event_filter, self.coordinator.upcoming or [],
timeline.active_after(dt_util.now()), ),
), None,
None,
)
): ):
self._event = _get_calendar_event(api_event) self._event = _get_calendar_event(api_event)
(self._event.summary, self._offset_value) = extract_offset( (self._event.summary, self._offset_value) = extract_offset(