[CalendarServer-changes] [14150] CalendarServer/trunk/calendarserver/tools
source_changes at macosforge.org
source_changes at macosforge.org
Mon Nov 10 11:44:51 PST 2014
Revision: 14150
http://trac.calendarserver.org//changeset/14150
Author: sagen at apple.com
Date: 2014-11-10 11:44:51 -0800 (Mon, 10 Nov 2014)
Log Message:
-----------
Adding test for import of events to attendee calendar (not working yet)
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/importer.py
CalendarServer/trunk/calendarserver/tools/test/test_importer.py
Modified: CalendarServer/trunk/calendarserver/tools/importer.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/importer.py 2014-11-09 19:58:30 UTC (rev 14149)
+++ CalendarServer/trunk/calendarserver/tools/importer.py 2014-11-10 19:44:51 UTC (rev 14150)
@@ -178,8 +178,8 @@
ownerUID, collectionResourceName = sourceURI.strip("/").split("/")[-2:]
dir = store.directoryService()
- record = yield dir.recordWithUID(ownerUID)
- if not record:
+ ownerRecord = yield dir.recordWithUID(ownerUID)
+ if not ownerRecord:
raise ImportException("{} is not in the directory".format(ownerUID))
# Set properties on the collection
@@ -201,29 +201,81 @@
# want to batch them?
groupedComponents = Component.componentsFromComponent(component)
for groupedComponent in groupedComponents:
- resourceName = "{}.ics".format(str(uuid.uuid4()))
- try:
- yield storeComponentInHomeAndCalendar(
- store, groupedComponent, ownerUID, collectionResourceName, resourceName
- )
- except UIDExistsError:
- # That event is already in the home
+
+ # If event is unscheduled or the organizer matches homeUID, store the
+ # component
+
+ storeDirectly = True
+ organizer = groupedComponent.getOrganizer()
+ if organizer is not None:
+ organizerRecord = yield dir.recordWithCalendarUserAddress(organizer)
+ if organizerRecord is None:
+ # Organizer does not exist, so skip this event
+ continue
+ else:
+ if ownerRecord.uid != organizerRecord.uid:
+ # Owner is not the organizer
+ storeDirectly = False
+
+ if storeDirectly:
+ resourceName = "{}.ics".format(str(uuid.uuid4()))
try:
- uid = list(groupedComponent.subcomponents())[0].propertyValue("UID")
- except:
- uid = "unknown"
+ yield storeComponentInHomeAndCalendar(
+ store, groupedComponent, ownerUID, collectionResourceName, resourceName
+ )
+ except UIDExistsError:
+ # That event is already in the home
+ try:
+ uid = list(groupedComponent.subcomponents())[0].propertyValue("UID")
+ except:
+ uid = "unknown"
- print("Skipping since UID already exists: {}".format(uid))
+ print("Skipping since UID already exists: {}".format(uid))
- except Exception, e:
- print(
- "Failed to import due to: {error}\n{comp}".format(
- error=e,
- comp=groupedComponent
+ except Exception, e:
+ print(
+ "Failed to import due to: {error}\n{comp}".format(
+ error=e,
+ comp=groupedComponent
+ )
)
- )
+ else:
+ # Owner is not the organizer
+ print("OTHER")
+ txn = store.newTransaction()
+ organizerHome = yield txn.calendarHomeWithUID(organizerRecord.uid)
+ if organizerHome is None:
+ continue
+ # Iterate owner's calendars to find the one containing the event
+ # UID
+ uid = list(groupedComponent.subcomponents())[0].propertyValue("UID")
+ for collection in (yield organizerHome.children()):
+ if collection.name() != "inbox":
+ resourceName = yield collection.resourceNameForUID(uid)
+ print("Resource name", collection, resourceName)
+ object = yield collection.objectResourceWithName(resourceName)
+ component = yield object.component()
+ print ("Comp", component)
+ ownerCUA = ownerRecord.canonicalCalendarUserAddress()
+ print("CUA", ownerCUA)
+ attendeeProp = component.getAttendeeProperty((ownerCUA,))
+ print("att prop", attendeeProp)
+ if attendeeProp is not None:
+ print("Before", attendeeProp)
+ attendeeProp.setParameter("PARTSTAT", "NEEDS-ACTION")
+ attendeeProp.removeParameter("SCHEDULE-STATUS")
+ print("I modified", attendeeProp)
+ result = yield object.setComponent(component)
+ print("Set component result", result)
+
+ break
+
+ yield txn.commit()
+
+
+
@inlineCallbacks
def storeComponentInHomeAndCalendar(
store, component, homeUID, collectionResourceName, objectResourceName
Modified: CalendarServer/trunk/calendarserver/tools/test/test_importer.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_importer.py 2014-11-09 19:58:30 UTC (rev 14149)
+++ CalendarServer/trunk/calendarserver/tools/test/test_importer.py 2014-11-10 19:44:51 UTC (rev 14150)
@@ -18,7 +18,10 @@
Unit tests for L{calendarsever.tools.importer}.
"""
-from calendarserver.tools.importer import importCollectionComponent, ImportException
+from calendarserver.tools.importer import (
+ importCollectionComponent, ImportException,
+ storeComponentInHomeAndCalendar
+)
from twext.enterprise.jobqueue import JobItem
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
@@ -145,6 +148,54 @@
"""
+DATA_OTHER_ORGANIZER_EVENT = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:6DB84FB1-C943-4144-BE65-9B0DD9A9E2C7
+DTSTART;TZID=America/Los_Angeles:20151008T053000
+DTEND;TZID=America/Los_Angeles:20151008T070000
+ATTENDEE;CN=User 01;CUTYPE=INDIVIDUAL:urn:x-uid:user01
+ATTENDEE;CN=User 02;CUTYPE=INDIVIDUAL;ROLE=CHAIR:urn:x-uid:user02
+ATTENDEE;CN=User 03;CUTYPE=INDIVIDUAL:urn:x-uid:user03
+ATTENDEE;CN=Mercury Seven;CUTYPE=ROOM:urn:x-uid:mercury
+CREATED:20141107T172645Z
+DTSTAMP:20141107T172645Z
+LOCATION:Mercury
+ORGANIZER;CN=User 02:urn:x-uid:user02
+SEQUENCE:0
+SUMMARY:Other organizer
+END:VEVENT
+END:VCALENDAR
+"""
+# TRANSP:OPAQUE
+
+DATA_ATTENDEE_EVENT = """BEGIN:VCALENDAR
+VERSION:2.0
+NAME:I'm an attendee
+COLOR:#0000FFFF
+SOURCE;VALUE=URI:http://example.com/calendars/__uids__/user01/calendar/
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:6DB84FB1-C943-4144-BE65-9B0DD9A9E2C7
+DTSTART;TZID=America/Los_Angeles:20151008T053000
+DTEND;TZID=America/Los_Angeles:20151008T070000
+ATTENDEE;CN=User 01;CUTYPE=INDIVIDUAL:urn:x-uid:user01
+ATTENDEE;CN=User 02;CUTYPE=INDIVIDUAL;ROLE=CHAIR:urn:x-uid:user02
+ATTENDEE;CN=User 03;CUTYPE=INDIVIDUAL:urn:x-uid:user03
+ATTENDEE;CN=Mercury Seven;CUTYPE=ROOM:urn:x-uid:mercury
+CREATED:20141107T172645Z
+DTSTAMP:20141107T172645Z
+LOCATION:Mercury
+ORGANIZER;CN=User 02:urn:x-uid:user02
+SEQUENCE:0
+SUMMARY:Other organizer
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+"""
+
+
class ImportTests(StoreTestCase):
"""
Tests for importing data to a live store.
@@ -277,3 +328,74 @@
self.assertEquals(len(objects), 1)
yield txn.commit()
+
+
+ @inlineCallbacks
+ def test_ImportComponentAttendee(self):
+
+ # Have another principal invite this principal
+
+ yield storeComponentInHomeAndCalendar(
+ self.store,
+ Component.allFromString(DATA_OTHER_ORGANIZER_EVENT),
+ "user02",
+ "calendar",
+ "invite.ics"
+ )
+
+ yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
+
+ # Delete the attendee's copy, thus declining the event
+ txn = self.store.newTransaction()
+ home = yield txn.calendarHomeWithUID("user01")
+ collection = yield home.childWithName("calendar")
+ objects = yield collection.objectResources()
+ self.assertEquals(len(objects), 1)
+ yield objects[0].remove()
+ yield txn.commit()
+ yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
+
+ # Make sure attendee's copy is gone
+ txn = self.store.newTransaction()
+ home = yield txn.calendarHomeWithUID("user01")
+ collection = yield home.childWithName("calendar")
+ objects = yield collection.objectResources()
+ self.assertEquals(len(objects), 0)
+ yield txn.commit()
+
+ # Make sure attendee shows as declined to the organizer
+ txn = self.store.newTransaction()
+ home = yield txn.calendarHomeWithUID("user02")
+ collection = yield home.childWithName("calendar")
+ objects = yield collection.objectResources()
+ self.assertEquals(len(objects), 1)
+ component = yield objects[0].component()
+ prop = component.getAttendeeProperty(("urn:x-uid:user01",))
+ self.assertEquals(
+ prop.parameterValue("PARTSTAT"),
+ "DECLINED"
+ )
+ yield txn.commit()
+
+ # When importing the event again, instead trigger a re-invite
+ # from the organizer
+ component = Component.allFromString(DATA_ATTENDEE_EVENT)
+ yield importCollectionComponent(self.store, component)
+
+ yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
+
+ # Make sure attendee now has a new invite
+ txn = self.store.newTransaction()
+ home = yield txn.calendarHomeWithUID("user01")
+ collection = yield home.childWithName("calendar")
+ objects = yield collection.objectResources()
+ self.assertEquals(len(objects), 1)
+ component = yield objects[0].component()
+ prop = component.getAttendeeProperty(("urn:x-uid:user01",))
+ self.assertEquals(
+ prop.parameterValue("PARTSTAT"),
+ "NEEDS-ACTION"
+ )
+ yield txn.commit()
+
+ test_ImportComponentAttendee.todo = "Debug"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20141110/4fa0e6bd/attachment.html>
More information about the calendarserver-changes
mailing list