[CalendarServer-changes] [4090] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 27 09:14:20 PDT 2009
Revision: 4090
http://trac.macosforge.org/projects/calendarserver/changeset/4090
Author: cdaboo at apple.com
Date: 2009-04-27 09:14:20 -0700 (Mon, 27 Apr 2009)
Log Message:
-----------
New schedule-changes XML schema and tests.
Modified Paths:
--------------
CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.txt
CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.xml
CalendarServer/trunk/run
CalendarServer/trunk/twistedcaldav/customxml.py
CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
CalendarServer/trunk/twistedcaldav/scheduling/itip.py
CalendarServer/trunk/twistedcaldav/scheduling/processing.py
CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py
Modified: CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.txt
===================================================================
--- CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.txt 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.txt 2009-04-27 16:14:20 UTC (rev 4090)
@@ -3,7 +3,7 @@
Calendar Server Extension C. Daboo
Apple
- February 28, 2009
+ April 26, 2009
Change Indicators for Processed CalDAV Scheduling Messages
@@ -25,16 +25,17 @@
4. New features . . . . . . . . . . . . . . . . . . . . . . . . . 3
4.1. CalDAV Changes . . . . . . . . . . . . . . . . . . . . . . 3
4.1.1. Change Indicator WebDAV Property . . . . . . . . . . . 3
- 4.1.2. CS:schedule-changes XML element . . . . . . . . . . . . 5
- 4.1.2.1. CS:dtstamp XML Element . . . . . . . . . . . . . . 5
- 4.1.2.2. CS:action XML Element . . . . . . . . . . . . . . . 5
- 4.1.2.3. CS:changes XML Element . . . . . . . . . . . . . . 6
- 4.1.2.4. CS:recurrences XML Element . . . . . . . . . . . . 7
- 5. Security Considerations . . . . . . . . . . . . . . . . . . . . 7
- 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 7
- 7. Normative References . . . . . . . . . . . . . . . . . . . . . 7
- Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . . 8
- Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 4.1.2. CS:schedule-changes XML element . . . . . . . . . . . . 6
+ 4.1.2.1. CS:dtstamp XML Element . . . . . . . . . . . . . . 6
+ 4.1.2.2. CS:action XML Element . . . . . . . . . . . . . . . 6
+ 4.1.2.3. CS:recurrence XML Element . . . . . . . . . . . . . 7
+ 4.1.2.4. CS:changes XML Element . . . . . . . . . . . . . . 8
+ 5. Security Considerations . . . . . . . . . . . . . . . . . . . . 8
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 8
+ 7. Normative References . . . . . . . . . . . . . . . . . . . . . 8
+ Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . . 9
+ Appendix B. Change History . . . . . . . . . . . . . . . . . . . . 9
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 9
@@ -51,10 +52,9 @@
-
Daboo [Page 1]
- CalDAV Scheduling Change Indicators February 2009
+ CalDAV Scheduling Change Indicators April 2009
1. Introduction
@@ -110,7 +110,7 @@
Daboo [Page 2]
- CalDAV Scheduling Change Indicators February 2009
+ CalDAV Scheduling Change Indicators April 2009
create an XML data value (as described next) and store that in the
@@ -166,7 +166,7 @@
Daboo [Page 3]
- CalDAV Scheduling Change Indicators February 2009
+ CalDAV Scheduling Change Indicators April 2009
<!ELEMENT schedule-changes
@@ -181,83 +181,139 @@
<!ELEMENT create EMPTY>
<!-- New calendar object was created -->
- <!ELEMENT update (changes, recurrences?)>
+ <!ELEMENT update (recurrence+)>
<!-- Calendar object was changed -->
- <!ELEMENT cancel (recurrences?)>
- <!-- Calendar object or instances were cancelled -->
+ <!ELEMENT cancel (recurrence*)>
+ <!-- Calendar object was cancelled -->
- <!ELEMENT reply (attendee, partstat?, private-comment?,
- recurrences?)>
+ <!ELEMENT reply (attendee, recurrence+)>
<!-- Reply received from attendee -->
- <!ELEMENT attendee CDATA>
- <!-- ATTENDEE iCalendar property value -->
+ <!ELEMENT recurrence
+ ((master | recurrenceid), changes)>
+ <!-- Which instances were affected by the change,
+ and details on the per-instance changes -->
- <!ELEMENT partstat EMPTY>
- <!-- ATTENDEE PARTSTAT property parameter value changed -->
+ <!ELEMENT master EMPTY>
+ <!-- The "master" instance was affected -->
- <!ELEMENT private-comment EMPTY>
- <!-- X-CALENDARSERVER-PRIVATE-COMMENT property value
- changed -->
+ <!ELEMENT recurrenceid CDATA>
+ <!-- RECURRENCE-ID value for the affected instance -->
<!ELEMENT changes changed-property*>
+ <!-- Detailed changes in the iCalendar data -->
+
+ <!ELEMENT changed-property changed-parameter*>
<!ATTLIST changed-property name PCDATA>
+ <!-- An iCalendar property changed -->
- <!ELEMENT changed-property changed-parameter*>
+ <!ELEMENT changed-parameter EMPTY>
<!ATTLIST changed-parameter name PCDATA>
+ <!-- An iCalendar property parameter changed -->
- <!ELEMENT recurrences (master?, recurrenceid*)>
- <!-- Which instances were affected by the change -->
+ <!ELEMENT attendee CDATA>
+ <!-- ATTENDEE iCalendar property value -->
- <!ELEMENT master EMPTY>
- <!-- The "master" instance was affected -->
- <!ELEMENT recurrenceid CDATA>
- <!-- RECURRENCE-ID value for the affected instance -->
-
Daboo [Page 4]
- CalDAV Scheduling Change Indicators February 2009
+ CalDAV Scheduling Change Indicators April 2009
- Example:
+ Example: This example indicates that a new calendar component was
+ created.
<CS:schedule-changes
xmlns:CS="http://calendarserver.org/ns/">
<CS:dtstamp>20080818T223423Z</CS:dtstamp>
- <CS:action><CS:create/></CS:action>
+ <CS:action>
+ <CS:create/>
+ </CS:action>
</CS:schedule-changes>
- Example:
+ Example: This example indicates that a non-recurring component, or
+ the master component in a recurring component, was changed and
+ that the change was to the "SUMMARY" iCalendar property.
<CS:schedule-changes
xmlns:CS="http://calendarserver.org/ns/">
<CS:dtstamp>20080818T223423Z</CS:dtstamp>
<CS:action>
<CS:update>
- <CS:changes>
- <CS:changed-property name="SUMMARY"/>
- </CS:changes>
- <CS:recurrences/>
+ <CS:recurrence>
+ <CS:master/>
+ <CS:changes>
+ <CS:changed-property name="SUMMARY"/>
+ </CS:changes>
+ <CS:recurrence/>
</CS:update>
</CS:action>
</CS:schedule-changes>
+ Example: This example indicates that two recurrence instances were
+ cancelled from a recurring component.
+
+ <CS:schedule-changes
+ xmlns:CS="http://calendarserver.org/ns/">
+ <CS:dtstamp>20080818T223423Z</CS:dtstamp>
+ <CS:action>
+ <CS:cancel>
+ <CS:recurrence>
+ <CS:recurrence-id>20090101T010000Z</CS:recurrence-id>
+ <CS:recurrence/>
+ <CS:recurrence>
+ <CS:recurrence-id>20090102T010000Z</CS:recurrence-id>
+ <CS:recurrence/>
+ </CS:update>
+ </CS:action>
+ </CS:schedule-changes>
+
+
+
+
+Daboo [Page 5]
+
+ CalDAV Scheduling Change Indicators April 2009
+
+
+ Example: This example indicates that the Attendee with calendar user
+ address "mailto:cyrus at example.com" replied to the Organizer and
+ changed their "PARTSTAT" iCalendar property parameter on one
+ recurrence instance.
+
+ <CS:schedule-changes
+ xmlns:CS="http://calendarserver.org/ns/">
+ <CS:dtstamp>20080818T223423Z</CS:dtstamp>
+ <CS:action>
+ <CS:reply>
+ <CS:attendee>mailto:cyrus at example.com</CS:attendee>
+ <CS:recurrence>
+ <CS:recurrence-id>20090101T010000Z</CS:recurrence-id>
+ <CS:changes>
+ <CS:changed-property name="ATTENDEE">
+ <CS:changed-parameter name="PARTSTAT"/>
+ </CS:changed-property>
+ </CS:changes>
+ <CS:recurrence/>
+ </CS:update>
+ </CS:action>
+ </CS:schedule-changes>
+
4.1.2. CS:schedule-changes XML element
The CS:schedule-changes XML element is used to indicate what changes
were made when the server automatically processed a scheduling
- message. There are four child elements that can appear, and each is
+ message. There are two child elements that can appear, and each is
described next.
4.1.2.1. CS:dtstamp XML Element
- This elements contains a text value in the form of an iCalendar Date-
+ This element contains a text value in the form of an iCalendar Date-
Time value in UTC. This value is the time at which the automatic
processing took place.
@@ -276,9 +332,9 @@
-Daboo [Page 5]
+Daboo [Page 6]
- CalDAV Scheduling Change Indicators February 2009
+ CalDAV Scheduling Change Indicators April 2009
+-----------+-------------------------------------------------------+
@@ -288,79 +344,84 @@
| CS:create | A new calendar object was created in the default |
| | calendar of the recipient. |
| | |
- | CS:update | An update to an existing calendar object occurred. |
- | | The CS:changes and CS:recurrences child elements |
- | | indicate what the changes were and which instances |
- | | were affected. If the calendar object is not |
- | | recurring, CS:recurrences MUST NOT be present. If |
- | | all or any individual instances of a recurring |
- | | calendar object were affected, then CS:recurrences |
- | | MUST be present and indicate which instances were |
- | | affected. |
+ | CS:update | An update to an existing calendar object occurred. A |
+ | | CS:recurrence element is included for each recurrence |
+ | | instance changed. Each CS:recurrence element |
+ | | indicates the specific instance that was changes as |
+ | | well as details on which properties or parameters |
+ | | changed. |
| | |
| CS:cancel | A cancellation scheduling message was processed. If |
| | the calendar object is not recurring or all instances |
- | | are being removed, then CS:recurrences MUST NOT be |
- | | present. If any individual instances of a recurring |
- | | calendar object were affected, then CS:recurrences |
- | | MUST be present and indicate which instances were |
- | | affected. |
+ | | are being removed, then there MUST NOT be any |
+ | | CS:recurrence element present. If any individual |
+ | | instances of a recurring calendar object were |
+ | | affected, then a CS:recurrence element MUST be |
+ | | present and indicate which instances were affected. |
| | |
| CS:reply | An Attendee's reply was processed. The CS:attendee, |
- | | CS:partstat and CS:private-comment elements indicate |
- | | which Attendee replied, whether their "PARTSTAT" |
- | | changed, and whether any private comment was changed. |
- | | The CS:partstat and CS:private-comment child elements |
- | | MUST only be present if the relevant properties or |
- | | parameters were changed. If the calendar object is |
- | | not recurring, CS:recurrences MUST NOT be present. |
- | | If all or any individual instances of a recurring |
- | | calendar object were affected, then CS:recurrences |
- | | MUST be present and indicate which instances were |
- | | affected.. |
+ | | element indicates which Attendee replied. The |
+ | | CS:recurrence element indicates which recurrence |
+ | | instance was changed and whether the change was to |
+ | | the Attendee's PARTSTAT parameter or |
+ | | X-CALENDARSERVER-PRIVATE-COMMENT property. |
+-----------+-------------------------------------------------------+
-4.1.2.3. CS:changes XML Element
+4.1.2.3. CS:recurrence XML Element
- This element indicates the key changes that took place. The child
- element CS:changed-property lists all the properties in all instances
- that changed, with the name attribute on each element indicating
- which iCalendar property changed. There MUST only be one CD:changed-
- property element for a specific name attribute value, i.e. if
- multiple properties of the same name changed, only one CS:changed-
- property will appear.
-
-
-
-Daboo [Page 6]
-
- CalDAV Scheduling Change Indicators February 2009
-
-
- For each CD:changed-property element, if any parameters were changed
- on the corresponding properties, then those should be includes as
- child elements CD:changed-parameter, with the name attribute on those
- elements containing the name of the parameter changed. As with CS:
- changed-proeprties, there MUST only be one CS:changed-parameter
- element for each iCalendar parameter that changed.
-
-4.1.2.4. CS:recurrences XML Element
-
This element indicates which instances were affected by a change:
+-----------------+-------------------------------------------------+
| Child Element | Description |
+-----------------+-------------------------------------------------+
| CS:master | The "master" component defining the recurrence |
- | | pattern was changed. |
+ | | pattern was changed, or a non-recurring |
+ | | component was changed. |
| | |
| CS:recurrenceid | The instance with the specified "RECURRENCE-ID" |
| | value was changed. |
+ | | |
+ | CS:changes | Detailed changes - see next section. This |
+ | | element is not present when processing a |
+ | | "CANCEL". |
+-----------------+-------------------------------------------------+
- If no child elements were specified, then all instances were changed.
+Daboo [Page 7]
+
+ CalDAV Scheduling Change Indicators April 2009
+
+
+4.1.2.4. CS:changes XML Element
+
+ This element indicates the key changes that took place.
+
+ +---------------------+---------------------------------------------+
+ | Child Element | Description |
+ +---------------------+---------------------------------------------+
+ | CS:changed-property | Indicates which iCalendar property changed. |
+ | | The "name" attribute on the XML element is |
+ | | the name of the iCalendar property that |
+ | | changed. There MUST only be one |
+ | | CS:changed-property element for a specific |
+ | | name attribute value, i.e. if multiple |
+ | | properties of the same name changed, only |
+ | | one CS:changed-property will appear. For |
+ | | each CS:changed-property element, if any |
+ | | property parameters were changed on the |
+ | | corresponding properties, then those should |
+ | | be included as CS:changed-parameter child |
+ | | elements, with the "name" attribute on |
+ | | those elements containing the name of the |
+ | | iCalendar property parameter changed. As |
+ | | with CS:changed-property, there MUST only |
+ | | be one CS:changed-parameter element for |
+ | | each iCalendar property parameter that |
+ | | changed. |
+ +---------------------+---------------------------------------------+
+
+
5. Security Considerations
TODO:
@@ -381,18 +442,17 @@
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
- [RFC2445] Dawson, F. and Stenerson, D., "Internet Calendaring and
- Scheduling Core Object Specification (iCalendar)",
- RFC 2445, November 1998.
+Daboo [Page 8]
+
+ CalDAV Scheduling Change Indicators April 2009
-Daboo [Page 7]
-
- CalDAV Scheduling Change Indicators February 2009
+ [RFC2445] Dawson, F. and Stenerson, D., "Internet Calendaring and
+ Scheduling Core Object Specification (iCalendar)",
+ RFC 2445, November 1998.
-
[RFC2446] Silverberg, S., Mansour, S., Dawson, F., and R. Hopson,
"iCalendar Transport-Independent Interoperability Protocol
(iTIP) Scheduling Events, BusyTime, To-dos and Journal
@@ -412,6 +472,19 @@
calendar server and client teams.
+Appendix B. Change History
+
+ Changes in -03
+
+ 1. Re-worked XML schema to allow for per-instance changes to be
+ indicated.
+
+ Changes in -02
+
+ 1. CS:changes element changed to use CS:changed-property child
+ elements for more detailed information.
+
+
Author's Address
Cyrus Daboo
@@ -427,22 +500,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Daboo [Page 8]
+Daboo [Page 9]
Modified: CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.xml
===================================================================
--- CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.xml 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/doc/Extensions/caldav-schedulingchanges.xml 2009-04-27 16:14:20 UTC (rev 4090)
@@ -17,7 +17,7 @@
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<?rfc private="Calendar Server Extension"?>
-<rfc ipr="none" docName='caldav-schedulingchanges-02'>
+<rfc ipr="none" docName='caldav-schedulingchanges-03'>
<front>
<title abbrev="CalDAV Scheduling Change Indicators">Change Indicators for Processed CalDAV Scheduling Messages</title>
<author initials="C." surname="Daboo" fullname="Cyrus Daboo">
@@ -109,56 +109,59 @@
<!ELEMENT create EMPTY>
<!-- New calendar object was created -->
- <!ELEMENT update (changes, recurrences?)>
+ <!ELEMENT update (recurrence+)>
<!-- Calendar object was changed -->
- <!ELEMENT cancel (recurrences?)>
- <!-- Calendar object or instances were cancelled -->
+ <!ELEMENT cancel (recurrence*)>
+ <!-- Calendar object was cancelled -->
- <!ELEMENT reply (attendee, partstat?, private-comment?,
- recurrences?)>
+ <!ELEMENT reply (attendee, recurrence+)>
<!-- Reply received from attendee -->
- <!ELEMENT attendee CDATA>
- <!-- ATTENDEE iCalendar property value -->
+ <!ELEMENT recurrence
+ ((master | recurrenceid), changes)>
+ <!-- Which instances were affected by the change,
+ and details on the per-instance changes -->
- <!ELEMENT partstat EMPTY>
- <!-- ATTENDEE PARTSTAT property parameter value changed -->
+ <!ELEMENT master EMPTY>
+ <!-- The "master" instance was affected -->
- <!ELEMENT private-comment EMPTY>
- <!-- X-CALENDARSERVER-PRIVATE-COMMENT property value
- changed -->
+ <!ELEMENT recurrenceid CDATA>
+ <!-- RECURRENCE-ID value for the affected instance -->
<!ELEMENT changes changed-property*>
+ <!-- Detailed changes in the iCalendar data -->
+
+ <!ELEMENT changed-property changed-parameter*>
<!ATTLIST changed-property name PCDATA>
+ <!-- An iCalendar property changed -->
- <!ELEMENT changed-property changed-parameter*>
+ <!ELEMENT changed-parameter EMPTY>
<!ATTLIST changed-parameter name PCDATA>
+ <!-- An iCalendar property parameter changed -->
- <!ELEMENT recurrences (master?, recurrenceid*)>
- <!-- Which instances were affected by the change -->
+ <!ELEMENT attendee CDATA>
+ <!-- ATTENDEE iCalendar property value -->
- <!ELEMENT master EMPTY>
- <!-- The "master" instance was affected -->
-
- <!ELEMENT recurrenceid CDATA>
- <!-- RECURRENCE-ID value for the affected instance -->
-
]]></artwork>
</figure>
</t>
<t hangText="Example:">
+ This example indicates that a new calendar component was created.
<figure>
<artwork><![CDATA[
<CS:schedule-changes
xmlns:CS="http://calendarserver.org/ns/">
<CS:dtstamp>20080818T223423Z</CS:dtstamp>
- <CS:action><CS:create/></CS:action>
+ <CS:action>
+ <CS:create/>
+ </CS:action>
</CS:schedule-changes>
]]></artwork>
</figure>
</t>
<t hangText="Example:">
+ This example indicates that a non-recurring component, or the master component in a recurring component, was changed and that the change was to the "SUMMARY" iCalendar property.
<figure>
<artwork><![CDATA[
<CS:schedule-changes
@@ -166,24 +169,71 @@
<CS:dtstamp>20080818T223423Z</CS:dtstamp>
<CS:action>
<CS:update>
- <CS:changes>
- <CS:changed-property name="SUMMARY"/>
- </CS:changes>
- <CS:recurrences/>
+ <CS:recurrence>
+ <CS:master/>
+ <CS:changes>
+ <CS:changed-property name="SUMMARY"/>
+ </CS:changes>
+ <CS:recurrence/>
</CS:update>
</CS:action>
</CS:schedule-changes>
]]></artwork>
</figure>
</t>
+ <t hangText="Example:">
+ This example indicates that two recurrence instances were cancelled from a recurring component.
+ <figure>
+ <artwork><![CDATA[
+<CS:schedule-changes
+ xmlns:CS="http://calendarserver.org/ns/">
+ <CS:dtstamp>20080818T223423Z</CS:dtstamp>
+ <CS:action>
+ <CS:cancel>
+ <CS:recurrence>
+ <CS:recurrence-id>20090101T010000Z</CS:recurrence-id>
+ <CS:recurrence/>
+ <CS:recurrence>
+ <CS:recurrence-id>20090102T010000Z</CS:recurrence-id>
+ <CS:recurrence/>
+ </CS:update>
+ </CS:action>
+</CS:schedule-changes>
+ ]]></artwork>
+ </figure>
+ </t>
+ <t hangText="Example:">
+ This example indicates that the Attendee with calendar user address "mailto:cyrus at example.com" replied to the Organizer and changed their "PARTSTAT" iCalendar property parameter on one recurrence instance.
+ <figure>
+ <artwork><![CDATA[
+<CS:schedule-changes
+ xmlns:CS="http://calendarserver.org/ns/">
+ <CS:dtstamp>20080818T223423Z</CS:dtstamp>
+ <CS:action>
+ <CS:reply>
+ <CS:attendee>mailto:cyrus at example.com</CS:attendee>
+ <CS:recurrence>
+ <CS:recurrence-id>20090101T010000Z</CS:recurrence-id>
+ <CS:changes>
+ <CS:changed-property name="ATTENDEE">
+ <CS:changed-parameter name="PARTSTAT"/>
+ </CS:changed-property>
+ </CS:changes>
+ <CS:recurrence/>
+ </CS:update>
+ </CS:action>
+</CS:schedule-changes>
+ ]]></artwork>
+ </figure>
+ </t>
</list>
<?rfc compact="yes" ?>
</t>
</section>
<section title="CS:schedule-changes XML element">
- <t>The CS:schedule-changes XML element is used to indicate what changes were made when the server automatically processed a scheduling message. There are four child elements that can appear, and each is described next.</t>
+ <t>The CS:schedule-changes XML element is used to indicate what changes were made when the server automatically processed a scheduling message. There are two child elements that can appear, and each is described next.</t>
<section title="CS:dtstamp XML Element">
- <t>This elements contains a text value in the form of an iCalendar Date-Time value in UTC. This value is the time at which the automatic processing took place.</t>
+ <t>This element contains a text value in the form of an iCalendar Date-Time value in UTC. This value is the time at which the automatic processing took place.</t>
</section>
<section title="CS:action XML Element">
<t>This element indicates the nature of the changes that took place:</t>
@@ -198,42 +248,54 @@
<c> </c>
<c>CS:update</c>
- <c>An update to an existing calendar object occurred. The CS:changes and CS:recurrences child elements indicate what the changes were and which instances were affected. If the calendar object is not recurring, CS:recurrences MUST NOT be present. If all or any individual instances of a recurring calendar object were affected, then CS:recurrences MUST be present and indicate which instances were affected.</c>
+ <c>An update to an existing calendar object occurred.
+ A CS:recurrence element is included for each recurrence instance changed. Each CS:recurrence element indicates the specific instance that was changes as well as details on which properties or parameters changed.</c>
<c> </c>
<c> </c>
<c>CS:cancel</c>
- <c>A cancellation scheduling message was processed. If the calendar object is not recurring or all instances are being removed, then CS:recurrences MUST NOT be present. If any individual instances of a recurring calendar object were affected, then CS:recurrences MUST be present and indicate which instances were affected.</c>
+ <c>A cancellation scheduling message was processed. If the calendar object is not recurring or all instances are being removed, then there MUST NOT be any CS:recurrence element present. If any individual instances of a recurring calendar object were affected, then a CS:recurrence element MUST be present and indicate which instances were affected.</c>
<c> </c>
<c> </c>
<c>CS:reply</c>
- <c>An Attendee's reply was processed. The CS:attendee, CS:partstat and CS:private-comment elements indicate which Attendee replied, whether their "PARTSTAT" changed, and whether any private comment was changed. The CS:partstat and CS:private-comment child elements MUST only be present if the relevant properties or parameters were changed. If the calendar object is not recurring, CS:recurrences MUST NOT be present. If all or any individual instances of a recurring calendar object were affected, then CS:recurrences MUST be present and indicate which instances were affected..</c>
+ <c>An Attendee's reply was processed. The CS:attendee, element indicates which Attendee replied. The CS:recurrence element indicates which recurrence instance was changed and whether the change was to the Attendee's PARTSTAT parameter or X-CALENDARSERVER-PRIVATE-COMMENT property.</c>
</texttable>
</section>
- <section title="CS:changes XML Element">
- <t>This element indicates the key changes that took place. The child element CS:changed-property lists all the properties in all instances that changed, with the name attribute on each element indicating which iCalendar property changed. There MUST only be one CD:changed-property element for a specific name attribute value, i.e. if multiple properties of the same name changed, only one CS:changed-property will appear.</t>
- <t>For each CD:changed-property element, if any parameters were changed on the corresponding properties, then those should be includes as child elements CD:changed-parameter, with the name attribute on those elements containing the name of the parameter changed. As with CS:changed-proeprties, there MUST only be one CS:changed-parameter element for each iCalendar parameter that changed.</t>
- </section>
- <section title="CS:recurrences XML Element">
+ <section title="CS:recurrence XML Element">
<t>This element indicates which instances were affected by a change:</t>
<texttable>
<ttcol>Child Element</ttcol>
<ttcol>Description</ttcol>
<c>CS:master</c>
- <c>The "master" component defining the recurrence pattern was changed.</c>
+ <c>The "master" component defining the recurrence pattern was changed, or a non-recurring component was changed.</c>
<c> </c>
<c> </c>
<c>CS:recurrenceid</c>
<c>The instance with the specified "RECURRENCE-ID" value was changed.</c>
+
+ <c> </c>
+ <c> </c>
+
+ <c>CS:changes</c>
+ <c>Detailed changes - see next section. This element is not present when processing a "CANCEL".</c>
</texttable>
- <t>If no child elements were specified, then all instances were changed.</t>
</section>
+ <section title="CS:changes XML Element">
+ <t>This element indicates the key changes that took place.</t>
+ <texttable>
+ <ttcol>Child Element</ttcol>
+ <ttcol>Description</ttcol>
+
+ <c>CS:changed-property</c>
+ <c>Indicates which iCalendar property changed. The "name" attribute on the XML element is the name of the iCalendar property that changed. There MUST only be one CS:changed-property element for a specific name attribute value, i.e. if multiple properties of the same name changed, only one CS:changed-property will appear. For each CS:changed-property element, if any property parameters were changed on the corresponding properties, then those should be included as CS:changed-parameter child elements, with the "name" attribute on those elements containing the name of the iCalendar property parameter changed. As with CS:changed-property, there MUST only be one CS:changed-parameter element for each iCalendar property parameter that changed.</c>
+ </texttable>
+ </section>
</section>
</section>
</section>
@@ -265,14 +327,17 @@
This specification is the result of discussions between the Apple calendar server and client teams.
</t>
</section>
- <!--
<section title='Change History'>
- <t>Changes since -00
+ <t>Changes in -03
<list style='numbers'>
- <t></t>
+ <t>Re-worked XML schema to allow for per-instance changes to be indicated.</t>
</list>
</t>
+ <t>Changes in -02
+ <list style='numbers'>
+ <t>CS:changes element changed to use CS:changed-property child elements for more detailed information.</t>
+ </list>
+ </t>
</section>
- -->
</back>
</rfc>
Modified: CalendarServer/trunk/run
===================================================================
--- CalendarServer/trunk/run 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/run 2009-04-27 16:14:20 UTC (rev 4090)
@@ -724,7 +724,7 @@
caldavtester="${top}/CalDAVTester";
-svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4075;
+svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4088;
#
# PyFlakes
Modified: CalendarServer/trunk/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/customxml.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/customxml.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -463,8 +463,7 @@
namespace = calendarserver_namespace
name = "update"
allowed_children = {
- (calendarserver_namespace, "changes" ) : (1, 1),
- (calendarserver_namespace, "recurrences" ) : (0, 1),
+ (calendarserver_namespace, "recurrence" ) : (1, None),
}
class Cancel (davxml.WebDAVElement):
@@ -474,7 +473,7 @@
namespace = calendarserver_namespace
name = "cancel"
allowed_children = {
- (calendarserver_namespace, "recurrences" ) : (0, 1),
+ (calendarserver_namespace, "recurrence" ) : (0, 1),
}
class Reply (davxml.WebDAVElement):
@@ -485,30 +484,34 @@
name = "reply"
allowed_children = {
(calendarserver_namespace, "attendee" ) : (1, 1),
- (calendarserver_namespace, "partstat" ) : (0, 1),
- (calendarserver_namespace, "private-comment" ) : (0, 1),
+ (calendarserver_namespace, "recurrence" ) : (1, None),
}
-class Attendee (davxml.WebDAVTextElement):
+class Recurrence (davxml.WebDAVElement):
"""
- An attendee calendar user address.
+ Changes to an event.
"""
namespace = calendarserver_namespace
- name = "attendee"
+ name = "recurrence"
+ allowed_children = {
+ (calendarserver_namespace, "master" ) : (0, 1),
+ (calendarserver_namespace, "recurrenceid" ) : (0, None),
+ (calendarserver_namespace, "changes" ) : (0, 1),
+ }
-class PartStat (davxml.WebDAVEmptyElement):
+class Master (davxml.WebDAVEmptyElement):
"""
- An attendee partstat.
+ Master instance changed.
"""
namespace = calendarserver_namespace
- name = "partstat"
+ name = "master"
-class PrivateComment (davxml.WebDAVEmptyElement):
+class RecurrenceID (davxml.WebDAVTextElement):
"""
- An attendee private comment.
+ A recurrence instance changed.
"""
namespace = calendarserver_namespace
- name = "private-comment"
+ name = "recurrenceid"
class Changes (davxml.WebDAVElement):
"""
@@ -546,31 +549,13 @@
"name" : True,
}
-class Recurrences (davxml.WebDAVElement):
+class Attendee (davxml.WebDAVTextElement):
"""
- Changes to an event.
+ An attendee calendar user address.
"""
namespace = calendarserver_namespace
- name = "recurrences"
- allowed_children = {
- (calendarserver_namespace, "master" ) : (0, 1),
- (calendarserver_namespace, "recurrenceid" ) : (0, None),
- }
+ name = "attendee"
-class Master (davxml.WebDAVEmptyElement):
- """
- Master instance changed.
- """
- namespace = calendarserver_namespace
- name = "master"
-
-class RecurrenceID (davxml.WebDAVTextElement):
- """
- A recurrence instance changed.
- """
- namespace = calendarserver_namespace
- name = "recurrenceid"
-
class RecordType (davxml.WebDAVTextElement):
"""
Exposes the type of a record
Modified: CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -589,8 +589,7 @@
map[(name, uid, rid,)] = component
return map
- props_changed = {}
- rids = set()
+ rids = {}
map1 = mapComponents(self.calendar1)
set1 = set(map1.keys())
@@ -601,7 +600,7 @@
for key in (set1 & set2):
component1 = map1[key]
component2 = map2[key]
- self._diffComponents(component1, component2, props_changed, rids)
+ self._diffComponents(component1, component2, rids)
# Now verify that each additional component in set1 matches a derived component in set2
for key in set1 - set2:
@@ -609,7 +608,7 @@
component2 = self.calendar2.deriveInstance(key[2])
if component2 is None:
continue
- self._diffComponents(component1, component2, props_changed, rids)
+ self._diffComponents(component1, component2, rids)
# Now verify that each additional component in set1 matches a derived component in set2
for key in set2 - set1:
@@ -617,11 +616,9 @@
if component1 is None:
continue
component2 = map2[key]
- self._diffComponents(component1, component2, props_changed, rids)
+ self._diffComponents(component1, component2, rids)
- if not self.calendar1.isRecurring() and not self.calendar2.isRecurring() or not props_changed:
- rids = None
- return props_changed, rids
+ return rids
def _attendeeDuplicateAndNormalize(self, calendar):
calendar = calendar.duplicate()
@@ -632,7 +629,7 @@
iTipGenerator.prepareSchedulingMessage(calendar, reply=True)
return calendar
- def _diffComponents(self, comp1, comp2, changed, rids):
+ def _diffComponents(self, comp1, comp2, rids):
assert isinstance(comp1, Component) and isinstance(comp2, Component)
@@ -648,6 +645,7 @@
comp2.transformAllToNative()
addedChanges = False
+ propsChanged = {}
for prop in propdiff:
if prop.name() in (
"TRANSP",
@@ -658,7 +656,7 @@
"X-CALENDARSERVER-PRIVATE-COMMENT",
):
continue
- changed.setdefault(prop.name(), set())
+ propsChanged.setdefault(prop.name(), set())
addedChanges = True
prop1s = tuple(comp1.properties(prop.name()))
prop2s = tuple(comp2.properties(prop.name()))
@@ -666,14 +664,14 @@
param1s = set(["%s=%s" % (name, value) for name, value in prop1s[0].params().iteritems()])
param2s = set(["%s=%s" % (name, value) for name, value in prop2s[0].params().iteritems()])
paramDiffs = param1s ^ param2s
- changed[prop.name()].update([param.split("=")[0] for param in paramDiffs])
- if "ORIGINAL-TZID" in changed[prop.name()]:
- changed[prop.name()].remove("ORIGINAL-TZID")
- changed[prop.name()].add("TZID")
+ propsChanged[prop.name()].update([param.split("=")[0] for param in paramDiffs])
+ if "ORIGINAL-TZID" in propsChanged[prop.name()]:
+ propsChanged[prop.name()].remove("ORIGINAL-TZID")
+ propsChanged[prop.name()].add("TZID")
if addedChanges:
rid = comp1.getRecurrenceIDUTC()
- rids.add(toString(rid) if rid is not None else "")
+ rids[toString(rid) if rid is not None else ""] = propsChanged
def _logDiffError(self, title):
Modified: CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -496,7 +496,7 @@
differ = iCalDiff(self.oldcalendar, self.calendar, self.do_smart_merge)
no_change = differ.organizerDiff()
if not no_change:
- _ignore_props, rids = differ.whatIsDifferent()
+ rids = set(differ.whatIsDifferent().keys())
else:
# Special case of RSVP added to attendees and no other change
rsvps = set()
Modified: CalendarServer/trunk/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/itip.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/scheduling/itip.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -91,7 +91,7 @@
# Merge Organizer data with Attendee's own changes (VALARMs, Comment only for now).
from twistedcaldav.scheduling.icaldiff import iCalDiff
- props_changed, rids = iCalDiff(calendar, itip_message, False).whatIsDifferent()
+ rids = iCalDiff(calendar, itip_message, False).whatIsDifferent()
# Different behavior depending on whether a master component is present or not
current_master = calendar.masterComponent()
@@ -135,7 +135,7 @@
iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, new_component)
# Replace the entire object
- return new_calendar, props_changed, rids
+ return new_calendar, rids
else:
# Need existing tzids
@@ -155,7 +155,7 @@
iTipProcessing.fixForiCal3((component,), recipient, config.Scheduling.CalDAV.OldDraftCompatibility)
# Write back the modified object
- return calendar, props_changed, rids
+ return calendar, rids
@staticmethod
def processCancel(itip_message, calendar, autoprocessing=False):
@@ -274,16 +274,12 @@
old_master = calendar.masterComponent()
new_master = itip_message.masterComponent()
attendees = set()
- partstat_changed = False
- private_comment_changed = False
- rids = set() if old_master.isRecurring() else None
+ rids = set()
if new_master:
attendee, partstat, private_comment = iTipProcessing.updateAttendeeData(new_master, old_master)
attendees.add(attendee)
- partstat_changed = partstat_changed or partstat
- private_comment_changed = private_comment_changed or private_comment
- if rids is not None and (partstat_changed or private_comment_changed):
- rids.add("")
+ if partstat or private_comment:
+ rids.add(("", partstat, private_comment,))
# Now do all overridden ones (sort by RECURRENCE-ID)
sortedComponents = []
@@ -311,12 +307,11 @@
attendee, partstat, private_comment = iTipProcessing.updateAttendeeData(itip_component, match_component)
attendees.add(attendee)
- partstat_changed = partstat_changed or partstat
- private_comment_changed = private_comment_changed or private_comment
if rids is not None and (partstat or private_comment):
- rids.add(toString(rid))
+ rids.add((toString(rid), partstat, private_comment,))
- return True, (attendees, partstat_changed, private_comment_changed, rids)
+ assert len(attendees) == 1, "ATTENDEE property in a REPLY must be the same in all components\n%s" % (str(itip_message),)
+ return True, (attendees.pop(), rids)
@staticmethod
def updateAttendeeData(from_component, to_component):
Modified: CalendarServer/trunk/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -162,18 +162,24 @@
recipient_calendar_resource = (yield self.writeCalendarResource(self.recipient_calendar_collection_uri, self.recipient_calendar_collection, self.recipient_calendar_name, self.recipient_calendar))
# Build the schedule-changes XML element
- processed_attendees, partstat_changed, private_comment_changed, rids = processed
- reply_details = (customxml.Attendee.fromString(tuple(processed_attendees)[0]),)
- if partstat_changed:
- reply_details += (customxml.PartStat(),)
- if private_comment_changed:
- reply_details += (customxml.PrivateComment(),)
- if rids is not None:
- recurrences = []
- if "" in rids:
- recurrences.append(customxml.Master())
- recurrences.extend([customxml.RecurrenceID.fromString(rid) for rid in rids if rid != ""])
- reply_details += (customxml.Recurrences(*recurrences),)
+ attendeeReplying, rids = processed
+ partstatChanged = False
+ reply_details = (customxml.Attendee.fromString(attendeeReplying),)
+
+ for rid, partstatChanged, privateCommentChanged in sorted(rids):
+ recurrence = []
+ if rid == "":
+ recurrence.append(customxml.Master())
+ else:
+ recurrence.append(customxml.RecurrenceID.fromString(rid))
+ changes = []
+ if partstatChanged:
+ changes.append(customxml.ChangedProperty(customxml.ChangedParameter(name="PARTSTAT"), name="ATTENDEE" ))
+ partstatChanged = True
+ if privateCommentChanged:
+ changes.append(customxml.ChangedProperty(name="X-CALENDARSERVER-PRIVATE-COMMENT"))
+ recurrence.append(customxml.Changes(*changes))
+ reply_details += (customxml.Recurrence(*recurrence),)
changes = customxml.ScheduleChanges(
customxml.DTStamp(),
@@ -183,8 +189,8 @@
)
# Only update other attendees when the partstat was changed by the reply
- if partstat_changed:
- self.updateAllAttendeesExceptSome(recipient_calendar_resource, processed_attendees)
+ if partstatChanged:
+ self.updateAllAttendeesExceptSome(recipient_calendar_resource, (attendeeReplying,))
result = (True, False, changes,)
@@ -293,7 +299,7 @@
else:
# Processing update to existing event
autoprocessed = (yield self.recipient.principal.getAutoSchedule())
- new_calendar, props_changed, rids = iTipProcessing.processRequest(self.message, self.recipient_calendar, self.recipient.cuaddr, autoprocessing=autoprocessed)
+ new_calendar, rids = iTipProcessing.processRequest(self.message, self.recipient_calendar, self.recipient.cuaddr, autoprocessing=autoprocessed)
if new_calendar:
# Handle auto-reply behavior
@@ -308,18 +314,20 @@
reactor.callLater(2.0, self.sendAttendeeAutoReply, *(new_calendar, new_resource, partstat))
# Build the schedule-changes XML element
- changes = []
- if props_changed:
+ update_details = []
+ for rid, props_changed in sorted(rids.iteritems(), key=lambda x:x[0]):
+ recurrence = []
+ if rid == "":
+ recurrence.append(customxml.Master())
+ else:
+ recurrence.append(customxml.RecurrenceID.fromString(rid))
+ changes = []
for propName, paramNames in sorted(props_changed.iteritems(), key=lambda x:x[0]):
params = tuple([customxml.ChangedParameter(name=param) for param in paramNames])
changes.append(customxml.ChangedProperty(*params, **{"name":propName}))
- update_details = (customxml.Changes(*changes),)
- if rids is not None:
- recurrences = []
- if "" in rids:
- recurrences.append(customxml.Master())
- recurrences.extend([customxml.RecurrenceID.fromString(rid) for rid in rids if rid != ""])
- update_details += (customxml.Recurrences(*recurrences),)
+ recurrence.append(customxml.Changes(*changes))
+ update_details += (customxml.Recurrence(*recurrence),)
+
changes = customxml.ScheduleChanges(
customxml.DTStamp(),
customxml.Action(
@@ -378,14 +386,15 @@
yield self.writeCalendarResource(self.recipient_calendar_collection_uri, self.recipient_calendar_collection, self.recipient_calendar_name, self.recipient_calendar)
# Build the schedule-changes XML element
- actions = (customxml.Cancel(),)
if rids:
- actions += (customxml.Recurrences(
- *[customxml.RecurrenceID.fromString(rid) for rid in rids]
- ),)
+ action = customxml.Cancel(
+ *[customxml.Recurrence(customxml.RecurrenceID.fromString(rid)) for rid in sorted(rids)]
+ )
+ else:
+ action = customxml.Cancel()
changes = customxml.ScheduleChanges(
customxml.DTStamp(),
- customxml.Action(*actions),
+ customxml.Action(action),
)
result = (True, autoprocessed, changes)
else:
Modified: CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-04-27 16:13:04 UTC (rev 4089)
+++ CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-04-27 16:14:20 UTC (rev 4090)
@@ -2277,7 +2277,6 @@
END:VCALENDAR
""",
{},
- (),
),
(
"#1.2 Simple component, one property change",
@@ -2303,8 +2302,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(),},
- (),
+ {"":{"SUMMARY":set(),}},
),
(
"#1.3 Simple component, one property change, one addition, one removal",
@@ -2332,8 +2330,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(), "LOCATION":set(), "DESCRIPTION":set(),},
- (),
+ {"":{"SUMMARY":set(), "LOCATION":set(), "DESCRIPTION":set(),}},
),
(
"#1.4 Simple component, add attendee",
@@ -2366,8 +2363,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- (),
+ {"":{"ATTENDEE":set(),}},
),
(
"#1.5 Simple component, remove attendee",
@@ -2398,8 +2394,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- (),
+ {"":{"ATTENDEE":set(),}},
),
(
"#1.6 Simple component, attendee PARTSTAT only",
@@ -2431,8 +2426,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- (),
+ {"":{"ATTENDEE":set(),}},
),
(
"#1.7 Simple component, attendee PARTSTAT and addition",
@@ -2465,8 +2459,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- (),
+ {"":{"ATTENDEE":set(),}},
),
(
"#1.8 Simple component, attendee RSVP only",
@@ -2498,8 +2491,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- (),
+ {"":{"ATTENDEE":set(),}},
),
(
"#1.9 Simple component, DTSTART/DTEND VALUE",
@@ -2531,8 +2523,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"DTEND":set(("VALUE",)), "DTSTART":set(("VALUE",)),},
- (),
+ {"":{"DTEND":set(("VALUE",)), "DTSTART":set(("VALUE",)),}},
),
(
"#1.10 Simple component, DTSTART/DTEND TZID",
@@ -2600,8 +2591,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"DTEND":set(("TZID",)), "DTSTART":set(("TZID",)),},
- (),
+ {"":{"DTEND":set(("TZID",)), "DTSTART":set(("TZID",)),}},
),
)
@@ -2639,7 +2629,6 @@
END:VCALENDAR
""",
{},
- (),
),
(
"#2.2 Simple component, one property change",
@@ -2667,8 +2656,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(),},
- ("",),
+ {"":{"SUMMARY":set(),}},
),
(
"#2.3 Simple component, one property change, one addition, one removal",
@@ -2698,8 +2686,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(), "LOCATION":set(), "DESCRIPTION":set(),},
- ("",),
+ {"":{"SUMMARY":set(), "LOCATION":set(), "DESCRIPTION":set(),}},
),
(
"#2.4 Simple component, add attendee",
@@ -2734,8 +2721,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- ("",),
+ {"":{"ATTENDEE":set(),}},
),
(
"#2.5 Simple component, remove attendee",
@@ -2768,8 +2754,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- ("",),
+ {"":{"ATTENDEE":set(),}},
),
(
"#2.6 Simple component, attendee PARTSTAT only",
@@ -2803,8 +2788,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- ("",),
+ {"":{"ATTENDEE":set(),}},
),
(
"#2.7 Simple component, attendee PARTSTAT and addition",
@@ -2839,8 +2823,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"ATTENDEE":set(),},
- ("",),
+ {"":{"ATTENDEE":set(),}},
),
)
@@ -2898,7 +2881,6 @@
END:VCALENDAR
""",
{},
- (),
),
(
"#3.2 Simple component, one property change in instance",
@@ -2946,8 +2928,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(),},
- ("20080602T120000Z",),
+ {"20080602T120000Z":{"SUMMARY":set(),}},
),
(
"#3.3 Simple component, one property change in master",
@@ -2995,8 +2976,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(),},
- ("",),
+ {"":{"SUMMARY":set(),}},
),
(
"#3.4 Simple component, one property change in master and instance",
@@ -3044,8 +3024,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(),},
- ("", "20080602T120000Z",),
+ {"":{"SUMMARY":set(),}, "20080602T120000Z":{"SUMMARY":set(),}},
),
(
"#3.5 Simple component, different property change in master and instance",
@@ -3094,8 +3073,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"SUMMARY":set(), "DESCRIPTION":set()},
- ("", "20080602T120000Z",),
+ {"":{"SUMMARY":set()}, "20080602T120000Z":{"DESCRIPTION":set()}},
),
(
"#3.6 Simple component, instance added no change",
@@ -3131,7 +3109,6 @@
END:VCALENDAR
""",
{},
- (),
),
(
"#3.7 Simple component, instance added time change",
@@ -3166,8 +3143,7 @@
END:VEVENT
END:VCALENDAR
""",
- {"DTSTART":set(), "DTEND":set(), },
- ("20080602T120000Z",),
+ {"20080602T120000Z":{"DTSTART":set(), "DTEND":set(), }},
),
(
"#3.8 Simple component, instance removed no change",
@@ -3203,7 +3179,6 @@
END:VCALENDAR
""",
{},
- (),
),
(
"#3.9 Simple component, instance removed time change",
@@ -3238,18 +3213,14 @@
END:VEVENT
END:VCALENDAR
""",
- {"DTSTART":set(), "DTEND":set(), },
- ("20080602T120000Z",),
+ {"20080602T120000Z":{"DTSTART":set(), "DTEND":set(), }},
),
)
- for description, calendar1, calendar2, changes, rids in itertools.chain(data1, data2, data3,):
+ for description, calendar1, calendar2, rids in itertools.chain(data1, data2, data3,):
differ = iCalDiff(Component.fromString(calendar1), Component.fromString(calendar2), False)
- expected_changes = changes
- expected_rids = set(rids) if rids else None
- got_changes, got_rids = differ.whatIsDifferent()
- self.assertEqual(got_changes, expected_changes, msg="%s expected changes: '%s', got: '%s'" % (description, expected_changes, got_changes,))
- self.assertEqual(got_rids, expected_rids, msg="%s expected R-IDs: '%s', got: '%s'" % (description, expected_rids, got_rids,))
+ got_rids = differ.whatIsDifferent()
+ self.assertEqual(got_rids, rids, msg="%s expected R-IDs: '%s', got: '%s'" % (description, rids, got_rids,))
def test_organizer_smart_merge(self):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090427/bdc0e17b/attachment-0001.html>
More information about the calendarserver-changes
mailing list