[CalendarServer-changes] [4699] CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/ twistedcaldav/datafilters

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 3 10:44:59 PST 2009


Revision: 4699
          http://trac.macosforge.org/projects/calendarserver/changeset/4699
Author:   cdaboo at apple.com
Date:     2009-11-03 10:44:59 -0800 (Tue, 03 Nov 2009)
Log Message:
-----------
Basic merge behavior for merging a "new" resource (i.e., just split out the per-user data with no real
merge).

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/__init__.py
    CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/peruserdata.py
    CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/test/test_peruserdata.py

Modified: CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/__init__.py
===================================================================
--- CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/__init__.py	2009-11-03 18:21:02 UTC (rev 4698)
+++ CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/__init__.py	2009-11-03 18:44:59 UTC (rev 4699)
@@ -29,7 +29,7 @@
     sortFirst = ('uid', 'x-calendarserver-peruser-uid')
     knownChildren = {
         'UID':                            (1, 1, None),#min, max, behaviorRegistry id
-        'X-CALENDARSERVER-PERUSER':       (1, 1, None),
+        'X-CALENDARSERVER-PERUSER-UID':   (1, 1, None),
         'X-CALENDARSERVER-PERINSTANCE':   (0, None, None),
     }
       

Modified: CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/peruserdata.py
===================================================================
--- CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/peruserdata.py	2009-11-03 18:21:02 UTC (rev 4698)
+++ CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/peruserdata.py	2009-11-03 18:44:59 UTC (rev 4699)
@@ -15,6 +15,7 @@
 ##
 
 from twistedcaldav.datafilters.filter import CalendarFilter
+from twistedcaldav.ical import Component, Property
 
 __all__ = [
     "PerUserDataFilter",
@@ -57,10 +58,14 @@
     Filter per-user data
     """
 
+    # If any of these change also change the vobject behaviors in this module's __init__.py
     PERUSER_COMPONENT     = "X-CALENDARSERVER-PERUSER"
     PERUSER_UID           = "X-CALENDARSERVER-PERUSER-UID"
     PERINSTANCE_COMPONENT = "X-CALENDARSERVER-PERINSTANCE"
 
+    PERUSER_PROPERTIES    = ("TRANSP",)
+    PERUSER_SUBCOMPONENTS = ("VALARM",)
+
     def __init__(self, uid):
         """
         
@@ -106,10 +111,27 @@
 
     def merge(self, icalnew, icalold):
         """
-        Private event merging does not happen
+        Merge the new data with the old taking per-user information into account.
+
+        @param icalnew: new calendar data
+        @type icalnew: L{Component} or C{str}
+        @param icalold: existing calendar data
+        @type icalold: L{Component} or C{str}
+        
+        @return: L{Component} for the merged calendar data
         """
-        raise NotImplementedError
 
+        # Make sure input is valid
+        icalnew = self.validCalendar(icalnew)
+
+        # First split the new data into common and per-user pieces
+        self._splitPerUserData(icalnew)
+        if icalold is None:
+            return icalnew
+        
+        # Make sure input is valid
+        icalold = self.validCalendar(icalold)
+
     def _mergeBack(self, ical, peruser):
         """
         Merge the per-user data back into the main calendar data.
@@ -178,3 +200,90 @@
             if property.name() == "RECURRENCE-ID":
                 continue
             ical.addProperty(property)
+
+    def _splitPerUserData(self, ical):
+        
+        peruser_component = None
+        perinstance_components = {}
+
+        def init_peruser_component():
+            peruser = Component(PerUserDataFilter.PERUSER_COMPONENT)
+            peruser.addProperty(Property("UID", ical.resourceUID()))
+            peruser.addProperty(Property(PerUserDataFilter.PERUSER_UID, self.uid))
+            ical.addComponent(peruser)
+            return peruser
+            
+        for subcomponent in ical.subcomponents():
+            if subcomponent.name() == "VTIMEZONE":
+                continue
+
+            perinstance_component = None
+            
+            def init_perinstance_component():
+                peruser = Component(PerUserDataFilter.PERINSTANCE_COMPONENT)
+                rid = subcomponent.getRecurrenceIDUTC()
+                if rid:
+                    peruser.addProperty(Property("RECURRENCE-ID", rid))
+                perinstance_components[rid] = peruser
+                return peruser
+
+            # Transfer per-user properties from main component to per-instance component
+            for property in tuple(subcomponent.properties()):
+                if property.name() in PerUserDataFilter.PERUSER_PROPERTIES or property.name().startswith("X-"):
+                    if peruser_component is None:
+                        peruser_component = init_peruser_component()
+                    if perinstance_component is None:
+                        perinstance_component = init_perinstance_component()
+                    perinstance_component.addProperty(property)
+                    subcomponent.removeProperty(property)
+            
+            # Transfer per-user components from main component to per-instance component
+            for component in tuple(subcomponent.subcomponents()):
+                if component.name() in PerUserDataFilter.PERUSER_SUBCOMPONENTS or component.name().startswith("X-"):
+                    if peruser_component is None:
+                        peruser_component = init_peruser_component()
+                    if perinstance_component is None:
+                        perinstance_component = init_perinstance_component()
+                    perinstance_component.addComponent(component)
+                    subcomponent.removeComponent(component)
+            
+        # Add unique per-instance components into the per-user component
+        master_perinstance = perinstance_components.get(None)
+        master_perinstance_txt = str(master_perinstance)
+        if master_perinstance:
+            peruser_component.addComponent(master_perinstance)
+        for rid, perinstance in perinstance_components.iteritems():
+            if rid is None:
+                continue
+            perinstance_txt = str(perinstance)
+            perinstance_txt = "".join([line for line in perinstance_txt.splitlines(True) if not line.startswith("RECURRENCE-ID:")])
+            if master_perinstance is None or perinstance_txt != master_perinstance_txt:
+                peruser_component.addComponent(perinstance)
+
+        self._compactInstances(ical)
+
+    def _compactInstances(self, ical):
+        """
+        Remove recurrences instances that are the same as their master-derived counterparts. This gives the most
+        compact representation of the calendar data.
+
+        @param ical: calendar data to process
+        @type ical: L{Component}
+        """
+
+        # Must have a master component in order to do this
+        master = ical.masterComponent()
+        if master is None:
+            return
+
+        for subcomponent in tuple(ical.subcomponents()):
+            if subcomponent.name() == "VTIMEZONE" or subcomponent.name().startswith("X-"):
+                continue
+            rid = subcomponent.getRecurrenceIDUTC()
+            if rid is None:
+                continue
+            derived = ical.deriveInstance(rid)
+            if derived:
+                if str(derived) == str(subcomponent):
+                    ical.removeComponent(subcomponent)
+

Modified: CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/test/test_peruserdata.py
===================================================================
--- CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/test/test_peruserdata.py	2009-11-03 18:21:02 UTC (rev 4698)
+++ CalendarServer/branches/users/cdaboo/per-user-icalendar-4669/twistedcaldav/datafilters/test/test_peruserdata.py	2009-11-03 18:44:59 UTC (rev 4699)
@@ -18,7 +18,7 @@
 from twistedcaldav.ical import Component
 from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
 
-class PerUserDataTestNotRecurring (twistedcaldav.test.util.TestCase):
+class PerUserDataFilterTestNotRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
         
@@ -202,7 +202,7 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user03").filter(item)), result03)
 
-class PerUserDataTestRecurring (twistedcaldav.test.util.TestCase):
+class PerUserDataFilterTestRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
         
@@ -835,3 +835,498 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user02").filter(item)), result02)
 
+class PerUserDataMergeTestNewNotRecurring (twistedcaldav.test.util.TestCase):
+
+    def test_public_noperuser(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), data)
+
+    def test_public_oneuser(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
+class PerUserDataMergeTestNewRecurring (twistedcaldav.test.util.TestCase):
+
+    def test_public_noperuser(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), data)
+
+    def test_public_oneuser_master(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
+    def test_public_oneuser_master_and_override(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+RECURRENCE-ID:20080602T120000Z
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
+    def test_public_oneuser_override(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+RECURRENCE-ID:20080602T120000Z
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
+    def test_public_oneuser_master_compact_override(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+RECURRENCE-ID:20080602T120000Z
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
+    def test_public_oneuser_master_noncompact_override(self):
+        
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        result01 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user01
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-master
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+RECURRENCE-ID:20080602T120000Z
+TRANSP:TRANSPARENT
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20091103/0af84a80/attachment-0001.html>


More information about the calendarserver-changes mailing list