[CalendarServer-changes] [4368] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Tue Jun 23 08:35:47 PDT 2009


Revision: 4368
          http://trac.macosforge.org/projects/calendarserver/changeset/4368
Author:   cdaboo at apple.com
Date:     2009-06-23 08:35:47 -0700 (Tue, 23 Jun 2009)
Log Message:
-----------
Don't raise an exception for an invalid instance when we are re-indexing data already on the server,
but do raise when there is incoming invalid data.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/ical.py
    CalendarServer/trunk/twistedcaldav/index.py
    CalendarServer/trunk/twistedcaldav/instance.py
    CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
    CalendarServer/trunk/twistedcaldav/test/test_index.py

Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py	2009-06-23 00:54:36 UTC (rev 4367)
+++ CalendarServer/trunk/twistedcaldav/ical.py	2009-06-23 15:35:47 UTC (rev 4368)
@@ -956,20 +956,21 @@
         self.cachedInstances = self.expandTimeRanges(limit)
         return self.cachedInstances
 
-    def expandTimeRanges(self, limit):
+    def expandTimeRanges(self, limit, ignoreInvalidInstances=False):
         """
         Expand the set of recurrence instances for the components
         contained within this VCALENDAR component. We will assume
         that this component has already been validated as a CalDAV resource
         (i.e. only one type of component, all with the same UID)
         @param limit: datetime.date value representing the end of the expansion.
+        @param ignoreInvalidInstances: C{bool} whether to ignore instance errors.
         @return: a set of Instances for each recurrence in the set.
         """
         
         componentSet = self.subcomponents()
-        return self.expandSetTimeRanges(componentSet, limit)
+        return self.expandSetTimeRanges(componentSet, limit, ignoreInvalidInstances)
     
-    def expandSetTimeRanges(self, componentSet, limit):
+    def expandSetTimeRanges(self, componentSet, limit, ignoreInvalidInstances=False):
         """
         Expand the set of recurrence instances up to the specified date limit.
         What we do is first expand the master instance into the set of generate
@@ -983,7 +984,7 @@
         """
         
         # Set of instances to return
-        instances = InstanceList()
+        instances = InstanceList(ignoreInvalidInstances=ignoreInvalidInstances)
         instances.expandTimeRanges(componentSet, limit)
         return instances
 

Modified: CalendarServer/trunk/twistedcaldav/index.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/index.py	2009-06-23 00:54:36 UTC (rev 4367)
+++ CalendarServer/trunk/twistedcaldav/index.py	2009-06-23 15:35:47 UTC (rev 4368)
@@ -204,7 +204,7 @@
 
         return uid
 
-    def addResource(self, name, calendar, fast=False):
+    def addResource(self, name, calendar, fast=False, reCreate=False):
         """
         Adding or updating an existing resource.
         To check for an update we attempt to get an existing UID
@@ -218,7 +218,7 @@
         oldUID = self.resourceUIDForName(name)
         if oldUID is not None:
             self._delete_from_db(name, oldUID)
-        self._add_to_db(name, calendar)
+        self._add_to_db(name, calendar, reCreate=reCreate)
         if not fast:
             self._db_commit()
 
@@ -341,7 +341,7 @@
         """
         return schema_version
 
-    def _add_to_db(self, name, calendar, cursor = None, expand_until=None):
+    def _add_to_db(self, name, calendar, cursor = None, expand_until=None, reCreate=False):
         """
         Records the given calendar resource in the index with the given name.
         Resource names and UIDs must both be unique; only one resource name may
@@ -455,10 +455,10 @@
         with a longer expansion.
         """
         calendar = self.resource.getChild(name).iCalendar()
-        self._add_to_db(name, calendar, expand_until=expand_until)
+        self._add_to_db(name, calendar, expand_until=expand_until, reCreate=True)
         self._db_commit()
 
-    def _add_to_db(self, name, calendar, cursor = None, expand_until=None):
+    def _add_to_db(self, name, calendar, cursor = None, expand_until=None, reCreate=False):
         """
         Records the given calendar resource in the index with the given name.
         Resource names and UIDs must both be unique; only one resource name may
@@ -488,7 +488,7 @@
                 raise IndexedSearchException
 
         try:
-            instances = calendar.expandTimeRanges(expand)
+            instances = calendar.expandTimeRanges(expand, ignoreInvalidInstances=reCreate)
         except InvalidOverriddenInstanceError, e:
             log.err("Invalid instance %s when indexing %s in %s" % (e.rid, name, self.resource,))
             raise
@@ -789,7 +789,7 @@
                 log.err("Non-calendar resource: %s" % (name,))
             else:
                 #log.msg("Indexing resource: %s" % (name,))
-                self.addResource(name, calendar, True)
+                self.addResource(name, calendar, True, reCreate=True)
             finally:
                 stream.close()
 
@@ -901,7 +901,7 @@
                 log.err("Non-calendar resource: %s" % (name,))
             else:
                 #log.msg("Indexing resource: %s" % (name,))
-                self.addResource(name, calendar, True)
+                self.addResource(name, calendar, True, reCreate=True)
             finally:
                 stream.close()
 

Modified: CalendarServer/trunk/twistedcaldav/instance.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/instance.py	2009-06-23 00:54:36 UTC (rev 4367)
+++ CalendarServer/trunk/twistedcaldav/instance.py	2009-06-23 15:35:47 UTC (rev 4368)
@@ -96,11 +96,12 @@
     
 class InstanceList(object):
     
-    __slots__ = ["instances", "limit"]
+    __slots__ = ["instances", "limit", "ignoreInvalidInstances",]
     
-    def __init__(self):
+    def __init__(self, ignoreInvalidInstances=False):
         self.instances = {}
         self.limit = None
+        self.ignoreInvalidInstances = ignoreInvalidInstances
         
     def __iter__(self):
         # Return keys in sorted order via iterator
@@ -324,7 +325,10 @@
         # Make sure override RECURRENCE-ID is a valid instance of the master
         if got_master:
             if str(rid) not in self.instances:
-                raise InvalidOverriddenInstanceError(str(rid))
+                if self.ignoreInvalidInstances:
+                    return
+                else:
+                    raise InvalidOverriddenInstanceError(str(rid))
         
         self.addInstance(Instance(component, start, end, rid, True, range))
         

Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2009-06-23 00:54:36 UTC (rev 4367)
+++ CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2009-06-23 15:35:47 UTC (rev 4368)
@@ -1656,6 +1656,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),)
             ),
             (
@@ -1671,6 +1672,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
                     datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
@@ -1690,6 +1692,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
                     datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
@@ -1710,6 +1713,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
                     datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
@@ -1729,6 +1733,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
                     datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
@@ -1753,6 +1758,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
                     datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()),
@@ -1777,16 +1783,42 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 None
             ),
+            (
+                "Recurring with invalid override",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DURATION:P1H
+RRULE:FREQ=DAILY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071115T010000Z
+DTSTART:20071115T000000Z
+DURATION:P1H
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                (
+                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
+                    datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
+                )
+            ),
         )
         
-        for description, original, results in data:
+        for description, original, ignoreInvalidInstances, results in data:
             component = Component.fromString(original)
             if results is None:
-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, datetime.date(2100, 1, 1))
+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, datetime.date(2100, 1, 1), ignoreInvalidInstances)
             else:
-                instances = component.expandTimeRanges(datetime.date(2100, 1, 1))
+                instances = component.expandTimeRanges(datetime.date(2100, 1, 1), ignoreInvalidInstances)
                 self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
                 for instance in instances:
                     self.assertTrue(instances[instance].start in results, "%s: %s missing" % (description, instance,))

Modified: CalendarServer/trunk/twistedcaldav/test/test_index.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_index.py	2009-06-23 00:54:36 UTC (rev 4367)
+++ CalendarServer/trunk/twistedcaldav/test/test_index.py	2009-06-23 15:35:47 UTC (rev 4368)
@@ -14,14 +14,19 @@
 # limitations under the License.
 ##
 
-from twistedcaldav.index import Index
-
-import twistedcaldav.test.util
-from twistedcaldav.test.util import InMemoryMemcacheProtocol
-from twistedcaldav.index import ReservationError, MemcachedUIDReserver
 from twisted.internet import reactor
 from twisted.internet.task import deferLater
 
+from twistedcaldav.ical import Component
+from twistedcaldav.index import Index
+from twistedcaldav.index import ReservationError, MemcachedUIDReserver
+from twistedcaldav.instance import InvalidOverriddenInstanceError
+from twistedcaldav.test.util import InMemoryMemcacheProtocol
+import twistedcaldav.test.util
+
+import datetime
+import os
+
 class SQLIndexTests (twistedcaldav.test.util.TestCase):
     """
     Test abstract SQL DB class
@@ -89,7 +94,163 @@
         return d
 
 
+    def test_index(self):
+        data = (
+            (
+                "#1.1 Simple component",
+                "1.1",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1.1
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+                True,
+            ),
+            (
+                "#2.1 Recurring component",
+                "2.1",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-2.1
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+RRULE:FREQ=WEEKLY;COUNT=2
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+                True,
+            ),
+            (
+                "#2.2 Recurring component with override",
+                "2.2",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-2.2
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+RRULE:FREQ=WEEKLY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-2.2
+RECURRENCE-ID:20080608T120000Z
+DTSTART:20080608T120000Z
+DTEND:20080608T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+                True,
+            ),
+            (
+                "#2.3 Recurring component with broken override - new",
+                "2.3",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-2.3
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+RRULE:FREQ=WEEKLY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-2.3
+RECURRENCE-ID:20080609T120000Z
+DTSTART:20080608T120000Z
+DTEND:20080608T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+                False,
+            ),
+            (
+                "#2.4 Recurring component with broken override - existing",
+                "2.4",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-2.4
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+RRULE:FREQ=WEEKLY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-2.4
+RECURRENCE-ID:20080609T120000Z
+DTSTART:20080608T120000Z
+DTEND:20080608T130000Z
+ORGANIZER;CN="User 01":mailto:user1 at example.com
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                True,
+            ),
+        )
 
+        for description, name, calendar_txt, reCreate, ok in data:
+            calendar = Component.fromString(calendar_txt)
+            if ok:
+                f = open(os.path.join(self.site.resource.fp.path, name), "w")
+                f.write(calendar_txt)
+                del f
+
+                self.db.addResource(name, calendar, reCreate=reCreate)
+                self.assertTrue(self.db.resourceExists(name), msg=description)
+            else:
+                self.assertRaises(InvalidOverriddenInstanceError, self.db.addResource, name, calendar)
+                self.assertFalse(self.db.resourceExists(name), msg=description)
+
+        self.db._db_recreate()
+        for description, name, calendar_txt, reCreate, ok in data:
+            if ok:
+                self.assertTrue(self.db.resourceExists(name), msg=description)
+            else:
+                self.assertFalse(self.db.resourceExists(name), msg=description)
+
+        self.db.testAndUpdateIndex(datetime.date(2020, 1, 1))
+        for description, name, calendar_txt, reCreate, ok in data:
+            if ok:
+                self.assertTrue(self.db.resourceExists(name), msg=description)
+            else:
+                self.assertFalse(self.db.resourceExists(name), msg=description)
+
 class MemcacheTests(SQLIndexTests):
     def setUp(self):
         super(MemcacheTests, self).setUp()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090623/aa8ade36/attachment-0001.html>


More information about the calendarserver-changes mailing list