diff --git a/radicale/app/report.py b/radicale/app/report.py index 08e1fed3..dc9638b5 100644 --- a/radicale/app/report.py +++ b/radicale/app/report.py @@ -207,30 +207,23 @@ def _expand( expanded = None for recurrence_dt in recurrences: - expanded_item_ = copy.copy(expanded_item) - - try: - delattr(expanded_item_.vobject_item.vevent, 'recurrence-id') - except AttributeError: - pass + vobject_item = copy.copy(expanded_item.vobject_item) recurrence_utc = recurrence_dt.astimezone(datetime.timezone.utc) - vevent = copy.deepcopy(expanded_item_.vobject_item.vevent) - recurrence_id = ContentLine( + vevent = copy.deepcopy(vobject_item.vevent) + vevent.recurrence_id = ContentLine( name='RECURRENCE-ID', value=recurrence_utc.strftime('%Y%m%dT%H%M%SZ'), params={} ) - vevent.add(recurrence_id) if expanded is None: - expanded_item_.vobject_item.vevent.add(recurrence_id) - expanded_item_.vobject_item.remove(expanded_item_.vobject_item.vevent) - expanded = expanded_item_ + vobject_item.vevent = vevent + expanded = vobject_item else: - expanded.vobject_item.add(vevent) + expanded.add(vevent) - element.text = expanded.vobject_item.serialize() + element.text = expanded.serialize() else: element.text = expanded_item.vobject_item.serialize() diff --git a/radicale/tests/test_base.py b/radicale/tests/test_base.py index 6c1ac1b3..0743dd6c 100644 --- a/radicale/tests/test_base.py +++ b/radicale/tests/test_base.py @@ -1527,8 +1527,44 @@ permissions: RrWw""") def test_report_with_expand_property(self) -> None: self.put("/calendar.ics/", get_file_content("event_daily_rrule.ics")) + req_body_without_expand = \ + """ + + + + + + + + + + + + + + """ + _, responses = self.report("/calendar.ics/", req_body_without_expand) + assert len(responses) == 1 - req_body = \ + response = responses['/calendar.ics/event_daily_rrule.ics'] + status, element = list(response.values())[0] + + assert status == 200 + + assert "RRULE" in element.text + assert "BEGIN:VTIMEZONE" in element.text + assert "RECURRENCE-ID" not in element.text + + uids = [] + for line in element.text.split("\n"): + if line.startswith("UID:"): + uid = line[len("UID:"):] + assert uid == "event_daily_rrule" + uids.append(uids) + + assert len(uids) == 1 + + req_body_with_expand = \ """ @@ -1546,27 +1582,29 @@ permissions: RrWw""") """ - # status, _, answer = self.request("REPORT", "/calendar.ics/", req_body, check=207) - # print(status, answer) + _, responses = self.report("/calendar.ics/", req_body_with_expand) - _, responses = self.report("/calendar.ics/", req_body) assert len(responses) == 1 + response = responses['/calendar.ics/event_daily_rrule.ics'] status, element = list(response.values())[0] - assert status == 200 - print("resp", status, element, flush=True) + assert status == 200 + assert "RRULE" not in element.text + assert "BEGIN:VTIMEZONE" not in element.text uids = [] + recurrence_ids = [] for line in element.text.split("\n"): - print("line", line, line.startswith("UID:")) if line.startswith("UID:"): - uid = line[len("UID:"):] - assert uid == "event_daily_rrule" + assert line == "UID:event_daily_rrule" uids.append(uids) - assert len(uids) == 3 - assert False + if line.startswith("RECURRENCE-ID:"): + recurrence_ids.append(line) + + assert len(uids) == 2 + assert len(set(recurrence_ids)) == 2 def test_propfind_sync_token(self) -> None: """Retrieve the sync-token with a propfind request"""