From 3cf268bd2e76636e5d08e9977a0c89af51c5ce89 Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Sat, 24 May 2025 22:11:35 +0200 Subject: [PATCH 1/2] fixes https://github.com/python-caldav/caldav/issues/163 and fixes https://github.com/python-caldav/caldav/issues/125 --- caldav/calendarobjectresource.py | 6 +++++- tests/test_caldav.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/caldav/calendarobjectresource.py b/caldav/calendarobjectresource.py index 7e183b41..95280cc5 100644 --- a/caldav/calendarobjectresource.py +++ b/caldav/calendarobjectresource.py @@ -543,6 +543,10 @@ def is_invite_request(self) -> bool: self.load(only_if_unloaded=True) return self.icalendar_instance.get("method", None) == "REQUEST" + def is_invite_reply(self) -> bool: + self.load(only_if_unloaded=True) + return self.icalendar_instance.get("method", None) == "REPLY" + def accept_invite(self, calendar: Optional["Calendar"] = None) -> None: self._reply_to_invite_request("ACCEPTED", calendar) @@ -729,7 +733,7 @@ def change_attendee_status(self, attendee: Optional[Any] = None, **kwargs) -> No if self.client is None: raise ValueError("Unexpected value None for self.client") - attendee = self.client.principal_address or self.client.principal() + attendee = self.client.principal() cnt = 0 diff --git a/tests/test_caldav.py b/tests/test_caldav.py index 54e54c2b..80f61013 100644 --- a/tests/test_caldav.py +++ b/tests/test_caldav.py @@ -490,7 +490,7 @@ def teardown_method(self): except error.NotFoundError: pass for c in self.clients: - c.teardown() + c.teardown(c) ## TODO # def testFreeBusy(self): From 9bcca6d96455c4fe0ec6a4abea3e26ee664f2292 Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Sun, 25 May 2025 05:13:01 +0200 Subject: [PATCH 2/2] started deprecating some methods that have been moved to icalendar library --- caldav/calendarobjectresource.py | 48 ++++++++------------------------ 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/caldav/calendarobjectresource.py b/caldav/calendarobjectresource.py index 95280cc5..9946fd83 100644 --- a/caldav/calendarobjectresource.py +++ b/caldav/calendarobjectresource.py @@ -456,19 +456,10 @@ def get_due(self): """ A VTODO may have due or duration set. Return or calculate due. - WARNING: this method is likely to be deprecated and moved to - the icalendar library. If you decide to use it, please put - caldav<2.0 in the requirements. + DEPRECATION WARNING: this method is likely to be removed in + caldav v3.0. Use self.icalendar.end instead. """ - i = self.icalendar_component - if "DUE" in i: - return i["DUE"].dt - elif "DTEND" in i: - return i["DTEND"].dt - elif "DURATION" in i and "DTSTART" in i: - return i["DTSTART"].dt + i["DURATION"].dt - else: - return None + return self.icalendar_component.end get_dtend = get_due @@ -976,7 +967,10 @@ def _get_icalendar_instance(self): ) def get_duration(self) -> timedelta: - """According to the RFC, either DURATION or DUE should be set + """ + DEPRECATION WARNING: This method may be removed in version 3.0 + + According to the RFC, either DURATION or DUE should be set for a task, but never both - implicitly meaning that DURATION is the difference between DTSTART and DUE (personally I believe that's stupid. If a task takes five minutes to @@ -997,29 +991,11 @@ def get_duration(self) -> timedelta: the icalendar library. If you decide to use it, please put caldav<3.0 in the requirements. """ - i = self.icalendar_component - return self._get_duration(i) - - def _get_duration(self, i): - if "DURATION" in i: - return i["DURATION"].dt - elif "DTSTART" in i and self._ENDPARAM in i: - end = i[self._ENDPARAM].dt - start = i["DTSTART"].dt - ## We do have a problem here if one is a date and the other is a - ## datetime. This is NOT explicitly defined as a technical - ## breach in the RFC, so we need to work around it. - if isinstance(end, datetime) != isinstance(start, datetime): - start = datetime(start.year, start.month, start.day) - end = datetime(end.year, end.month, end.day) - return end - start - elif "DTSTART" in i and not isinstance(i["DTSTART"], datetime): - return timedelta(days=1) - else: - return timedelta(0) + return self.icalendar_component.duration + ## DEPRECATION WARNING: ## for backward-compatibility - may be changed to - ## icalendar_instance in version 1.0 + ## icalendar_instance in version 3.0 instance: VBase = vobject_instance @@ -1168,7 +1144,7 @@ def _next(self, ts=None, i=None, dtstart=None, rrule=None, by=None, no_count=Tru else: dtstart = ts or datetime.now() else: - dtstart = ts or datetime.now() - self._get_duration(i) + dtstart = ts or datetime.now() - i.duration ## dtstart should be compared to the completion timestamp, which ## is set in UTC in the complete() method. However, dtstart ## may be a naïve or a floating timestamp @@ -1303,7 +1279,7 @@ def _complete_recurring_thisandfuture(self, completion_timestamp) -> None: rrule = rrule2 or rrule - duration = self._get_duration(i=prev) + duration = prev.duration thisandfuture.pop("DTSTART", None) thisandfuture.pop("DUE", None) next_dtstart = self._next(i=prev, rrule=rrule, ts=completion_timestamp)