Update remote calendar to do all event handling in an executor (#144232)

This commit is contained in:
Allen Porter 2025-05-04 20:07:02 -07:00 committed by GitHub
parent 68d62ab58e
commit fa6a2f08ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -29,7 +29,7 @@ async def async_setup_entry(
"""Set up the remote calendar platform."""
coordinator = entry.runtime_data
entity = RemoteCalendarEntity(coordinator, entry)
async_add_entities([entity])
async_add_entities([entity], True)
class RemoteCalendarEntity(
@ -48,25 +48,46 @@ class RemoteCalendarEntity(
super().__init__(coordinator)
self._attr_name = entry.data[CONF_CALENDAR_NAME]
self._attr_unique_id = entry.entry_id
self._event: CalendarEvent | None = None
@property
def event(self) -> CalendarEvent | None:
"""Return the next upcoming event."""
now = dt_util.now()
events = self.coordinator.data.timeline_tz(now.tzinfo).active_after(now)
if event := next(events, None):
return _get_calendar_event(event)
return None
return self._event
async def async_get_events(
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
) -> list[CalendarEvent]:
"""Get all events in a specific time frame."""
events = self.coordinator.data.timeline_tz(start_date.tzinfo).overlapping(
start_date,
end_date,
)
return [_get_calendar_event(event) for event in events]
def events_in_range() -> list[CalendarEvent]:
"""Return all events in the given time range."""
events = self.coordinator.data.timeline_tz(start_date.tzinfo).overlapping(
start_date,
end_date,
)
return [_get_calendar_event(event) for event in events]
return await self.hass.async_add_executor_job(events_in_range)
async def async_update(self) -> None:
"""Refresh the timeline.
This is called when the coordinator updates. Creating the timeline may
require walking through the entire calendar and handling recurring
events, so it is done as a separate task without blocking the event loop.
"""
await super().async_update()
def next_timeline_event() -> CalendarEvent | None:
"""Return the next active event."""
now = dt_util.now()
events = self.coordinator.data.timeline_tz(now.tzinfo).active_after(now)
if event := next(events, None):
return _get_calendar_event(event)
return None
self._event = await self.hass.async_add_executor_job(next_timeline_event)
def _get_calendar_event(event: Event) -> CalendarEvent: