Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dozed fix avoid recurrence id duplicate #445

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion caldav/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2006,7 +2006,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
60 changes: 59 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 @@ -2406,7 +2436,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 @@ -2484,6 +2514,34 @@ 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
Loading