From e6f0659cbf2cd466e1db96b43ea6401f26f3b08c Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 13 Sep 2026 00:13:29 +0200 Subject: [PATCH] =?UTF-8?q?fix(caldav):=20ignorer=20les=20=C3=A9v=C3=A9nem?= =?UTF-8?q?ents=20g=C3=A9r=C3=A9s=20sans=20UID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #47 Co-authored-by: Codex --- .secrets.baseline | 4 ++-- pronote_sync/sync/caldav.py | 6 +++++- tests/unit/test_caldav_gateway.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 7cb5390..6ea4938 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -156,7 +156,7 @@ "filename": "tests/unit/test_caldav_gateway.py", "hashed_secret": "1c58bd92003bbaa0538e249fff6ee19a270dec5f", "is_verified": false, - "line_number": 763 + "line_number": 794 } ], "tests/unit/test_caldav_security.py": [ @@ -185,5 +185,5 @@ } ] }, - "generated_at": "2026-09-12T17:57:39Z" + "generated_at": "2026-09-12T22:12:56Z" } diff --git a/pronote_sync/sync/caldav.py b/pronote_sync/sync/caldav.py index 5ad6c60..4839a3d 100644 --- a/pronote_sync/sync/caldav.py +++ b/pronote_sync/sync/caldav.py @@ -191,7 +191,11 @@ class CalDAVGateway: for vevent in component.walk("VEVENT"): managed = vevent.get(MANAGED_PROPERTY) if managed is not None and str(managed) == MANAGED_VALUE: - raw_uid = str(vevent.get("UID")) + raw_uid_value = vevent.get("UID") + if raw_uid_value is None or not str(raw_uid_value).strip(): + logger.warning("Événement CalDAV géré sans UID ignoré.") + continue + raw_uid = str(raw_uid_value) canonical_uid = normalize_pronote_uid(raw_uid) result.append((raw_uid, canonical_uid, vevent)) except Exception as exc: diff --git a/tests/unit/test_caldav_gateway.py b/tests/unit/test_caldav_gateway.py index f6088a4..abcbd27 100644 --- a/tests/unit/test_caldav_gateway.py +++ b/tests/unit/test_caldav_gateway.py @@ -327,6 +327,37 @@ def test_list_managed_events_returns_only_managed( assert str(vevent.get("UID")) == "test-uid-123" +def test_list_managed_events_ignores_managed_event_without_uid( + caldav_settings: CalDAVSettings, + mock_client_factory: MagicMock, + caplog: LogCaptureFixture, +) -> None: + """Ignore un événement géré sans UID et ne le transmet pas au planificateur. + + :param caldav_settings: Paramètres CalDAV valides. + :param mock_client_factory: Usine de clients CalDAV mockée. + :param caplog: Capture des journaux de diagnostic. + :return: None + """ + gateway = CalDAVGateway(caldav_settings, client_factory=mock_client_factory) + gateway.connect() + + malformed_event = Event() + malformed_event.add("SUMMARY", "Événement sans identifiant") + malformed_event.add(MANAGED_PROPERTY, MANAGED_VALUE) + remote_event = MagicMock() + remote_event.icalendar_component = Calendar() + remote_event.icalendar_component.add_component(malformed_event) + calendar = mock_client_factory.return_value.principal.return_value.calendars.return_value[0] + calendar.search.return_value = [remote_event] + + with caplog.at_level(logging.WARNING): + result = gateway.list_managed_events(datetime(2026, 1, 1), datetime(2026, 12, 31)) + + assert result == [] + assert "sans UID ignoré" in caplog.text + + def test_list_managed_events_not_connected_raises( caldav_settings: CalDAVSettings, ) -> None: