diff --git a/homeassistant/components/todoist/const.py b/homeassistant/components/todoist/const.py index be95d57dd2c..f96a5fc6527 100644 --- a/homeassistant/components/todoist/const.py +++ b/homeassistant/components/todoist/const.py @@ -93,4 +93,7 @@ COLLABORATORS: Final = "collaborators" DOMAIN: Final = "todoist" +# Maximum number of items per page for Todoist API requests +MAX_PAGE_SIZE: Final = 200 + SERVICE_NEW_TASK: Final = "new_task" diff --git a/homeassistant/components/todoist/coordinator.py b/homeassistant/components/todoist/coordinator.py index 8bdf35ceaf5..41e7602836e 100644 --- a/homeassistant/components/todoist/coordinator.py +++ b/homeassistant/components/todoist/coordinator.py @@ -1,5 +1,6 @@ """DataUpdateCoordinator for the Todoist component.""" +import asyncio from collections.abc import AsyncGenerator from datetime import timedelta import logging @@ -12,6 +13,8 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed +from .const import MAX_PAGE_SIZE + T = TypeVar("T") @@ -53,26 +56,30 @@ class TodoistCoordinator(DataUpdateCoordinator[list[Task]]): async def _async_update_data(self) -> list[Task]: """Fetch tasks from the Todoist API.""" try: - tasks_async = await self.api.get_tasks() + tasks_async = await self.api.get_tasks(limit=MAX_PAGE_SIZE) + return await flatten_async_pages(tasks_async) + except asyncio.CancelledError: + raise except Exception as err: raise UpdateFailed(f"Error communicating with API: {err}") from err - return await flatten_async_pages(tasks_async) async def async_get_projects(self) -> list[Project]: """Return todoist projects fetched at most once.""" if self._projects is None: - projects_async = await self.api.get_projects() + projects_async = await self.api.get_projects(limit=MAX_PAGE_SIZE) self._projects = await flatten_async_pages(projects_async) return self._projects async def async_get_sections(self, project_id: str) -> list[Section]: """Return todoist sections for a given project ID.""" - sections_async = await self.api.get_sections(project_id=project_id) + sections_async = await self.api.get_sections( + project_id=project_id, limit=MAX_PAGE_SIZE + ) return await flatten_async_pages(sections_async) async def async_get_labels(self) -> list[Label]: """Return todoist labels fetched at most once.""" if self._labels is None: - labels_async = await self.api.get_labels() + labels_async = await self.api.get_labels(limit=MAX_PAGE_SIZE) self._labels = await flatten_async_pages(labels_async) return self._labels diff --git a/tests/components/todoist/conftest.py b/tests/components/todoist/conftest.py index 2b8bf169142..ded828769f0 100644 --- a/tests/components/todoist/conftest.py +++ b/tests/components/todoist/conftest.py @@ -8,6 +8,7 @@ from unittest.mock import AsyncMock, patch import pytest from requests.exceptions import HTTPError from requests.models import Response +from todoist_api_python.api_async import TodoistAPIAsync from todoist_api_python.models import Collaborator, Due, Label, Project, Section, Task from homeassistant.components.todoist import DOMAIN @@ -126,7 +127,7 @@ def mock_tasks(due: Due) -> list[Task]: @pytest.fixture(name="api") def mock_api(tasks: list[Task]) -> AsyncMock: """Mock the api state.""" - api = AsyncMock() + api = AsyncMock(spec=TodoistAPIAsync) api.get_projects.side_effect = make_api_response( [ Project(