Fix adding/updating todo items with due date in CalDAV integration (#105435)

* refactor: return date/datetime for due date

* fix: explicitly set due date on vTODO component

Using `set_due` automatically handles converting the Python-native
date/datetime values to the correct representation required by RFC5545.

* fix: fix tests with changed due date handling

* fix: item.due may not be a str

* refactor: keep local timezone of due datetime

* refactor: reorder import statement

To make ruff happy.

* fix: fix false-positive mypy error
This commit is contained in:
Florian B 2023-12-10 17:23:05 +01:00 committed by GitHub
parent 6a3c422d2f
commit 063ac53f01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 9 deletions

View File

@ -98,10 +98,7 @@ def _to_ics_fields(item: TodoItem) -> dict[str, Any]:
if status := item.status: if status := item.status:
item_data["status"] = TODO_STATUS_MAP_INV.get(status, "NEEDS-ACTION") item_data["status"] = TODO_STATUS_MAP_INV.get(status, "NEEDS-ACTION")
if due := item.due: if due := item.due:
if isinstance(due, datetime): item_data["due"] = due
item_data["due"] = dt_util.as_utc(due).strftime("%Y%m%dT%H%M%SZ")
else:
item_data["due"] = due.strftime("%Y%m%d")
if description := item.description: if description := item.description:
item_data["description"] = description item_data["description"] = description
return item_data return item_data
@ -162,7 +159,10 @@ class WebDavTodoListEntity(TodoListEntity):
except (requests.ConnectionError, DAVError) as err: except (requests.ConnectionError, DAVError) as err:
raise HomeAssistantError(f"CalDAV lookup error: {err}") from err raise HomeAssistantError(f"CalDAV lookup error: {err}") from err
vtodo = todo.icalendar_component # type: ignore[attr-defined] vtodo = todo.icalendar_component # type: ignore[attr-defined]
vtodo.update(**_to_ics_fields(item)) updated_fields = _to_ics_fields(item)
if "due" in updated_fields:
todo.set_due(updated_fields.pop("due")) # type: ignore[attr-defined]
vtodo.update(**updated_fields)
try: try:
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
partial( partial(

View File

@ -1,4 +1,5 @@
"""The tests for the webdav todo component.""" """The tests for the webdav todo component."""
from datetime import UTC, date, datetime
from typing import Any from typing import Any
from unittest.mock import MagicMock, Mock from unittest.mock import MagicMock, Mock
@ -200,12 +201,16 @@ async def test_supported_components(
), ),
( (
{"due_date": "2023-11-18"}, {"due_date": "2023-11-18"},
{"status": "NEEDS-ACTION", "summary": "Cheese", "due": "20231118"}, {"status": "NEEDS-ACTION", "summary": "Cheese", "due": date(2023, 11, 18)},
{**RESULT_ITEM, "due": "2023-11-18"}, {**RESULT_ITEM, "due": "2023-11-18"},
), ),
( (
{"due_datetime": "2023-11-18T08:30:00-06:00"}, {"due_datetime": "2023-11-18T08:30:00-06:00"},
{"status": "NEEDS-ACTION", "summary": "Cheese", "due": "20231118T143000Z"}, {
"status": "NEEDS-ACTION",
"summary": "Cheese",
"due": datetime(2023, 11, 18, 14, 30, 00, tzinfo=UTC),
},
{**RESULT_ITEM, "due": "2023-11-18T08:30:00-06:00"}, {**RESULT_ITEM, "due": "2023-11-18T08:30:00-06:00"},
), ),
( (
@ -311,13 +316,13 @@ async def test_add_item_failure(
), ),
( (
{"due_date": "2023-11-18"}, {"due_date": "2023-11-18"},
["SUMMARY:Cheese", "DUE:20231118"], ["SUMMARY:Cheese", "DUE;VALUE=DATE:20231118"],
"1", "1",
{**RESULT_ITEM, "due": "2023-11-18"}, {**RESULT_ITEM, "due": "2023-11-18"},
), ),
( (
{"due_datetime": "2023-11-18T08:30:00-06:00"}, {"due_datetime": "2023-11-18T08:30:00-06:00"},
["SUMMARY:Cheese", "DUE:20231118T143000Z"], ["SUMMARY:Cheese", "DUE;TZID=America/Regina:20231118T083000"],
"1", "1",
{**RESULT_ITEM, "due": "2023-11-18T08:30:00-06:00"}, {**RESULT_ITEM, "due": "2023-11-18T08:30:00-06:00"},
), ),