summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2016-05-06 14:20:13 +0200
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2016-05-06 14:21:47 +0200
commit899fd8ec78ae03907f7a52b6764d25a2ff9b5cdd (patch)
treeb77deda9ad3c3fe30a710cb5b6d889aea9db8651
parent249343c34f948757426538e245dafbad7fe38aa9 (diff)
downloadpykolab-899fd8ec78ae03907f7a52b6764d25a2ff9b5cdd.tar.gz
Add RDATE support (#5401)
Summary: Fixes #5401 Reviewers: #pykolab_developers, vanmeeuwen Reviewed By: #pykolab_developers, vanmeeuwen Subscribers: vanmeeuwen Differential Revision: https://git.kolab.org/D139
-rw-r--r--pykolab/xml/event.py50
-rw-r--r--tests/unit/test-003-event.py44
2 files changed, 93 insertions, 1 deletions
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index e064b0c..40dfaba 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -152,6 +152,23 @@ class Event(object):
self._categories.append(ustr(category))
self.event.setCategories(self._categories)
+ def add_recurrence_date(self, _datetime):
+ valid_datetime = False
+ if isinstance(_datetime, datetime.date):
+ valid_datetime = True
+
+ if isinstance(_datetime, datetime.datetime):
+ # If no timezone information is passed on, make it UTC
+ if _datetime.tzinfo is None:
+ _datetime = _datetime.replace(tzinfo=pytz.utc)
+
+ valid_datetime = True
+
+ if not valid_datetime:
+ raise InvalidEventDateError, _("Rdate needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime))
+
+ self.event.addRecurrenceDate(xmlutils.to_cdatetime(_datetime, True))
+
def add_exception_date(self, _datetime):
valid_datetime = False
if isinstance(_datetime, datetime.date):
@@ -481,6 +498,9 @@ class Event(object):
return "%s - %s" % (start.strftime(date_format + " " + time_format), end.strftime(end_format))
+ def get_recurrence_dates(self):
+ return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.recurrenceDates())
+
def get_exception_dates(self):
return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates())
@@ -665,6 +685,13 @@ class Event(object):
result.append(rrule.to_ical())
return result
+ def get_ical_rdate(self):
+ rdates = self.get_recurrence_dates()
+ for i in range(len(rdates)):
+ rdates[i] = icalendar.prop.vDDDLists(rdates[i])
+
+ return rdates
+
def get_location(self):
return self.event.location()
@@ -829,6 +856,10 @@ class Event(object):
for _datetime in _datetimes:
self.add_exception_date(_datetime)
+ def set_recurrence_dates(self, _datetimes):
+ for _datetime in _datetimes:
+ self.add_recurrence_date(_datetime)
+
def add_custom_property(self, name, value):
if not name.upper().startswith('X-'):
raise ValueError, _("Invalid custom property name %r") % (name)
@@ -946,6 +977,23 @@ class Event(object):
def set_ical_uid(self, uid):
self.set_uid(str(uid))
+ def set_ical_rdate(self, rdate):
+ rdates = []
+ # rdate here can be vDDDLists or a list of vDDDLists, why?!
+ if isinstance(rdate, icalendar.prop.vDDDLists):
+ rdate = [rdate]
+
+ for _rdate in rdate:
+ if isinstance(_rdate, icalendar.prop.vDDDLists):
+ tzid = None
+ if hasattr(_rdate, 'params') and 'TZID' in _rdate.params:
+ tzid = _rdate.params['TZID']
+ dts = icalendar.prop.vDDDLists.from_ical(_rdate.to_ical(), tzid)
+ for datetime in dts:
+ rdates.append(datetime)
+
+ self.set_recurrence_dates(rdates)
+
def set_ical_recurrenceid(self, value, params):
try:
self.thisandfuture = params.get('RANGE', '') == 'THISANDFUTURE'
@@ -1316,7 +1364,7 @@ class Event(object):
return msg
def is_recurring(self):
- return self.event.recurrenceRule().isValid()
+ return self.event.recurrenceRule().isValid() or len(self.get_recurrence_dates()) > 0
def to_event_cal(self):
from kolab.calendaring import EventCal
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
index 18b186b..a7ab82f 100644
--- a/tests/unit/test-003-event.py
+++ b/tests/unit/test-003-event.py
@@ -89,6 +89,25 @@ ORGANIZER;CN=Doe\, John:mailto:john.doe@example.org
END:VEVENT
"""
+ical_event_rdate = """
+BEGIN:VEVENT
+UID:7a35527d-f783-4b58-b404-b1389bd2fc57
+DTSTAMP;VALUE=DATE-TIME:20140407T122311Z
+CREATED;VALUE=DATE-TIME:20140407T122245Z
+LAST-MODIFIED;VALUE=DATE-TIME:20140407T122311Z
+DTSTART;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T110000
+DURATION:PT1H30M0S
+RDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140530T110000
+RDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140620T110000
+SUMMARY:Summary
+LOCATION:Location
+DESCRIPTION:Description
+SEQUENCE:2
+CLASS:PUBLIC
+ORGANIZER;CN=Doe\, John:mailto:john.doe@example.org
+END:VEVENT
+"""
+
xml_event = """
<icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">
<vcalendar>
@@ -961,6 +980,31 @@ END:VEVENT
self.assertEqual(event.get_attendee("jack@example.org").get_name(), "Jack")
self.assertRaises(ValueError, exception.get_attendee, "somebody@else.com") # not addded to exception
+ def test_028_rdate(self):
+ event = event_from_ical(ical_event_rdate)
+
+ self.assertTrue(event.is_recurring())
+ self.assertEqual(len(event.get_recurrence_dates()), 2)
+ self.assertIsInstance(event.get_recurrence_dates()[0], datetime.datetime)
+
+ rdates = event.get_recurrence_dates()
+ self.assertEqual(str(rdates[0]), "2014-05-30 11:00:00+02:00")
+ self.assertEqual(str(rdates[1]), "2014-06-20 11:00:00+02:00")
+
+ dt = datetime.datetime(2014, 8, 15, 10, 0, 0, tzinfo=pytz.timezone("Europe/Zurich"))
+ event.add_recurrence_date(dt)
+ rdates = event.get_recurrence_dates()
+ self.assertEqual(str(rdates[2]), "2014-08-15 10:00:00+02:00")
+
+ itip = event.as_string_itip()
+ rdates = []
+ for line in itip.split("\n"):
+ if re.match('^RDATE', line):
+ rdates.append(line.strip().split(':')[1])
+ self.assertEqual("TZID=Europe/Zurich", line.split(':')[0].split(';')[1])
+
+ self.assertEqual(rdates, ["20140530T110000", "20140620T110000", "20140815T100000"])
+
def _find_prop_in_list(self, diff, name):
for prop in diff:
if prop['property'] == name: