Skip to content

Commit 65ab732

Browse files
authored
New methods Event.set_dtend and CalendarObjectResource.set_end
Fixes collective/icalendar#496 (#499)
1 parent 286787a commit 65ab732

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

caldav/calendarobjectresource.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,28 @@ def __init__(
129129
old_id = self.icalendar_component.pop("UID", None)
130130
self.icalendar_component.add("UID", id)
131131

132+
def set_end(self, end, move_dtstart=False):
133+
"""The RFC specifies that a VEVENT/VTODO cannot have both
134+
dtend/due and duration, so when setting dtend/due, the duration
135+
field must be evicted
136+
137+
WARNING: this method is likely to be deprecated and parts of
138+
it moved to the icalendar library. If you decide to use it,
139+
please put caldav<3.0 in the requirements.
140+
"""
141+
i = self.icalendar_component
142+
if hasattr(end, "tzinfo") and not end.tzinfo:
143+
end = end.astimezone(timezone.utc)
144+
duration = self.get_duration()
145+
i.pop("DURATION", None)
146+
i.pop(self._ENDPARAM, None)
147+
148+
if move_dtstart and duration and "DTSTART" in i:
149+
i.pop("DTSTART")
150+
i.add("DTSTART", end - duration)
151+
152+
i.add(self._ENDPARAM, end)
153+
132154
def add_organizer(self) -> None:
133155
"""
134156
goes via self.client, finds the principal, figures out the right attendee-format and adds an
@@ -1027,13 +1049,13 @@ class Event(CalendarObjectResource):
10271049
"""
10281050
The `Event` object is used to represent an event (VEVENT).
10291051
1030-
As of 2020-12 it adds nothing to the inheritated class. (I have
1052+
As of 2020-12 it adds very little to the inheritated class. (I have
10311053
frequently asked myself if we need those subclasses ... perhaps
10321054
not)
10331055
"""
10341056

1057+
set_dtend = CalendarObjectResource.set_end
10351058
_ENDPARAM = "DTEND"
1036-
pass
10371059

10381060

10391061
class Journal(CalendarObjectResource):
@@ -1073,9 +1095,13 @@ def __init__(
10731095

10741096
class Todo(CalendarObjectResource):
10751097
"""The `Todo` object is used to represent a todo item (VTODO). A
1076-
Todo-object can be completed. Extra logic for different ways to
1077-
complete one recurrence of a recurrent todo. Extra logic to
1078-
handle due vs duration.
1098+
Todo-object can be completed.
1099+
1100+
There is some extra logic here - arguably none of it belongs to
1101+
the caldav library, and should be moved either to the icalendar
1102+
library or to the plann library (plann is a cli-tool, should
1103+
probably be split up into one library for advanced calendaring
1104+
operations and the cli-tool as separate packages)
10791105
"""
10801106

10811107
_ENDPARAM = "DUE"
@@ -1421,7 +1447,7 @@ def set_due(self, due, move_dtstart=False, check_dependent=False):
14211447
please put caldav<2.0 in the requirements.
14221448
14231449
WARNING: the check_dependent-logic may be rewritten to support
1424-
RFC9253 in 1.x already
1450+
RFC9253 in 3.x
14251451
"""
14261452
i = self.icalendar_component
14271453
if hasattr(due, "tzinfo") and not due.tzinfo:
@@ -1440,12 +1466,6 @@ def set_due(self, due, move_dtstart=False, check_dependent=False):
14401466
raise error.ConsistencyError(
14411467
"parent object has due/end %s, cannot procrastinate child object without first procrastinating parent object"
14421468
)
1443-
duration = self.get_duration()
1444-
i.pop("DURATION", None)
1445-
i.pop("DUE", None)
1446-
1447-
if move_dtstart and duration and "DTSTART" in i:
1448-
i.pop("DTSTART")
1449-
i.add("DTSTART", due - duration)
1469+
CalendarObjectResource.set_end(self, due, move_dtstart)
14501470

1451-
i.add("DUE", due)
1471+
set_end = set_due

0 commit comments

Comments
 (0)