Skip to content

Commit

Permalink
Fixed duplicate RECURRENCE-ID when expanding events
Browse files Browse the repository at this point in the history
  • Loading branch information
dozed authored and tobixen committed Oct 26, 2024
1 parent 42acfde commit 4fa67d2
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
3 changes: 2 additions & 1 deletion caldav/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2027,7 +2027,8 @@ def expand_rrule(self, start: datetime, end: datetime) -> None:
calendar = self.icalendar_instance
calendar.subcomponents = []
for occurrence in recurrings:
occurrence.add("RECURRENCE-ID", occurrence.get("DTSTART"))
if "RECURRENCE-ID" not in occurrence:
occurrence.add("RECURRENCE-ID", occurrence.get("DTSTART"))
calendar.add_component(occurrence)
# add other components (except for the VEVENT itself and VTIMEZONE which is not allowed on occurrence events)
for component in stripped_event.icalendar_instance.subcomponents:
Expand Down
56 changes: 55 additions & 1 deletion tests/test_caldav.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from datetime import timedelta
from datetime import timezone

import icalendar
import pytest
import requests
import vobject
Expand Down Expand Up @@ -174,6 +175,35 @@
END:VEVENT
END:VCALENDAR"""

# example created by editing a specific occurrence of a recurrent event via Thunderbird
evr2 = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
BEGIN:VEVENT
UID:c26921f4-0653-11ef-b756-58ce2a14e2e5
DTSTART;VALUE=DATE:20240411
DTEND;VALUE=DATE:20240412
DTSTAMP:20240429T181103Z
LAST-MODIFIED:20240429T181103Z
RRULE:FREQ=WEEKLY;INTERVAL=2
SEQUENCE:1
SUMMARY:Test
X-MOZ-GENERATION:1
END:VEVENT
BEGIN:VEVENT
UID:c26921f4-0653-11ef-b756-58ce2a14e2e5
RECURRENCE-ID;VALUE=DATE:20240425
DTSTART;VALUE=DATE:20240425
DTEND;VALUE=DATE:20240426
CREATED:20240429T181031Z
DTSTAMP:20240429T181103Z
LAST-MODIFIED:20240429T181103Z
SEQUENCE:1
SUMMARY:Test (edited)
X-MOZ-GENERATION:1
END:VEVENT
END:VCALENDAR"""

# example from http://www.rfc-editor.org/rfc/rfc5545.txt
todo = """BEGIN:VCALENDAR
VERSION:2.0
Expand Down Expand Up @@ -2505,7 +2535,7 @@ def testRecurringDateSearch(self):
self.skip_on_compatibility_flag("no_search")
c = self._fixCalendar()

# evr is a yearly event starting at 1997-02-11
# evr is a yearly event starting at 1997-11-02
e = c.save_event(evr)

## Without "expand", we should still find it when searching over 2008 ...
Expand Down Expand Up @@ -2583,6 +2613,30 @@ def testRecurringDateSearch(self):
assert len(r) == 1
assert r[0].data.count("END:VEVENT") == 1

def testRecurringDateWithExceptionSearch(self):
c = self._fixCalendar()

# evr2 is a bi-weekly event starting 2024-04-11
e = c.save_event(evr2)

r = c.search(
start=datetime(2024, 3, 31, 0, 0),
end=datetime(2024, 5, 4, 0, 0, 0),
event=True,
expand=True,
)

assert len(r) == 2

assert 'RRULE' not in r[0].data
assert 'RRULE' not in r[1].data

assert isinstance(r[0].icalendar_component['RECURRENCE-ID'], icalendar.vDDDTypes)
assert r[0].icalendar_component['RECURRENCE-ID'].dt == date(2024, 4, 11)

assert isinstance(r[1].icalendar_component['RECURRENCE-ID'], icalendar.vDDDTypes)
assert r[1].icalendar_component['RECURRENCE-ID'].dt == date(2024, 4, 25)

def testOffsetURL(self):
"""
pass a URL pointing to a calendar or a user to the DAVClient class,
Expand Down

0 comments on commit 4fa67d2

Please sign in to comment.