[CalendarServer-changes] [13942] CalendarServer/trunk/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Fri Sep 5 13:35:08 PDT 2014
Revision: 13942
http://trac.calendarserver.org//changeset/13942
Author: cdaboo at apple.com
Date: 2014-09-05 13:35:08 -0700 (Fri, 05 Sep 2014)
Log Message:
-----------
Fix issue with group reconciliation when an attendee is removed as a member of one group but is still a member of another.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/ical.py
CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py 2014-09-05 20:25:47 UTC (rev 13941)
+++ CalendarServer/trunk/twistedcaldav/ical.py 2014-09-05 20:35:08 UTC (rev 13942)
@@ -3501,16 +3501,16 @@
# remove attendee or update MEMBER attribute for non-primary attendees in this group,
for attendeeProp in oldAttendeeProps:
if attendeeProp.hasParameter("MEMBER"):
- parameterValues = tuple(attendeeProp.parameterValues("MEMBER"))
- if groupCUA in parameterValues:
+ memberValues = attendeeProp.parameterValues("MEMBER")
+ if groupCUA in tuple(memberValues):
if attendeeProp.value() not in memberCUAs:
- attendeeProp.removeParameterValue("MEMBER", groupCUA)
- if not attendeeProp.parameterValues("MEMBER"):
+ memberValues.remove(groupCUA)
+ if len(memberValues) == 0:
component.removeProperty(attendeeProp)
changed = True
else:
if attendeeProp.value() in memberCUAs:
- attendeeProp.setParameter("MEMBER", parameterValues + (groupCUA,))
+ memberValues.append(groupCUA)
changed = True
return changed
@@ -3537,10 +3537,10 @@
attendeeCUA = attendeeProp.value()
if attendeeCUA in allMemberCUAs:
# remove orphan member values
- parameterValues = tuple(attendeeProp.parameterValues("MEMBER"))
- for orphanGroupCUA in set(parameterValues) - nonemptyGroupCUAs:
- attendeeProp.removeParameterValue("MEMBER", orphanGroupCUA)
- if not attendeeProp.parameterValues("MEMBER"):
+ memberValues = attendeeProp.parameterValues("MEMBER")
+ for orphanGroupCUA in set(memberValues) - nonemptyGroupCUAs:
+ memberValues.remove(orphanGroupCUA)
+ if len(memberValues) == 0:
component.removeProperty(attendeeProp)
changed = True
else:
Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_icalendar.py 2014-09-05 20:25:47 UTC (rev 13941)
+++ CalendarServer/trunk/twistedcaldav/test/test_icalendar.py 2014-09-05 20:35:08 UTC (rev 13942)
@@ -23,7 +23,7 @@
from twistedcaldav.dateops import normalizeForExpand
from twistedcaldav.ical import Component, Property, InvalidICalendarDataError, \
- normalizeCUAddress, normalize_iCalStr
+ normalizeCUAddress, normalize_iCalStr, diff_iCalStrs
from twistedcaldav.ical import iCalendarProductID
from twistedcaldav.instance import InvalidOverriddenInstanceError
import twistedcaldav.test.util
@@ -11082,3 +11082,470 @@
component = Component.fromString(txt).mainComponent()
transp = component.adjustedTransp()
self.assertEqual(transp, result, msg=title)
+
+
+ def test_reconcileGroupAttendees(self):
+ """
+ reconcileGroupAttendees()
+ """
+
+ data = (
+ (
+ "No change",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {},
+ False,
+ ),
+ (
+ "Empty group",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {"urn:uuid:group01": ()},
+ False,
+ ),
+ (
+ "One new member",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group01": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ True,
+ ),
+ (
+ "One existing member",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group01": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ False,
+ ),
+ (
+ "One removed member",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {"urn:uuid:group01": ()},
+ True,
+ ),
+ (
+ "Two members: one existing, one new",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user04 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group01": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ Property("ATTENDEE", "mailto:user04 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ True,
+ ),
+ (
+ "Two existing members",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user04 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user04 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group01": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ Property("ATTENDEE", "mailto:user04 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ False,
+ ),
+ (
+ "One existing, one removed member",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user04 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group01
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user04 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group01": (
+ Property("ATTENDEE", "mailto:user04 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ True,
+ ),
+ (
+ "Member with removed group",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {},
+ True,
+ ),
+ (
+ "Member with removed group added to another",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group02
+ATTENDEE;MEMBER="urn:uuid:group01":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group02
+ATTENDEE;MEMBER="urn:uuid:group02":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group02": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ True,
+ ),
+ (
+ "Member with removed group in another",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group02
+ATTENDEE;MEMBER="urn:uuid:group01","urn:uuid:group02":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART;VALUE=DATE:20080601
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE;CUTYPE=X-SERVER-GROUP:urn:uuid:group02
+ATTENDEE;MEMBER="urn:uuid:group02":mailto:user03 at example.com
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {
+ "urn:uuid:group02": (
+ Property("ATTENDEE", "mailto:user03 at example.com", {"MEMBER": "urn:uuid:group01"}),
+ )
+ },
+ True,
+ ),
+ )
+
+ for title, txt, txt_result, propMap, changed in data:
+ cal = Component.fromString(txt)
+ result = cal.reconcileGroupAttendees(propMap)
+ self.assertEqual(result, changed, msg="{}: {}".format(title, "Result mismatch"))
+ self.assertEqual(normalize_iCalStr(cal), normalize_iCalStr(txt_result), msg="{}:{}".format(title, diff_iCalStrs(cal, txt_result)))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140905/d3467c5b/attachment-0001.html>
More information about the calendarserver-changes
mailing list