2 commits - pykolab/xml tests/unit

Thomas Brüderli bruederli at kolabsys.com
Wed Mar 5 09:33:45 CET 2014


 pykolab/xml/event.py         |   44 +++++++++++++++++++++++++++++++++++++++++--
 pykolab/xml/utils.py         |    2 -
 tests/unit/test-003-event.py |   15 +++++++++++++-
 3 files changed, 57 insertions(+), 4 deletions(-)

New commits:
commit 74c17bde3f0eb6d83730d3711c8b9d8f68c6c2dc
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Mar 4 13:58:53 2014 -0500

    Import DURATION and EXDATE properties from ical

diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index afaa088..181c270 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -183,12 +183,13 @@ class Event(object):
             if ical_event.has_key(attr):
                 self.set_from_ical(attr.lower(), ical_event[attr])
 
-        # HACK: use libkolab::EventCal::fromICal() to parse RRULEs
+        # HACK: use calendaring::EventCal::fromICal() to parse RRULEs
         if ical_event.has_key('RRULE'):
             from kolab.calendaring import EventCal
             event_xml = EventCal()
             event_xml.fromICal("BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR")
             self.event.setRecurrenceRule(event_xml.recurrenceRule())
+            self.event.setExceptionDates(event_xml.exceptionDates())
 
     def get_attendee_participant_status(self, attendee):
         return attendee.get_participant_status()
@@ -242,11 +243,30 @@ class Event(object):
     def get_description(self):
         return self.event.description()
 
+    def get_duration(self):
+        duration = self.event.duration()
+        if duration and duration.isValid():
+            dtd = datetime.timedelta(
+                days=duration.days(),
+                seconds=duration.seconds(),
+                minutes=duration.minutes(),
+                hours=duration.hours(),
+                weeks=duration.weeks()
+            )
+            return dtd
+
+        return None
+
     def get_end(self):
-        return xmlutils.from_cdatetime(self.event.end(), True)
+        dt = xmlutils.from_cdatetime(self.event.end(), True)
+        if not dt:
+            duration = self.get_duration()
+            if duration is not None:
+                dt = self.get_start() + duration
+        return dt
 
     def get_exception_dates(self):
-        return self.event.exceptionDates()
+        return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates())
 
     def get_ical_attendee(self):
         # TODO: Formatting, aye? See also the example snippet:
@@ -462,6 +482,8 @@ class Event(object):
             self.set_ical_dtend(value.dt)
         elif attr == "dtstart":
             self.set_ical_dtstart(value.dt)
+        elif attr == "duration":
+            self.set_ical_duration(value)
         elif attr == "status":
             self.set_ical_status(value)
         elif attr == "summary":
@@ -526,6 +548,11 @@ class Event(object):
     def set_ical_dtstart(self, dtstart):
         self.set_start(dtstart)
 
+    def set_ical_duration(self, value):
+        if value.dt:
+            duration = kolabformat.Duration(value.dt.days, 0, 0, value.dt.seconds, False)
+            self.event.setDuration(duration)
+
     def set_ical_organizer(self, organizer):
         address = str(organizer).split(':')[-1]
 
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
index f9fcf8b..3f9083e 100644
--- a/tests/unit/test-003-event.py
+++ b/tests/unit/test-003-event.py
@@ -117,10 +117,14 @@ class TestEventXML(unittest.TestCase):
     def test_018_load_from_ical(self):
         ical_str = """BEGIN:VCALENDAR
 VERSION:2.0
+PRODID:-//Apple Inc.//Mac OS X 10.9.2//EN
 CALSCALE:GREGORIAN
 BEGIN:VEVENT
 DTSTART;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T110000
-DTEND;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T130000
+DURATION:PT1H30M0S
+RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=10
+EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140530T110000
+EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140620T110000
 UID:7a35527d-f783-4b58-b404-b1389bd2fc57
 ATTENDEE;CN="Doe, Jane";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED
  ;ROLE=REQ-PARTICIPANT;RSVP=FALSE:MAILTO:jane at doe.org
@@ -134,6 +138,12 @@ END:VCALENDAR
         event = event_from_ical(ical.walk('VEVENT')[0].to_ical())
         self.assertEqual(event.get_attendee_by_email("max at imum.com").get_cutype(), kolabformat.CutypeResource)
         self.assertEqual(event.get_sequence(), 2)
+        self.assertTrue(event.is_recurring())
+        self.assertIsInstance(event.get_duration(), datetime.timedelta)
+        self.assertIsInstance(event.get_end(), datetime.datetime)
+        self.assertEqual(str(event.get_end()), "2014-05-23 12:30:00+01:00")
+        self.assertEqual(len(event.get_exception_dates()), 2)
+        self.assertIsInstance(event.get_exception_dates()[0], datetime.datetime)
 
     def test_019_as_string_itip(self):
         self.event.set_summary("test")


commit 14a14d77a1178167614ad3bcac9e9dfe4d6e0372
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Mar 4 12:02:41 2014 -0500

    Import RRULE property from iCal

diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index a4e10f0..afaa088 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -183,6 +183,13 @@ class Event(object):
             if ical_event.has_key(attr):
                 self.set_from_ical(attr.lower(), ical_event[attr])
 
+        # HACK: use libkolab::EventCal::fromICal() to parse RRULEs
+        if ical_event.has_key('RRULE'):
+            from kolab.calendaring import EventCal
+            event_xml = EventCal()
+            event_xml.fromICal("BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR")
+            self.event.setRecurrenceRule(event_xml.recurrenceRule())
+
     def get_attendee_participant_status(self, attendee):
         return attendee.get_participant_status()
 
@@ -762,6 +769,9 @@ class Event(object):
 
         return msg
 
+    def is_recurring(self):
+        return self.event.recurrenceRule().isValid()
+
     def to_event_cal(self):
         from kolab.calendaring import EventCal
         return EventCal(self.event)
@@ -774,6 +784,9 @@ class Event(object):
         return xmlutils.from_cdatetime(next_cdatetime, True) if next_cdatetime is not None else None
 
     def get_occurence_end_date(self, datetime):
+        if not datetime:
+            return None
+
         if not hasattr(self, 'eventcal'):
             return None
 
diff --git a/pykolab/xml/utils.py b/pykolab/xml/utils.py
index c4d123c..780932d 100644
--- a/pykolab/xml/utils.py
+++ b/pykolab/xml/utils.py
@@ -7,7 +7,7 @@ def to_dt(dt):
         Convert a naive date or datetime to a tz-aware datetime.
     """
 
-    if isinstance(dt, datetime.date) or not hasattr(dt, 'hour'):
+    if isinstance(dt, datetime.date) and not isinstance(dt, datetime.datetime) or not hasattr(dt, 'hour'):
         dt = datetime.datetime(dt.year, dt.month, dt.day, 0, 0, 0, 0)
 
     else:
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
index 5e77bc8..f9fcf8b 100644
--- a/tests/unit/test-003-event.py
+++ b/tests/unit/test-003-event.py
@@ -159,6 +159,8 @@ END:VCALENDAR
         self.event.set_start(_start)
         self.event.set_end(_start + datetime.timedelta(hours=2))
 
+        self.assertTrue(self.event.is_recurring())
+
         next_date = self.event.get_next_occurence(_start)
         self.assertIsInstance(next_date, datetime.datetime)
         self.assertEqual(next_date.month, 6)
@@ -183,6 +185,7 @@ END:VCALENDAR
         self.assertIsInstance(next_instance, Event)
         self.assertEqual(self.event.get_summary(), next_instance.get_summary())
         self.assertEqual(next_instance.get_start().month, 7)
+        self.assertFalse(next_instance.is_recurring())
 
     def test_021_calendaring_no_recurrence(self):
         _start = datetime.datetime(2014, 2, 1, 14, 30, 00, tzinfo=pytz.timezone("Europe/London"))




More information about the commits mailing list