[CalendarServer-changes] [4351] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 17 09:50:59 PDT 2009


Revision: 4351
          http://trac.macosforge.org/projects/calendarserver/changeset/4351
Author:   cdaboo at apple.com
Date:     2009-06-17 09:50:59 -0700 (Wed, 17 Jun 2009)
Log Message:
-----------
SCHEDULE-AGENT support.

Modified Paths:
--------------
    CalendarServer/trunk/run
    CalendarServer/trunk/twistedcaldav/ical.py
    CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
    CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
    CalendarServer/trunk/twistedcaldav/scheduling/itip.py
    CalendarServer/trunk/twistedcaldav/test/test_icalendar.py

Modified: CalendarServer/trunk/run
===================================================================
--- CalendarServer/trunk/run	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/run	2009-06-17 16:50:59 UTC (rev 4351)
@@ -727,7 +727,7 @@
 
 caldavtester="${top}/CalDAVTester";
 
-svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4346;
+svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4350;
 
 #
 # PyFlakes

Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/twistedcaldav/ical.py	2009-06-17 16:50:59 UTC (rev 4351)
@@ -96,12 +96,12 @@
     "TZOFFSETTO":   (None, {"VALUE": "UTC-OFFSET"}),
     "TZURL":        (None, {"VALUE": "URI"}),
     "ATTENDEE":     (None, {
-        "VALUE": "CAL-ADDRESS",
-        "CUTYPE": "INDIVIDUAL",
-        "ROLE": "REQ-PARTICIPANT",
-        "PARTSTAT": "NEEDS-ACTION",
-        "RSVP": "FALSE",
-        
+        "VALUE":          "CAL-ADDRESS",
+        "CUTYPE":         "INDIVIDUAL",
+        "ROLE":           "REQ-PARTICIPANT",
+        "PARTSTAT":       "NEEDS-ACTION",
+        "RSVP":           "FALSE",
+        "SCHEDULE-AGENT": "SERVER",
     }),
     "CONTACT":      (None, {"VALUE": "TEXT"}),
     "ORGANIZER":    (None, {"VALUE": "CAL-ADDRESS"}),
@@ -1510,12 +1510,14 @@
 
         return None
 
-    def getAttendeesByInstance(self, makeUnique=False):
+    def getAttendeesByInstance(self, makeUnique=False, onlyScheduleAgentServer=False):
         """
         Get the attendee values for each instance. Optionally remove duplicates.
         
         @param makeUnique: if C{True} remove duplicate ATTENDEEs in each component
         @type makeUnique: C{bool}
+        @param onlyScheduleAgentServer: if C{True} only return ATETNDEEs with SCHEDULE-AGENT=SERVER set
+        @type onlyScheduleAgentServer: C{bool}
         @return: a list of tuples of (organizer value, recurrence-id)
         """
         
@@ -1524,13 +1526,19 @@
             result = ()
             for component in self.subcomponents():
                 if component.name() != "VTIMEZONE":
-                    result += component.getAttendeesByInstance(makeUnique)
+                    result += component.getAttendeesByInstance(makeUnique, onlyScheduleAgentServer)
             return result
         else:
             result = ()
             attendees = set()
             rid = self.getRecurrenceIDUTC()
             for attendee in tuple(self.properties("ATTENDEE")):
+                
+                if onlyScheduleAgentServer:
+                    if "SCHEDULE-AGENT" in attendee.params():
+                        if attendee.paramValue("SCHEDULE-AGENT") != "SERVER":
+                            continue
+
                 cuaddr = attendee.value()
                 if makeUnique and cuaddr in attendees:
                     self.removeProperty(attendee)
@@ -1739,7 +1747,7 @@
                     for prop in matched.properties(propname):
                         self.addProperty(prop)
             
-    def attendeesView(self, attendees):
+    def attendeesView(self, attendees, onlyScheduleAgentServer=False):
         """
         Filter out any components that all attendees are not present in. Use EXDATEs
         on the master to account for changes.
@@ -1756,9 +1764,15 @@
                 continue
             found_all_attendees = True
             for attendee in attendees:
-                if component.getAttendeeProperty((attendee,)) is None:
+                foundAttendee = component.getAttendeeProperty((attendee,))
+                if foundAttendee is None:
                     found_all_attendees = False
                     break
+                if onlyScheduleAgentServer:
+                    if "SCHEDULE-AGENT" in foundAttendee.params():
+                        if foundAttendee.paramValue("SCHEDULE-AGENT") != "SERVER":
+                            found_all_attendees = False
+                            break
             if not found_all_attendees:
                 remove_components.append(component)
             if component.getRecurrenceIDUTC() is None:

Modified: CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py	2009-06-17 16:50:59 UTC (rev 4351)
@@ -70,7 +70,7 @@
                 "LAST-MODIFIED",
             ))
             calendar.removeXProperties()
-            calendar.removePropertyParameters("ATTENDEE", ("RSVP", "SCHEDULE-AGENT", "SCHEDULE-STATUS",))
+            calendar.removePropertyParameters("ATTENDEE", ("RSVP", "SCHEDULE-STATUS",))
             calendar.normalizeAll()
             return calendar
         

Modified: CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/implicit.py	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/twistedcaldav/scheduling/implicit.py	2009-06-17 16:50:59 UTC (rev 4351)
@@ -45,8 +45,6 @@
 # TODO:
 #
 # Handle the case where a PUT removes the ORGANIZER property. That should be equivalent to cancelling the entire meeting.
-# Support SCHEDULE-AGENT property
-# Support SCHEDULE-STATUS property
 # Support Schedule-Reply header
 #
 
@@ -346,7 +344,7 @@
             raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "single-organizer")))
         
         # Get the ATTENDEEs
-        self.attendeesByInstance = self.calendar.getAttendeesByInstance(True)
+        self.attendeesByInstance = self.calendar.getAttendeesByInstance(True, onlyScheduleAgentServer=True)
         self.attendees = set()
         for attendee, _ignore in self.attendeesByInstance:
             self.attendees.add(attendee)
@@ -574,7 +572,7 @@
         
         # TODO: the later three will be ignored for now.
 
-        oldAttendeesByInstance = self.oldcalendar.getAttendeesByInstance()
+        oldAttendeesByInstance = self.oldcalendar.getAttendeesByInstance(onlyScheduleAgentServer=True)
         
         mappedOld = set(oldAttendeesByInstance)
         mappedNew = set(self.attendeesByInstance)
@@ -617,7 +615,7 @@
                     if (new_attendee, None) not in mappedNew or rid in addedexdates:
                         self.cancelledAttendees.add(item)
 
-        master_attendees = self.oldcalendar.masterComponent().getAttendeesByInstance()
+        master_attendees = self.oldcalendar.masterComponent().getAttendeesByInstance(onlyScheduleAgentServer=True)
         for attendee, _ignore in master_attendees:
             for exdate in addedexdates:
                 # Don't remove the master attendee's when an EXDATE is added for a removed overridden component
@@ -842,7 +840,7 @@
         oldcalendar = self.oldcalendar
         if oldcalendar is None:
             oldcalendar = self.organizer_calendar
-            oldcalendar.attendeesView((self.attendee,))
+            oldcalendar.attendeesView((self.attendee,), onlyScheduleAgentServer=True)
         differ = iCalDiff(oldcalendar, self.calendar, self.do_smart_merge)
         return differ.attendeeMerge(self.attendee)
 

Modified: CalendarServer/trunk/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/itip.py	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/twistedcaldav/scheduling/itip.py	2009-06-17 16:50:59 UTC (rev 4351)
@@ -560,7 +560,7 @@
         itip.replacePropertyInAllComponents(Property("DTSTAMP", datetime.datetime.now(tz=utc)))
 
         # Now filter out components that do not contain every attendee
-        itip.attendeesView(attendees)
+        itip.attendeesView(attendees, onlyScheduleAgentServer=True)
         
         # Now filter out components except the ones specified
         if itip.filterComponents(filter_rids):
@@ -649,7 +649,7 @@
         
         # Property Parameters
         itip.removePropertyParameters("ATTENDEE", ("SCHEDULE-AGENT", "SCHEDULE-STATUS",))
-        itip.removePropertyParameters("ORGANIZER", ("SCHEDULE-STATUS",))
+        itip.removePropertyParameters("ORGANIZER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS",))
 
 class iTIPRequestStatus(object):
     """

Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2009-06-17 16:49:45 UTC (rev 4350)
+++ CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2009-06-17 16:50:59 UTC (rev 4351)
@@ -388,6 +388,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 ()
             ),
             (
@@ -401,6 +402,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     ("mailto:user2 at example.com", None),
                 )
@@ -417,6 +419,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     ("mailto:user2 at example.com", None),
                     ("mailto:user3 at example.com", None),
@@ -437,22 +440,65 @@
 RECURRENCE-ID:20081114T000000Z
 DTSTART:20071114T010000Z
 ORGANIZER:mailto:user1 at example.com
-ATTENDEE:mailto:user2 at example.com
-ATTENDEE:mailto:user3 at example.com
+ATTENDEE;SCHEDULE-AGENT=NONE:mailto:user2 at example.com
+ATTENDEE;SCHEDULE-AGENT=CLIENT:mailto:user3 at example.com
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 (
                     ("mailto:user2 at example.com", None),
                     ("mailto:user2 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc())),
                     ("mailto:user3 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc()))
                 )
             ),
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20071114T000000Z
+ORGANIZER:mailto:user1 at example.com
+ATTENDEE;SCHEDULE-AGENT=NONE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                (
+                    ("mailto:user3 at example.com", None),
+                )
+            ),
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20071114T000000Z
+ORGANIZER:mailto:user1 at example.com
+ATTENDEE;SCHEDULE-AGENT=SERVER:mailto:user2 at example.com
+RRULE:FREQ=YEARLY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20081114T000000Z
+DTSTART:20071114T010000Z
+ORGANIZER:mailto:user1 at example.com
+ATTENDEE;SCHEDULE-AGENT=NONE:mailto:user2 at example.com
+ATTENDEE;SCHEDULE-AGENT=CLIENT:mailto:user3 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                (
+                    ("mailto:user2 at example.com", None),
+                )
+            ),
         )
         
-        for caldata, result in data:
+        for caldata, checkScheduleAgent, result in data:
             component = Component.fromString(caldata)
-            self.assertEqual(component.getAttendeesByInstance(), result)
+            self.assertEqual(component.getAttendeesByInstance(onlyScheduleAgentServer=checkScheduleAgent), result)
 
     def test_set_parameter_value(self):
         data = (
@@ -675,6 +721,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -698,6 +745,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -719,6 +767,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -746,6 +795,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -775,6 +825,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -818,6 +869,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -846,6 +898,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -882,6 +935,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -910,6 +964,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -945,6 +1000,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
+                False,
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//PYVOBJECT//NONSGML Version 1//EN
@@ -952,11 +1008,156 @@
 """,
                 ("mailto:user3 at example.com",)
             ),
+
+                    # Simple component, no Attendees - no filtering
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+END:VEVENT
+END:VCALENDAR
+""",
+                ()
+            ),
+
+            # Simple component, no Attendees - filtering
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-2
+DTSTART:20071114T000000Z
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+END:VCALENDAR
+""",
+                ("mailto:user01 at example.com",)
+            ),
+
+            # Simple component, with one attendee - filtering match
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                ("mailto:user2 at example.com",)
+            ),
+
+            # Simple component, with one attendee - filtering match
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE;SCHEDULE-AGENT=SERVER:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE;SCHEDULE-AGENT=SERVER:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                ("mailto:user2 at example.com",)
+            ),
+
+            # Simple component, with one attendee - filtering match - no schedule-agent match
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE;SCHEDULE-AGENT=CLIENT:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+END:VCALENDAR
+""",
+                ("mailto:user2 at example.com",)
+            ),
+
+            # Simple component, with one attendee - filtering match - no schedule-agent match
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-3
+DTSTART:20071114T000000Z
+ATTENDEE;SCHEDULE-AGENT=NONE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+END:VCALENDAR
+""",
+                ("mailto:user2 at example.com",)
+            ),
+
         )
         
-        for original, filtered, attendees in data:
+        for original, checkScheduleAgent, filtered, attendees in data:
             component = Component.fromString(original)
-            component.attendeesView(attendees)
+            component.attendeesView(attendees, onlyScheduleAgentServer=checkScheduleAgent)
             self.assertEqual(filtered, str(component).replace("\r", ""))
 
     def test_all_but_one_attendee(self):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090617/2517ca7d/attachment-0001.html>


More information about the calendarserver-changes mailing list