Update local_calendar/todo to avoid blocking in the event loop (#127048)
parent
8f47b63762
commit
4e11797d72
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import date, datetime, timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
|
@ -74,6 +75,7 @@ class LocalCalendarEntity(CalendarEntity):
|
|||
"""Initialize LocalCalendarEntity."""
|
||||
self._store = store
|
||||
self._calendar = calendar
|
||||
self._calendar_lock = asyncio.Lock()
|
||||
self._event: CalendarEvent | None = None
|
||||
self._attr_name = name
|
||||
self._attr_unique_id = unique_id
|
||||
|
@ -110,8 +112,10 @@ class LocalCalendarEntity(CalendarEntity):
|
|||
async def async_create_event(self, **kwargs: Any) -> None:
|
||||
"""Add a new event to calendar."""
|
||||
event = _parse_event(kwargs)
|
||||
EventStore(self._calendar).add(event)
|
||||
await self._async_store()
|
||||
async with self._calendar_lock:
|
||||
event_store = EventStore(self._calendar)
|
||||
await self.hass.async_add_executor_job(event_store.add, event)
|
||||
await self._async_store()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_delete_event(
|
||||
|
@ -124,15 +128,16 @@ class LocalCalendarEntity(CalendarEntity):
|
|||
range_value: Range = Range.NONE
|
||||
if recurrence_range == Range.THIS_AND_FUTURE:
|
||||
range_value = Range.THIS_AND_FUTURE
|
||||
try:
|
||||
EventStore(self._calendar).delete(
|
||||
uid,
|
||||
recurrence_id=recurrence_id,
|
||||
recurrence_range=range_value,
|
||||
)
|
||||
except EventStoreError as err:
|
||||
raise HomeAssistantError(f"Error while deleting event: {err}") from err
|
||||
await self._async_store()
|
||||
async with self._calendar_lock:
|
||||
try:
|
||||
EventStore(self._calendar).delete(
|
||||
uid,
|
||||
recurrence_id=recurrence_id,
|
||||
recurrence_range=range_value,
|
||||
)
|
||||
except EventStoreError as err:
|
||||
raise HomeAssistantError(f"Error while deleting event: {err}") from err
|
||||
await self._async_store()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_update_event(
|
||||
|
@ -147,16 +152,23 @@ class LocalCalendarEntity(CalendarEntity):
|
|||
range_value: Range = Range.NONE
|
||||
if recurrence_range == Range.THIS_AND_FUTURE:
|
||||
range_value = Range.THIS_AND_FUTURE
|
||||
try:
|
||||
EventStore(self._calendar).edit(
|
||||
uid,
|
||||
new_event,
|
||||
recurrence_id=recurrence_id,
|
||||
recurrence_range=range_value,
|
||||
)
|
||||
except EventStoreError as err:
|
||||
raise HomeAssistantError(f"Error while updating event: {err}") from err
|
||||
await self._async_store()
|
||||
|
||||
async with self._calendar_lock:
|
||||
event_store = EventStore(self._calendar)
|
||||
|
||||
def apply_edit() -> None:
|
||||
event_store.edit(
|
||||
uid,
|
||||
new_event,
|
||||
recurrence_id=recurrence_id,
|
||||
recurrence_range=range_value,
|
||||
)
|
||||
|
||||
try:
|
||||
await self.hass.async_add_executor_job(apply_edit)
|
||||
except EventStoreError as err:
|
||||
raise HomeAssistantError(f"Error while updating event: {err}") from err
|
||||
await self._async_store()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""A Local To-do todo platform."""
|
||||
|
||||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
|
@ -130,6 +131,7 @@ class LocalTodoListEntity(TodoListEntity):
|
|||
"""Initialize LocalTodoListEntity."""
|
||||
self._store = store
|
||||
self._calendar = calendar
|
||||
self._calendar_lock = asyncio.Lock()
|
||||
self._attr_name = name.capitalize()
|
||||
self._attr_unique_id = unique_id
|
||||
|
||||
|
@ -159,23 +161,28 @@ class LocalTodoListEntity(TodoListEntity):
|
|||
async def async_create_todo_item(self, item: TodoItem) -> None:
|
||||
"""Add an item to the To-do list."""
|
||||
todo = _convert_item(item)
|
||||
self._new_todo_store().add(todo)
|
||||
await self.async_save()
|
||||
async with self._calendar_lock:
|
||||
todo_store = self._new_todo_store()
|
||||
await self.hass.async_add_executor_job(todo_store.add, todo)
|
||||
await self.async_save()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_update_todo_item(self, item: TodoItem) -> None:
|
||||
"""Update an item to the To-do list."""
|
||||
todo = _convert_item(item)
|
||||
self._new_todo_store().edit(todo.uid, todo)
|
||||
await self.async_save()
|
||||
async with self._calendar_lock:
|
||||
todo_store = self._new_todo_store()
|
||||
await self.hass.async_add_executor_job(todo_store.edit, todo.uid, todo)
|
||||
await self.async_save()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_delete_todo_items(self, uids: list[str]) -> None:
|
||||
"""Delete an item from the To-do list."""
|
||||
store = self._new_todo_store()
|
||||
for uid in uids:
|
||||
store.delete(uid)
|
||||
await self.async_save()
|
||||
async with self._calendar_lock:
|
||||
for uid in uids:
|
||||
store.delete(uid)
|
||||
await self.async_save()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_move_todo_item(
|
||||
|
@ -184,23 +191,24 @@ class LocalTodoListEntity(TodoListEntity):
|
|||
"""Re-order an item to the To-do list."""
|
||||
if uid == previous_uid:
|
||||
return
|
||||
todos = self._calendar.todos
|
||||
item_idx: dict[str, int] = {itm.uid: idx for idx, itm in enumerate(todos)}
|
||||
if uid not in item_idx:
|
||||
raise HomeAssistantError(
|
||||
"Item '{uid}' not found in todo list {self.entity_id}"
|
||||
)
|
||||
if previous_uid and previous_uid not in item_idx:
|
||||
raise HomeAssistantError(
|
||||
"Item '{previous_uid}' not found in todo list {self.entity_id}"
|
||||
)
|
||||
dst_idx = item_idx[previous_uid] + 1 if previous_uid else 0
|
||||
src_idx = item_idx[uid]
|
||||
src_item = todos.pop(src_idx)
|
||||
if dst_idx > src_idx:
|
||||
dst_idx -= 1
|
||||
todos.insert(dst_idx, src_item)
|
||||
await self.async_save()
|
||||
async with self._calendar_lock:
|
||||
todos = self._calendar.todos
|
||||
item_idx: dict[str, int] = {itm.uid: idx for idx, itm in enumerate(todos)}
|
||||
if uid not in item_idx:
|
||||
raise HomeAssistantError(
|
||||
"Item '{uid}' not found in todo list {self.entity_id}"
|
||||
)
|
||||
if previous_uid and previous_uid not in item_idx:
|
||||
raise HomeAssistantError(
|
||||
"Item '{previous_uid}' not found in todo list {self.entity_id}"
|
||||
)
|
||||
dst_idx = item_idx[previous_uid] + 1 if previous_uid else 0
|
||||
src_idx = item_idx[uid]
|
||||
src_item = todos.pop(src_idx)
|
||||
if dst_idx > src_idx:
|
||||
dst_idx -= 1
|
||||
todos.insert(dst_idx, src_item)
|
||||
await self.async_save()
|
||||
await self.async_update_ha_state(force_refresh=True)
|
||||
|
||||
async def async_save(self) -> None:
|
||||
|
|
Loading…
Reference in New Issue