From 29d4472cb75d665cff1cc7ec7911c7cbbb3f5d04 Mon Sep 17 00:00:00 2001 From: Pierre Brassart Date: Tue, 11 Aug 2026 16:26:02 +0100 Subject: [PATCH 1/5] Fix non-conformant CalDAV PRIORITY of empty string --- syncall/tw_caldav_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncall/tw_caldav_utils.py b/syncall/tw_caldav_utils.py index 3cf7dc7..edffa5d 100644 --- a/syncall/tw_caldav_utils.py +++ b/syncall/tw_caldav_utils.py @@ -92,7 +92,7 @@ def convert_tw_to_caldav(tw_item: Item) -> Item: if "priority" in tw_item: caldav_item["priority"] = aliases_tw_caldav_priority[tw_item["priority"].lower()] else: - caldav_item["priority"] = "" + caldav_item["priority"] = None # Timestamps if "entry" in tw_item: From 11a08ef998488df6f0ce2d3346b73343cb13dc0d Mon Sep 17 00:00:00 2001 From: Pierre Brassart Date: Tue, 11 Aug 2026 17:26:09 +0100 Subject: [PATCH 2/5] Fixed incorrectly updated VTODO with empty priority --- syncall/caldav/caldav_side.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/syncall/caldav/caldav_side.py b/syncall/caldav/caldav_side.py index 4e97d07..747d32f 100644 --- a/syncall/caldav/caldav_side.py +++ b/syncall/caldav/caldav_side.py @@ -75,7 +75,11 @@ def get_all_items(self, **kargs): # Format & cache items from ics files for t in raw_todos: - data = icalendar_component(t) + try: + data = icalendar_component(t) + except Exception as E: + logger.warning(f"Skipping unparsable calendar object (url={t.url}, {err})") + continue item = map_ics_to_item(data) todos.append(item) self._items_cache[item["id"]] = item @@ -132,7 +136,12 @@ def set_(key: str, val: Any): # noqa: ANN401 set_(key, vText(value.upper())) if key in ["due", "created", "last-modified"]: set_(key, vDatetime(value)) - if key in ["priority", "description", "summary"]: + if key == "priority": + if value in (None, ""): + icalendar_component(todo).pop("priority", None) + else: + set_(key, vText(value)) + if key in ["description", "summary"]: set_(key, vText(value)) if key == "categories": set_(key, vCategory([vText(cat) for cat in value])) From d1e28c8d82d7113ecdc49d77f4a41802b61e415f Mon Sep 17 00:00:00 2001 From: Pierre Brassart Date: Tue, 11 Aug 2026 17:42:34 +0100 Subject: [PATCH 3/5] Fix error value --- syncall/caldav/caldav_side.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncall/caldav/caldav_side.py b/syncall/caldav/caldav_side.py index 747d32f..77838dd 100644 --- a/syncall/caldav/caldav_side.py +++ b/syncall/caldav/caldav_side.py @@ -77,7 +77,7 @@ def get_all_items(self, **kargs): for t in raw_todos: try: data = icalendar_component(t) - except Exception as E: + except Exception as err: logger.warning(f"Skipping unparsable calendar object (url={t.url}, {err})") continue item = map_ics_to_item(data) From 97bc97d53c952757429fa7de32c08372b72c8cf2 Mon Sep 17 00:00:00 2001 From: Pierre Brassart Date: Thu, 13 Aug 2026 11:22:13 +0100 Subject: [PATCH 4/5] Reformatting due to linter failure --- syncall/caldav/caldav_side.py | 43 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/syncall/caldav/caldav_side.py b/syncall/caldav/caldav_side.py index 77838dd..66097fc 100644 --- a/syncall/caldav/caldav_side.py +++ b/syncall/caldav/caldav_side.py @@ -77,10 +77,10 @@ def get_all_items(self, **kargs): for t in raw_todos: try: data = icalendar_component(t) - except Exception as err: - logger.warning(f"Skipping unparsable calendar object (url={t.url}, {err})") + item = map_ics_to_item(data) + except Exception as err: # noqa: BLE001 + logger.warning(f"Skipping unparsable calendar object (url={t.url}: {err})") continue - item = map_ics_to_item(data) todos.append(item) self._items_cache[item["id"]] = item @@ -114,6 +114,25 @@ def delete_single_item(self, item_id: ID): if todo is not None: todo.delete() + def _update_todo_changes(self, todo, **changes): + def set_(key: str, val: Any): # noqa: ANN401 + icalendar_component(todo)[key] = val + + for key, value in changes.items(): + if key == "status": + set_(key, vText(value.upper())) + elif key in ["due", "created", "last-modified"]: + set_(key, vDatetime(value)) + elif key == "priority": + if value: + set_(key, vText(value)) + else: + icalendar_component(todo).pop("priority", None) + elif key in ["description", "summary"]: + set_(key, vText(value)) + elif key == "categories": + set_(key, vCategory([vText(cat) for cat in value])) + def update_item(self, item_id: ID, **changes): todo = self._find_todo_by_id_raw(item_id=item_id) if todo is None: @@ -124,27 +143,11 @@ def update_item(self, item_id: ID, **changes): logger.opt(lazy=True).debug(f"Can't update item {item_id}\n\nchanges: {changes}") return - def set_(key: str, val: Any): # noqa: ANN401 - icalendar_component(todo)[key] = val - # pop the key:value (s) that we're intending to potentially update for key in self._identical_comparison_keys: icalendar_component(todo).pop(key) - for key, value in changes.items(): - if key == "status": - set_(key, vText(value.upper())) - if key in ["due", "created", "last-modified"]: - set_(key, vDatetime(value)) - if key == "priority": - if value in (None, ""): - icalendar_component(todo).pop("priority", None) - else: - set_(key, vText(value)) - if key in ["description", "summary"]: - set_(key, vText(value)) - if key == "categories": - set_(key, vCategory([vText(cat) for cat in value])) + self._update_todo_changes(todo, changes) todo.save() From b510bfd62167d210b2dda678733bebd0d9c2b1e2 Mon Sep 17 00:00:00 2001 From: Pierre Brassart Date: Thu, 13 Aug 2026 12:13:31 +0100 Subject: [PATCH 5/5] Fixed typo --- syncall/caldav/caldav_side.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncall/caldav/caldav_side.py b/syncall/caldav/caldav_side.py index 66097fc..5363b80 100644 --- a/syncall/caldav/caldav_side.py +++ b/syncall/caldav/caldav_side.py @@ -147,7 +147,7 @@ def update_item(self, item_id: ID, **changes): for key in self._identical_comparison_keys: icalendar_component(todo).pop(key) - self._update_todo_changes(todo, changes) + self._update_todo_changes(todo, **changes) todo.save()