[CalendarServer-changes] [11168] CalendarServer/branches/users/gaya/sharedgroups-3

source_changes at macosforge.org source_changes at macosforge.org
Fri May 10 16:18:19 PDT 2013


Revision: 11168
          http://trac.calendarserver.org//changeset/11168
Author:   gaya at apple.com
Date:     2013-05-10 16:18:19 -0700 (Fri, 10 May 2013)
Log Message:
-----------
merge from 11165 (with some tests failing)

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups-3/bin/caldavd
    CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/calverify.py
    CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/workitems.py
    CalendarServer/branches/users/gaya/sharedgroups-3/contrib/performance/httpauth.py
    CalendarServer/branches/users/gaya/sharedgroups-3/contrib/tools/readStats.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/peruserdata.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/test/test_peruserdata.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/resource.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/icaldiff.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/itip.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/test/test_itip.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/oracle-dialect/19.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/postgres-dialect/19.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py

Property Changed:
----------------
    CalendarServer/branches/users/gaya/sharedgroups-3/
    CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py


Property changes on: CalendarServer/branches/users/gaya/sharedgroups-3
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11090-11095,11097-11111,11115-11149
   + /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11090-11095,11097-11111,11115-11165

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/bin/caldavd
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/bin/caldavd	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/bin/caldavd	2013-05-10 23:18:19 UTC (rev 11168)
@@ -94,7 +94,6 @@
     echo "        -t Process type (Master, Slave or Combined)";
     echo "        -p Path to the desired pstats file.";
     echo "        -R The Twisted Reactor to run [${reactor}]";
-    echo "        -o Pass option through to server";
 
     if [ "${1-}" == "-" ]; then return 0; fi;
     exit 64;

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/push/applepush.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/push/applepush.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -368,13 +368,13 @@
 
         self.transport.write(
             struct.pack("!BIIH32sH%ds" % (payloadLength,),
-                self.COMMAND_ENHANCED,  # Command
-                identifier,             # Identifier
-                0,                      # Expiry
-                32,                     # Token Length
-                binaryToken,            # Token
-                payloadLength,          # Payload Length
-                payload,                # Payload in JSON format
+                self.COMMAND_ENHANCED,           # Command
+                identifier,                      # Identifier
+                int(time.time()) + 72 * 60 * 60, # Expires in 72 hours
+                32,                              # Token Length
+                binaryToken,                     # Token
+                payloadLength,                   # Payload Length
+                payload,                         # Payload in JSON format
             )
         )
 

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/calverify.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/calverify.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -1598,7 +1598,8 @@
 
             # Look at each attendee in the organizer's meeting
             for organizerAttendee, organizerViewOfStatus in organizerViewOfAttendees.iteritems():
-                broken = False
+                missing = False
+                mismatch = False
 
                 self.matched_attendee_to_organizer[uid].add(organizerAttendee)
 
@@ -1627,7 +1628,7 @@
                             if partstat not in ("DECLINED", "CANCELLED"):
                                 results_mismatch.append((uid, resid, organizer, org_created, org_modified, organizerAttendee, att_created, att_modified))
                                 self.results.setdefault("Mismatch Attendee", set()).add((uid, organizer, organizerAttendee,))
-                                broken = True
+                                mismatch = True
                                 if self.options["details"]:
                                     self.output.write("Mismatch: on Organizer's side:\n")
                                     self.output.write("          UID: %s\n" % (uid,))
@@ -1638,10 +1639,10 @@
                         # Check that the difference is only cancelled on the attendees side
                         for _attendeeInstance, partstat in attendeeOwnStatus.difference(organizerViewOfStatus):
                             if partstat not in ("CANCELLED",):
-                                if not broken:
+                                if not mismatch:
                                     results_mismatch.append((uid, resid, organizer, org_created, org_modified, organizerAttendee, att_created, att_modified))
                                     self.results.setdefault("Mismatch Attendee", set()).add((uid, organizer, organizerAttendee,))
-                                broken = True
+                                mismatch = True
                                 if self.options["details"]:
                                     self.output.write("Mismatch: on Attendee's side:\n")
                                     self.output.write("          Organizer: %s\n" % (organizer,))
@@ -1655,12 +1656,19 @@
                         if partstat not in ("DECLINED", "CANCELLED"):
                             results_missing.append((uid, resid, organizer, organizerAttendee, org_created, org_modified))
                             self.results.setdefault("Missing Attendee", set()).add((uid, organizer, organizerAttendee,))
-                            broken = True
+                            missing = True
                             break
 
                 # If there was a problem we can fix it
-                if broken and self.fix:
-                    yield self.fixByReinvitingAttendee(resid, attendeeResIDs.get((organizerAttendee, uid)), organizerAttendee)
+                if (missing or mismatch) and self.fix:
+                    fix_result = (yield self.fixByReinvitingAttendee(resid, attendeeResIDs.get((organizerAttendee, uid)), organizerAttendee))
+                    if fix_result:
+                        if missing:
+                            self.fixAttendeesForOrganizerMissing += 1
+                        else:
+                            self.fixAttendeesForOrganizerMismatch += 1
+                    else:
+                        self.fixFailed += 1
 
         yield self.txn.commit()
         self.txn = None
@@ -1803,7 +1811,11 @@
 
                 # If there is a mismatch we fix by re-inviting the attendee
                 if self.fix:
-                    yield self.fixByReinvitingAttendee(self.organized_byuid[uid][1], resid, attendee)
+                    fix_result = (yield self.fixByReinvitingAttendee(self.organized_byuid[uid][1], resid, attendee))
+                    if fix_result:
+                        self.fixOrganizersForAttendeeMismatch += 1
+                    else:
+                        self.fixFailed += 1
 
         yield self.txn.commit()
         self.txn = None

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/workitems.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/workitems.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/calendarserver/tools/workitems.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -28,7 +28,7 @@
 from twisted.application.service import Service
 from calendarserver.push.notifier import PushNotificationWork
 from twistedcaldav.directory.directory import GroupCacherPollingWork
-from twistedcaldav.scheduling.imip.inbound import IMIPPollingWork, IMIPReplyWork
+from txdav.caldav.datastore.scheduling.imip.inbound import IMIPPollingWork, IMIPReplyWork
 
 def usage(e=None):
 
@@ -84,6 +84,8 @@
 
     utilityMain(configFileName, WorkItemMonitorService, verbose=debug)
 
+
+
 class WorkItemMonitorService(Service):
 
     def __init__(self, store):
@@ -98,6 +100,7 @@
         self.updateScreenGeometry()
         self.reactor.callLater(0, self.updateDisplay)
 
+
     def updateScreenGeometry(self):
         for win in self.windows:
             del win
@@ -113,10 +116,10 @@
         # Specify row and column for each window as though it is a cell in an invisible html table
         # Itemize windows in ascending order by row, col
         for title, height, width, row, col, workItemClass, fmt, attrs in (
-            ("Group Membership Indexing",   "10%", "50%",  1, 1, GroupCacherPollingWork, "", ()),
-            ("IMIP Reply Polling",          "10%", "50%",  1, 2, IMIPPollingWork, "", ()),
-            ("IMIP Reply Processing",       "20%", "100%", 2, 1, IMIPReplyWork, "%s %s", ("organizer", "attendee")),
-            ("Push Notifications",          "69%", "100%", 3, 1, PushNotificationWork, "%s", ("pushID",)),
+            ("Group Membership Indexing", "10%", "50%", 1, 1, GroupCacherPollingWork, "", ()),
+            ("IMIP Reply Polling", "10%", "50%", 1, 2, IMIPPollingWork, "", ()),
+            ("IMIP Reply Processing", "20%", "100%", 2, 1, IMIPReplyWork, "%s %s", ("organizer", "attendee")),
+            ("Push Notifications", "69%", "100%", 3, 1, PushNotificationWork, "%s", ("pushID",)),
         ):
             if (isinstance(height, basestring)):
                 height = max(int(winY * (float(height.strip("%")) / 100.0)), 3)
@@ -144,6 +147,8 @@
 
         self.reactor.callLater(1, self.updateDisplay)
 
+
+
 class WorkWindow(object):
     def __init__(self, nlines, ncols, begin_y, begin_x,
         store, title, workItemClass, fmt, attrs):
@@ -155,6 +160,7 @@
         self.fmt = fmt
         self.attrs = attrs
 
+
     @inlineCallbacks
     def update(self):
         self.window.erase()
@@ -178,7 +184,7 @@
                 except Exception, e:
                     s = "Error: %s" % (str(e),)
                 try:
-                    self.window.addnstr(y, x, s, self.ncols-2)
+                    self.window.addnstr(y, x, s, self.ncols - 2)
                 except curses.error:
                     pass
                 y += 1

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/contrib/performance/httpauth.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/contrib/performance/httpauth.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/contrib/performance/httpauth.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -104,7 +104,12 @@
 
 
     def _parse(self, authorization):
-        scheme, rest = authorization.split(None, 1)
+        try:
+            scheme, rest = authorization.split(None, 1)
+        except ValueError:
+            # Probably "negotiate", which we don't support
+            scheme = authorization
+            rest = ""
         args = urllib2.parse_keqv_list(urllib2.parse_http_list(rest))
         challengeType = {
             'basic': BasicChallenge,

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/contrib/tools/readStats.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/contrib/tools/readStats.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/contrib/tools/readStats.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -303,15 +303,15 @@
     for i in ("T", "T-RESP-WR",):
         table.addRow((
             "Overall Response" if i == "T" else "Response Write",
-            (stat[i]["<10ms"], safeDivision(stat[i]["<10ms"], stat["requests"], 100.0)),
-            (stat[i]["10ms<->100ms"], safeDivision(stat[i]["10ms<->100ms"], stat["requests"], 100.0)),
-            (stat[i]["100ms<->1s"], safeDivision(stat[i]["100ms<->1s"], stat["requests"], 100.0)),
-            (stat[i]["1s<->10s"], safeDivision(stat[i]["1s<->10s"], stat["requests"], 100.0)),
-            (stat[i]["10s<->30s"], safeDivision(stat[i]["10s<->30s"], stat["requests"], 100.0)),
-            (stat[i]["30s<->60s"], safeDivision(stat[i]["30s<->60s"], stat["requests"], 100.0)),
-            (stat[i][">60s"], safeDivision(stat[i][">60s"], stat["requests"], 100.0)),
-            safeDivision(stat[i]["Over 1s"], stat["requests"], 100.0),
-            safeDivision(stat[i]["Over 10s"], stat["requests"], 100.0),
+            (stat[i]["<10ms"], safeDivision(stat[i]["<10ms"], stat[i]["requests"], 100.0)),
+            (stat[i]["10ms<->100ms"], safeDivision(stat[i]["10ms<->100ms"], stat[i]["requests"], 100.0)),
+            (stat[i]["100ms<->1s"], safeDivision(stat[i]["100ms<->1s"], stat[i]["requests"], 100.0)),
+            (stat[i]["1s<->10s"], safeDivision(stat[i]["1s<->10s"], stat[i]["requests"], 100.0)),
+            (stat[i]["10s<->30s"], safeDivision(stat[i]["10s<->30s"], stat[i]["requests"], 100.0)),
+            (stat[i]["30s<->60s"], safeDivision(stat[i]["30s<->60s"], stat[i]["requests"], 100.0)),
+            (stat[i][">60s"], safeDivision(stat[i][">60s"], stat[i]["requests"], 100.0)),
+            safeDivision(stat[i]["Over 1s"], stat[i]["requests"], 100.0),
+            safeDivision(stat[i]["Over 10s"], stat[i]["requests"], 100.0),
         ))
     os = StringIO()
     table.printTable(os=os)
@@ -389,8 +389,9 @@
     for stat in stats:
         for method in stat[index]["method"]:
             methods[method] += stat[index]["method"][method]
-        for method_time in stat[index]["method-t"]:
-            method_times[method_time] += stat[index]["method-t"][method_time]
+        if "method-t" in stat[index]:
+            for method_time in stat[index]["method-t"]:
+                method_times[method_time] += stat[index]["method-t"][method_time]
 
     printMethodCounts({"method": methods, "method-t": method_times})
 

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/peruserdata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/peruserdata.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/peruserdata.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -40,7 +40,7 @@
 for each instance overridden by the per-user data. These per-user overridden components may not correspond to an
 actual overridden component. In that situation the server has to re-construct the per-user data appropriately:
 
-e.g., 
+e.g.,
 
 1. VEVENT contains an overridden instance, but X-CALENDARSERVER-PERUSER does not - server uses the must instance
 X-CALENDARSERVER-PERUSER data (if any) for the overridden instance.
@@ -59,23 +59,24 @@
     """
 
     # If any of these change also update usage in ical.py
-    PERUSER_COMPONENT     = "X-CALENDARSERVER-PERUSER"
-    PERUSER_UID           = "X-CALENDARSERVER-PERUSER-UID"
+    PERUSER_COMPONENT = "X-CALENDARSERVER-PERUSER"
+    PERUSER_UID = "X-CALENDARSERVER-PERUSER-UID"
     PERINSTANCE_COMPONENT = "X-CALENDARSERVER-PERINSTANCE"
 
-    PERUSER_PROPERTIES    = ("TRANSP",)
+    PERUSER_PROPERTIES = ("TRANSP",)
     PERUSER_SUBCOMPONENTS = ("VALARM",)
-    IGNORE_X_PROPERTIES   = ("X-CALENDARSERVER-HIDDEN-INSTANCE",)
+    IGNORE_X_PROPERTIES = ("X-CALENDARSERVER-HIDDEN-INSTANCE",)
 
     def __init__(self, uid):
         """
-        
-        @param uid: unique identifier of the user for whom the data is being filtered 
+
+        @param uid: unique identifier of the user for whom the data is being filtered
         @type uid: C{str}
         """
-        
+
         self.uid = uid
-    
+
+
     def filter(self, ical):
         """
         Filter the supplied iCalendar object using the request information.
@@ -83,10 +84,10 @@
 
         @param ical: iCalendar object - this will be modified and returned
         @type ical: L{Component} or C{str}
-        
+
         @return: L{Component} for the filtered calendar data
         """
-        
+
         # Make sure input is valid
         ical = self.validCalendar(ical)
 
@@ -94,7 +95,7 @@
         peruser_component = None
         for component in tuple(ical.subcomponents()):
             if component.name() == PerUserDataFilter.PERUSER_COMPONENT:
-                
+
                 # Check user id - remove if not matches
                 if component.propertyValue(PerUserDataFilter.PERUSER_UID) != self.uid:
                     ical.removeComponent(component)
@@ -110,6 +111,7 @@
 
         return ical
 
+
     def merge(self, icalnew, icalold):
         """
         Merge the new data with the old taking per-user information into account.
@@ -118,13 +120,13 @@
         @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
         """
 
         # Make sure input is valid
         icalnew = self.validCalendar(icalnew)
-        
+
         # There cannot be any X-CALENDARSERVER-PERUSER components in the new data
         for component in tuple(icalnew.subcomponents()):
             if component.name() == PerUserDataFilter.PERUSER_COMPONENT:
@@ -134,13 +136,14 @@
         self._splitPerUserData(icalnew)
         if icalold is None:
             return icalnew
-        
+
         # Make sure input is valid
         icalold = self.validCalendar(icalold)
 
         self._mergeRepresentations(icalnew, icalold)
         return icalnew
 
+
     def _mergeBack(self, ical, peruser):
         """
         Merge the per-user data back into the main calendar data.
@@ -150,22 +153,22 @@
         @param peruser: the per-user data to merge in
         @type peruser: L{Component}
         """
-        
+
         # Iterate over each instance in the per-user data and build mapping
         peruser_recurrence_map = {}
         for subcomponent in peruser.subcomponents():
             if subcomponent.name() != PerUserDataFilter.PERINSTANCE_COMPONENT:
                 raise AssertionError("Wrong sub-component '%s' in a X-CALENDARSERVER-PERUSER component" % (subcomponent.name(),))
             peruser_recurrence_map[subcomponent.getRecurrenceIDUTC()] = subcomponent
-            
+
         ical_recurrence_set = set(ical.getComponentInstances())
         peruser_recurrence_set = set(peruser_recurrence_map.keys())
-        
+
         # Set operations to find union and differences
         union_set = ical_recurrence_set.intersection(peruser_recurrence_set)
         ical_only_set = ical_recurrence_set.difference(peruser_recurrence_set)
         peruser_only_set = peruser_recurrence_set.difference(ical_recurrence_set)
-        
+
         # For ones in per-user data but no main data, we synthesize an instance and copy over per-user data
         # NB We have to do this before we do any merge that may change the master
         if ical.masterComponent() is not None:
@@ -175,8 +178,9 @@
                 self._mergeBackComponent(ical_component, peruser_component)
                 ical.addComponent(ical_component)
         elif peruser_only_set:
-            raise AssertionError("Cannot derive a per-user instance when there is no master component.")
-                    
+            # We used to error out here, but instead we should silently ignore this error and keep going
+            pass
+
         # Process the unions by merging in per-user data
         for rid in union_set:
             ical_component = ical.overriddenComponent(rid)
@@ -190,7 +194,8 @@
                 for rid in ical_only_set:
                     ical_component = ical.overriddenComponent(rid)
                     self._mergeBackComponent(ical_component, peruser_master)
-                    
+
+
     def _mergeBackComponent(self, ical, peruser):
         """
         Copy all properties and sub-components from per-user data into the main component
@@ -199,17 +204,18 @@
         @param peruser:
         @type peruser:
         """
-        
+
         # Each sub-component
         for subcomponent in peruser.subcomponents():
             ical.addComponent(subcomponent)
-        
+
         # Each property except RECURRENCE-ID
         for property in peruser.properties():
             if property.name() == "RECURRENCE-ID":
                 continue
             ical.addProperty(property)
 
+
     def _splitPerUserData(self, ical):
         """
         Split the per-user data out of the "normal" iCalendar components into separate per-user
@@ -219,13 +225,13 @@
         @param ical: calendar data to process
         @type ical: L{Component}
         """
-        
+
         def init_peruser_component():
             peruser = Component(PerUserDataFilter.PERUSER_COMPONENT)
             peruser.addProperty(Property("UID", ical.resourceUID()))
             peruser.addProperty(Property(PerUserDataFilter.PERUSER_UID, self.uid))
             return peruser
-        
+
         components = tuple(ical.subcomponents())
         peruser_component = init_peruser_component() if self.uid else None
         perinstance_components = {}
@@ -245,7 +251,7 @@
                         perinstance_component.addProperty(property)
                     component.removeProperty(property)
                     perinstance_id_different = True
-            
+
             # Transfer per-user components from main component to per-instance component
             for subcomponent in tuple(component.subcomponents()):
                 if subcomponent.name() in PerUserDataFilter.PERUSER_SUBCOMPONENTS or subcomponent.name().startswith("X-"):
@@ -253,10 +259,10 @@
                         perinstance_component.addComponent(subcomponent)
                     component.removeComponent(subcomponent)
                     perinstance_id_different = True
-            
+
             if perinstance_id_different and perinstance_component:
                 perinstance_components[rid] = perinstance_component
-            
+
         if self.uid:
             # Add unique per-instance components into the per-user component
             peruser_component_different = False
@@ -271,12 +277,13 @@
                     perinstance.addProperty(Property("RECURRENCE-ID", rid))
                     peruser_component.addComponent(perinstance)
                     peruser_component_different = True
-            
+
             if peruser_component_different:
                 ical.addComponent(peruser_component)
 
             self._compactInstances(ical)
 
+
     def _compactInstances(self, ical):
         """
         Remove recurrences instances that are the same as their master-derived counterparts. This gives the most
@@ -303,17 +310,19 @@
             if derived and derived == subcomponent:
                 ical.removeComponent(subcomponent)
 
+
     def _mergeRepresentations(self, icalnew, icalold):
-        
+
         # Test for simple case first
         if icalnew.isRecurring() and icalold.isRecurring():
-            # Test each instance from old data to see whether it is still valid in the new one 
+            # Test each instance from old data to see whether it is still valid in the new one
             self._complexMerge(icalnew, icalold)
         else:
             self._simpleMerge(icalnew, icalold)
-    
+
+
     def _simpleMerge(self, icalnew, icalold):
-        
+
         # Take all per-user components from old and add to new, except for our user
         new_recur = icalnew.isRecurring()
         old_recur = icalold.isRecurring()
@@ -322,7 +331,7 @@
             if component.name() == PerUserDataFilter.PERUSER_COMPONENT:
                 if component.propertyValue(PerUserDataFilter.PERUSER_UID) != self.uid and not new_recur_has_no_master:
                     newcomponent = component.duplicate()
-                    
+
                     # Only transfer the master components from the old data to the new when the old
                     # was recurring and the new is not recurring
                     if not new_recur and old_recur:
@@ -332,15 +341,16 @@
 
                     if len(tuple(newcomponent.subcomponents())):
                         icalnew.addComponent(newcomponent)
-    
+
+
     def _complexMerge(self, icalnew, icalold):
-        
+
         # Take all per-user components from old and add to new, except for our user
         for component in icalold.subcomponents():
             if component.name() == PerUserDataFilter.PERUSER_COMPONENT:
                 if component.propertyValue(PerUserDataFilter.PERUSER_UID) != self.uid:
                     newcomponent = component.duplicate()
-                    
+
                     # See which of the instances are still valid
                     old_rids = dict([(subcomponent.getRecurrenceIDUTC(), subcomponent,) for subcomponent in newcomponent.subcomponents()])
                     valid_rids = icalnew.validInstances(old_rids.keys())

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/test/test_peruserdata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/test/test_peruserdata.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/datafilters/test/test_peruserdata.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -122,7 +122,7 @@
 class PerUserDataFilterTestNotRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -137,14 +137,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), data)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), data)
 
+
     def test_public_oneuser(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -205,7 +206,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -238,7 +239,7 @@
 class PerUserDataFilterTestRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -264,14 +265,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), data)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), data)
 
+
     def test_public_oneuser_master(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -371,7 +373,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -379,8 +381,9 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
+
     def test_public_oneuser_master_and_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -489,7 +492,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -497,8 +500,9 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
+
     def test_public_oneuser_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -593,7 +597,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -601,8 +605,9 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
+
     def test_public_oneuser_master_derived_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -691,7 +696,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -699,8 +704,9 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
+
     def test_public_oneuser_master_derived_override_x2(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -847,7 +853,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -855,8 +861,9 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result03)
 
+
     def test_public_oneuser_no_master_and_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -921,7 +928,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
@@ -929,22 +936,44 @@
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
-class PerUserDataMergeTestNewNotRecurring (twistedcaldav.test.util.TestCase):
 
-    def test_public_noperuser(self):
-        
+    def test_public_oneuser_no_master_and_override_bogus_peruser(self):
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
 BEGIN:VEVENT
 UID:12345-67890
-DTSTART:20080601T120000Z
-DTEND:20080601T130000Z
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
 ATTENDEE:mailto:user1 at example.com
 ATTENDEE:mailto:user2 at example.com
 DTSTAMP:20080601T120000Z
 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
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+RECURRENCE-ID:20080603T120000Z
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:Test-override
+TRIGGER;RELATED=START:-PT10M
+END:VALARM
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
         result01 = """BEGIN:VCALENDAR
@@ -952,23 +981,48 @@
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
 BEGIN:VEVENT
 UID:12345-67890
-DTSTART:20080601T120000Z
-DTEND:20080601T130000Z
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
 ATTENDEE:mailto:user1 at example.com
 ATTENDEE:mailto:user2 at example.com
 DTSTAMP:20080601T120000Z
 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")
-        
+        result02 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+DTSTAMP:20080601T120000Z
+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)), result01)
+            self.assertEqual(str(PerUserDataFilter("user01").filter(item)), result01)
         for item in (data, Component.fromString(data),):
-            self.assertEqual(str(PerUserDataFilter("").merge(item, None)), data)
+            self.assertEqual(str(PerUserDataFilter("user02").filter(item)), result02)
+        for item in (data, Component.fromString(data),):
+            self.assertEqual(str(PerUserDataFilter("").filter(item)), result02)
 
+
     def test_public_oneuser(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1029,14 +1083,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
     def test_prevent_injection(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1057,7 +1112,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             filter = PerUserDataFilter("user01")
             self.assertRaises(ValueError, filter.merge, item, None)
@@ -1065,10 +1120,12 @@
             filter = PerUserDataFilter("")
             self.assertRaises(ValueError, filter.merge, item, None)
 
+
+
 class PerUserDataMergeTestNewRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1119,14 +1176,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), data)
 
+
     def test_public_oneuser_master(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1226,14 +1284,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
     def test_public_oneuser_master_and_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1342,14 +1401,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
     def test_public_oneuser_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1444,14 +1504,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
     def test_public_oneuser_master_compact_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1550,14 +1611,15 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
     def test_public_oneuser_master_noncompact_override(self):
-        
+
         data = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1666,16 +1728,18 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("user01").merge(item, None)), result01)
         for item in (data, Component.fromString(data),):
             self.assertEqual(str(PerUserDataFilter("").merge(item, None)), result02)
 
+
+
 class PerUserDataMergeTestExistingNotRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1718,13 +1782,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1797,13 +1862,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1900,13 +1966,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -1985,15 +2052,17 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestExistingNowRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2038,13 +2107,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_noperuser_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2109,13 +2179,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_noperuser_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2160,13 +2231,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2241,13 +2313,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_oneuser_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2357,13 +2430,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_oneuser_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2441,13 +2515,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2546,13 +2621,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2686,13 +2762,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2780,13 +2857,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2867,13 +2945,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -2974,14 +3053,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
 
     def test_public_twousers_removal_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3050,15 +3129,17 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestExistingWasRecurring (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3104,13 +3185,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_noperuser_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3166,13 +3248,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_noperuser_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3216,13 +3299,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3296,13 +3380,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_oneuser_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3386,13 +3471,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_oneuser_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3467,13 +3553,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3571,13 +3658,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3703,13 +3791,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3797,13 +3886,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal_master(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3884,13 +3974,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal_master_with_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -3991,14 +4082,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
 
     def test_public_twousers_removal_only_override(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4068,15 +4159,17 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestBothRecurringMasterOnly (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4122,13 +4215,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4204,13 +4298,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4310,13 +4405,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4398,13 +4494,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_invalid_instance(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4495,15 +4592,17 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestBothRecurringMasterWithOverride (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4579,13 +4678,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4715,13 +4815,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -4884,13 +4985,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5020,15 +5122,17 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestBothRecurringOverrideOnly (twistedcaldav.test.util.TestCase):
 
     def test_public_noperuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5074,13 +5178,14 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), newresult)
 
+
     def test_public_oneuser(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5158,13 +5263,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5255,13 +5361,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_removal(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5333,15 +5440,17 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
+
 class PerUserDataMergeTestBothRecurringSpecialCase (twistedcaldav.test.util.TestCase):
 
     def test_public_twousers_recurrence_truncation(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5468,13 +5577,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_recurrence_shift(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5592,13 +5702,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_rdate_removed(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5708,13 +5819,14 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
+
     def test_public_twousers_exdate_added(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5825,16 +5937,17 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         for olditem in (olddata, Component.fromString(olddata),):
             for newitem in (newdata, Component.fromString(newdata),):
                 self.assertEqual(str(PerUserDataFilter("user01").merge(newitem, olditem)), result01)
 
 
+
 class PerUserDataMergeTestCompact (twistedcaldav.test.util.TestCase):
 
     def test_merge_vevent_compact(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5908,7 +6021,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         filtered = PerUserDataFilter("user01").merge(newdata, None)
         self.assertEqual(str(filtered), result)
         unfiltered = PerUserDataFilter("user01").filter(filtered)
@@ -5916,7 +6029,7 @@
 
 
     def test_merge_vevent_all_day_compact(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -5990,7 +6103,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         filtered = PerUserDataFilter("user01").merge(newdata, None)
         self.assertEqual(str(filtered), result)
         unfiltered = PerUserDataFilter("user01").filter(filtered)
@@ -5998,7 +6111,7 @@
 
 
     def test_merge_peruser_compact(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -6073,7 +6186,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         filtered = PerUserDataFilter("user01").merge(newdata, None)
         self.assertEqual(str(filtered), result)
         unfiltered = PerUserDataFilter("user01").filter(filtered)
@@ -6081,7 +6194,7 @@
 
 
     def test_merge_peruser_all_day_compact(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -6158,7 +6271,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         filtered = PerUserDataFilter("user01").merge(newdata, None)
         self.assertEqual(str(filtered), result)
         unfiltered = PerUserDataFilter("user01").filter(filtered)
@@ -6166,7 +6279,7 @@
 
 
     def test_merge_both_compact(self):
-        
+
         newdata = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -6231,7 +6344,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         unfiltered_result = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -6253,7 +6366,7 @@
 END:VEVENT
 END:VCALENDAR
 """.replace("\n", "\r\n")
-        
+
         filtered = PerUserDataFilter("user01").merge(newdata, None)
         self.assertEqual(str(filtered), result)
         unfiltered = PerUserDataFilter("user01").filter(filtered)

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/resource.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/resource.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -530,21 +530,6 @@
         returnValue(res)
 
 
-    def _hasSharedProperty(self, qname, request):
-
-        # Always have default alarms on shared calendars
-        if qname in (
-            caldavxml.DefaultAlarmVEventDateTime.qname(),
-            caldavxml.DefaultAlarmVEventDate.qname(),
-            caldavxml.DefaultAlarmVToDoDateTime.qname(),
-            caldavxml.DefaultAlarmVToDoDate.qname(),
-        ) and self.isCalendarCollection():
-            return True
-
-        p = self.deadProperties().contains(qname)
-        return p
-
-
     def _hasGlobalProperty(self, property, request):
         """
         Need to special case schedule-calendar-transp for backwards compatability.
@@ -713,6 +698,8 @@
             "%r is not a WebDAVElement instance" % (property,)
         )
 
+        self._preProcessWriteProperty(property, request)
+
         res = (yield self._writeGlobalProperty(property, request))
         returnValue(res)
 
@@ -779,8 +766,6 @@
     @inlineCallbacks
     def _writeGlobalProperty(self, property, request):
 
-        self._preProcessWriteProperty(property, request)
-
         if property.qname() == caldavxml.ScheduleCalendarTransp.qname():
             yield self._newStoreObject.setUsedForFreeBusy(property == caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
             returnValue(None)
@@ -1955,35 +1940,70 @@
     the default alarm properties in a more useful way that using readProperty.
     In particular it will handle inheritance of the property from the home if a
     calendar does not explicitly have the property.
+
+    Important: we need to distinguish between the property not being present, or
+    present but empty, however the store by default is unable to distinguish between
+    None and and empty C{str}. So what we do is use the value "empty" to represent
+    a present but empty property.
     """
 
-    def getDefaultAlarm(self, vevent, timed):
+    ALARM_PROPERTIES = {
+        caldavxml.DefaultAlarmVEventDateTime.qname(): (True, True,),
+        caldavxml.DefaultAlarmVEventDate.qname(): (True, False,),
+        caldavxml.DefaultAlarmVToDoDateTime.qname(): (False, True,),
+        caldavxml.DefaultAlarmVToDoDate.qname(): (False, False,),
+    }
 
-        if vevent:
-            propname = caldavxml.DefaultAlarmVEventDateTime if timed else caldavxml.DefaultAlarmVEventDate
-        else:
-            propname = caldavxml.DefaultAlarmVToDoDateTime if timed else caldavxml.DefaultAlarmVToDoDate
+    ALARM_PROPERTY_CLASSES = {
+        caldavxml.DefaultAlarmVEventDateTime.qname(): caldavxml.DefaultAlarmVEventDateTime,
+        caldavxml.DefaultAlarmVEventDate.qname(): caldavxml.DefaultAlarmVEventDate,
+        caldavxml.DefaultAlarmVToDoDateTime.qname(): caldavxml.DefaultAlarmVToDoDateTime,
+        caldavxml.DefaultAlarmVToDoDate.qname(): caldavxml.DefaultAlarmVToDoDate,
+    }
 
+    def getDefaultAlarmProperty(self, propname):
+
+        vevent, timed = DefaultAlarmPropertyMixin.ALARM_PROPERTIES[propname]
+
         if self.isCalendarCollection():
 
             # Get from calendar or inherit from home
-            try:
-                prop = self.deadProperties().get(propname.qname())
-            except HTTPError:
-                prop = None
-            if prop is None:
-                prop = self.parentResource().getDefaultAlarm(vevent, timed)
+            alarm = self._newStoreObject.getDefaultAlarm(vevent, timed)
+            if alarm is None:
+                return self.parentResource().getDefaultAlarmProperty(propname)
+            elif alarm == "empty":
+                return DefaultAlarmPropertyMixin.ALARM_PROPERTY_CLASSES[propname]()
         else:
             # Just return whatever is on the home
-            try:
-                prop = self.deadProperties().get(propname.qname())
-            except HTTPError:
-                prop = None
+            alarm = self._newStoreHome.getDefaultAlarm(vevent, timed)
 
-        return str(prop) if prop is not None else None
+        return DefaultAlarmPropertyMixin.ALARM_PROPERTY_CLASSES[propname](alarm) if alarm else None
 
 
+    @inlineCallbacks
+    def setDefaultAlarmProperty(self, prop):
 
+        vevent, timed = DefaultAlarmPropertyMixin.ALARM_PROPERTIES[prop.qname()]
+        alarm = str(prop)
+
+        if self.isCalendarCollection():
+            yield self._newStoreObject.setDefaultAlarm(alarm if alarm else "empty", vevent, timed)
+        else:
+            yield self._newStoreHome.setDefaultAlarm(alarm if alarm else "empty", vevent, timed)
+
+
+    @inlineCallbacks
+    def removeDefaultAlarmProperty(self, propname):
+
+        vevent, timed = DefaultAlarmPropertyMixin.ALARM_PROPERTIES[propname]
+
+        if self.isCalendarCollection():
+            yield self._newStoreObject.setDefaultAlarm(None, vevent, timed)
+        else:
+            yield self._newStoreHome.setDefaultAlarm(None, vevent, timed)
+
+
+
 class CommonHomeResource(PropfindCacheMixin, SharedHomeMixin, CalDAVResource):
     """
     Logic common to Calendar and Addressbook home resources.
@@ -2409,6 +2429,24 @@
         return existing
 
 
+    def _hasGlobalProperty(self, property, request):
+        """
+        Need to special case schedule-calendar-transp for backwards compatability.
+        """
+
+        if type(property) is tuple:
+            qname = property
+        else:
+            qname = property.qname()
+
+        # Force calendar collections to always appear to have the property
+        if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            return succeed(self.getDefaultAlarmProperty(qname) is not None)
+
+        else:
+            return super(CalendarHomeResource, self)._hasGlobalProperty(property, request)
+
+
     @inlineCallbacks
     def readProperty(self, property, request):
         if type(property) is tuple:
@@ -2442,10 +2480,39 @@
             else:
                 returnValue(None)
 
+        elif qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            returnValue(self.getDefaultAlarmProperty(qname))
+
         result = (yield super(CalendarHomeResource, self).readProperty(property, request))
         returnValue(result)
 
 
+    @inlineCallbacks
+    def _writeGlobalProperty(self, property, request):
+
+        if property.qname() in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            yield self.setDefaultAlarmProperty(property)
+            returnValue(None)
+
+        result = (yield super(CalendarHomeResource, self)._writeGlobalProperty(property, request))
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def removeProperty(self, property, request):
+        if type(property) is tuple:
+            qname = property
+        else:
+            qname = property.qname()
+
+        if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            result = (yield self.removeDefaultAlarmProperty(qname))
+            returnValue(result)
+
+        result = (yield super(CalendarHomeResource, self).removeProperty(property, request))
+        returnValue(result)
+
+
     def _setupProvisions(self):
 
         # Cache children which must be of a specific type

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/sharing.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/sharing.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -573,7 +573,7 @@
             returnValue([])
 
         #TODO: Cache
-        if True:#not hasattr(self, "_invitations"):
+        if True:  #not hasattr(self, "_invitations"):
 
             acceptedHomeChildren = yield self._newStoreObject.asShared()
             # remove direct shares (it might be OK not to remove these, but that would be different from legacy code)
@@ -1221,11 +1221,11 @@
                         yield shareeCalender.writeProperty(customxml.CalendarColor.fromString(color), request)
 
                 # Calendars always start out transparent and with empty default alarms
-                yield shareeCalender.writeProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Transparent()), request)
-                yield shareeCalender.writeProperty(caldavxml.DefaultAlarmVEventDateTime.fromString(""), request)
-                yield shareeCalender.writeProperty(caldavxml.DefaultAlarmVEventDate.fromString(""), request)
-                yield shareeCalender.writeProperty(caldavxml.DefaultAlarmVToDoDateTime.fromString(""), request)
-                yield shareeCalender.writeProperty(caldavxml.DefaultAlarmVToDoDate.fromString(""), request)
+                yield shareeCalender._newStoreObject.setUsedForFreeBusy(False)
+                yield shareeCalender._newStoreObject.setDefaultAlarm("empty", True, True)
+                yield shareeCalender._newStoreObject.setDefaultAlarm("empty", True, False)
+                yield shareeCalender._newStoreObject.setDefaultAlarm("empty", False, True)
+                yield shareeCalender._newStoreObject.setDefaultAlarm("empty", False, False)
 
         elif sharedResource.isAddressBookCollection():
             shareeHomeResource = yield sharee.addressBookHome(request)
@@ -1292,15 +1292,6 @@
         shared = (yield request.locateResource(shareURL))
         displayname = shared.displayName()
 
-        #FIXME: Remove! Probably obsolete
-        if self.isCalendarCollection():
-            # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
-            principal = (yield self.resourceOwnerPrincipal(request))
-            inboxURL = principal.scheduleInboxURL()
-            if inboxURL:
-                inbox = (yield request.locateResource(inboxURL))
-                inbox.processFreeBusyCalendar(shareURL, False)
-
         if share.direct():
             yield share._ownerStoreObject.unshareWith(share._shareeStoreObject.viewerHome())
         else:

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/stdconfig.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/stdconfig.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -644,6 +644,10 @@
                 "X-APPLE-TRAVEL-RETURN-DURATION",
                 "X-APPLE-TRAVEL-RETURN",
             ],
+            "OrganizerPublicProperties"  : [     # Names of X- iCalendar properties that are sent from ORGANIZER to ATTENDEE
+                "X-APPLE-DROPBOX",
+                "X-APPLE-STRUCTURED-LOCATION",
+            ],
         },
 
         "iSchedule": {

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -1216,7 +1216,65 @@
         return caldavxml.CalendarData
 
 
+    def _hasGlobalProperty(self, property, request):
+        """
+        Need to special case schedule-calendar-transp for backwards compatability.
+        """
+
+        if type(property) is tuple:
+            qname = property
+        else:
+            qname = property.qname()
+
+        # Force calendar collections to always appear to have the property
+        if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            return succeed(self.getDefaultAlarmProperty(qname) is not None)
+
+        else:
+            return super(CalendarCollectionResource, self)._hasGlobalProperty(property, request)
+
+
     @inlineCallbacks
+    def readProperty(self, property, request):
+        if type(property) is tuple:
+            qname = property
+        else:
+            qname = property.qname()
+
+        if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            returnValue(self.getDefaultAlarmProperty(qname))
+
+        result = (yield super(CalendarCollectionResource, self).readProperty(property, request))
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def _writeGlobalProperty(self, property, request):
+
+        if property.qname() in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            yield self.setDefaultAlarmProperty(property)
+            returnValue(None)
+
+        result = (yield super(CalendarCollectionResource, self)._writeGlobalProperty(property, request))
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def removeProperty(self, property, request):
+        if type(property) is tuple:
+            qname = property
+        else:
+            qname = property.qname()
+
+        if qname in DefaultAlarmPropertyMixin.ALARM_PROPERTIES:
+            result = (yield self.removeDefaultAlarmProperty(qname))
+            returnValue(result)
+
+        result = (yield super(CalendarCollectionResource, self).removeProperty(property, request))
+        returnValue(result)
+
+
+    @inlineCallbacks
     def storeResourceData(self, newchild, component, returnChangedData=False):
 
         yield newchild.storeComponent(component)

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/icaldiff.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/icaldiff.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -73,9 +73,7 @@
                 "DTSTAMP",
                 "LAST-MODIFIED",
             ))
-            calendar.removeXProperties(keep_properties=(
-                "X-APPLE-DROPBOX",
-            ))
+            calendar.removeXProperties(keep_properties=config.Scheduling.CalDAV.OrganizerPublicProperties)
             calendar.removePropertyParameters("ATTENDEE", ("RSVP", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
             calendar.normalizeAll()
             return calendar

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/itip.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/itip.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -864,7 +864,7 @@
         # Component properties - remove all X- except for those specified
         if not reply:
             # Organizer properties that need to go to the Attendees
-            keep_properties = ("X-APPLE-DROPBOX",)
+            keep_properties = config.Scheduling.CalDAV.OrganizerPublicProperties
         else:
             # Attendee properties that need to go to the Organizer
             keep_properties = ("X-CALENDARSERVER-PRIVATE-COMMENT",)

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/test/test_itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/test/test_itip.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/scheduling/test/test_itip.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -20,12 +20,14 @@
 
 from twisted.trial import unittest
 
+from twistedcaldav.stdconfig import config
 from twistedcaldav.ical import Component
 
 from txdav.caldav.datastore.scheduling.itip import iTipProcessing, iTipGenerator
 
 import os
 
+hasattr(config, "Scheduling")   # Quell pyflakes
 
 class iTIPProcessing (unittest.TestCase):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/sql.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/sql.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -346,6 +346,10 @@
         return (
             cls._homeMetaDataSchema.DEFAULT_EVENTS,
             cls._homeMetaDataSchema.DEFAULT_TASKS,
+            cls._homeMetaDataSchema.ALARM_VEVENT_TIMED,
+            cls._homeMetaDataSchema.ALARM_VEVENT_ALLDAY,
+            cls._homeMetaDataSchema.ALARM_VTODO_TIMED,
+            cls._homeMetaDataSchema.ALARM_VTODO_ALLDAY,
             cls._homeMetaDataSchema.CREATED,
             cls._homeMetaDataSchema.MODIFIED,
         )
@@ -364,6 +368,10 @@
         return (
             "_default_events",
             "_default_tasks",
+            "_alarm_vevent_timed",
+            "_alarm_vevent_allday",
+            "_alarm_vtodo_timed",
+            "_alarm_vtodo_allday",
             "_created",
             "_modified",
         )
@@ -772,6 +780,12 @@
         # Not allowed to delete the default calendar
         return calendar._resourceID in (self._default_events, self._default_tasks)
 
+    ALARM_DETAILS = {
+        (True, True): (_homeMetaDataSchema.ALARM_VEVENT_TIMED, "_alarm_vevent_timed"),
+        (True, False): (_homeMetaDataSchema.ALARM_VEVENT_ALLDAY, "_alarm_vevent_allday"),
+        (False, True): (_homeMetaDataSchema.ALARM_VTODO_TIMED, "_alarm_vtodo_timed"),
+        (False, False): (_homeMetaDataSchema.ALARM_VTODO_ALLDAY, "_alarm_vtodo_allday"),
+    }
 
     def getDefaultAlarm(self, vevent, timed):
         """
@@ -781,20 +795,14 @@
         @type vevent: C{bool}
         @param timed: timed ({C{True}) or all-day ({C{False})
         @type timed: C{bool}
+
         @return: the alarm (text)
         @rtype: C{str}
         """
 
-        if vevent:
-            propname = caldavxml.DefaultAlarmVEventDateTime if timed else caldavxml.DefaultAlarmVEventDate
-        else:
-            propname = caldavxml.DefaultAlarmVToDoDateTime if timed else caldavxml.DefaultAlarmVToDoDate
+        return getattr(self, self.ALARM_DETAILS[(vevent, timed)][1])
 
-        prop = self.properties().get(PropertyName.fromElement(propname))
 
-        return str(prop) if prop is not None else None
-
-
     @inlineCallbacks
     def setDefaultAlarm(self, alarm, vevent, timed):
         """
@@ -808,12 +816,16 @@
         @type timed: C{bool}
         """
 
-        if vevent:
-            prop = caldavxml.DefaultAlarmVEventDateTime if timed else caldavxml.DefaultAlarmVEventDate
-        else:
-            prop = caldavxml.DefaultAlarmVToDoDateTime if timed else caldavxml.DefaultAlarmVToDoDate
+        colname, attr_alarm = self.ALARM_DETAILS[(vevent, timed)]
 
-        self.properties()[PropertyName.fromElement(prop)] = prop.fromString(alarm)
+        setattr(self, attr_alarm, alarm)
+
+        chm = self._homeMetaDataSchema
+        yield Update(
+            {colname: alarm},
+            Where=chm.RESOURCE_ID == self._resourceID,
+        ).on(self._txn)
+        yield self.invalidateQueryCache()
         yield self.notifyChanged()
 
 
@@ -894,6 +906,10 @@
 
         return (
             cls._bindSchema.TRANSP,
+            cls._bindSchema.ALARM_VEVENT_TIMED,
+            cls._bindSchema.ALARM_VEVENT_ALLDAY,
+            cls._bindSchema.ALARM_VTODO_TIMED,
+            cls._bindSchema.ALARM_VTODO_ALLDAY,
         )
 
 
@@ -907,6 +923,10 @@
 
         return (
             "_transp",
+            "_alarm_vevent_timed",
+            "_alarm_vevent_allday",
+            "_alarm_vtodo_timed",
+            "_alarm_vtodo_allday",
         )
 
 
@@ -989,6 +1009,12 @@
         else:
             return True
 
+    ALARM_DETAILS = {
+        (True, True): (_bindSchema.ALARM_VEVENT_TIMED, "_alarm_vevent_timed"),
+        (True, False): (_bindSchema.ALARM_VEVENT_ALLDAY, "_alarm_vevent_allday"),
+        (False, True): (_bindSchema.ALARM_VTODO_TIMED, "_alarm_vtodo_timed"),
+        (False, False): (_bindSchema.ALARM_VTODO_ALLDAY, "_alarm_vtodo_allday"),
+    }
 
     def getDefaultAlarm(self, vevent, timed):
         """
@@ -1002,19 +1028,9 @@
         @rtype: C{str}
         """
 
-        if vevent:
-            propname = caldavxml.DefaultAlarmVEventDateTime if timed else caldavxml.DefaultAlarmVEventDate
-        else:
-            propname = caldavxml.DefaultAlarmVToDoDateTime if timed else caldavxml.DefaultAlarmVToDoDate
+        return getattr(self, self.ALARM_DETAILS[(vevent, timed)][1])
 
-        prop = self.properties().get(PropertyName.fromElement(propname))
 
-        if prop is None:
-            return self.viewerHome().getDefaultAlarm(vevent, timed)
-        else:
-            return str(prop)
-
-
     @inlineCallbacks
     def setDefaultAlarm(self, alarm, vevent, timed):
         """
@@ -1028,12 +1044,16 @@
         @type timed: C{bool}
         """
 
-        if vevent:
-            prop = caldavxml.DefaultAlarmVEventDateTime if timed else caldavxml.DefaultAlarmVEventDate
-        else:
-            prop = caldavxml.DefaultAlarmVToDoDateTime if timed else caldavxml.DefaultAlarmVToDoDate
+        colname, attr_alarm = self.ALARM_DETAILS[(vevent, timed)]
 
-        self.properties()[PropertyName.fromElement(prop)] = prop.fromString(alarm)
+        setattr(self, attr_alarm, alarm)
+
+        cal = self._bindSchema
+        yield Update(
+            {colname: alarm},
+            Where=(cal.CALENDAR_HOME_RESOURCE_ID == self.viewerHome()._resourceID).And(cal.CALENDAR_RESOURCE_ID == self._resourceID)
+        ).on(self._txn)
+        yield self.invalidateQueryCache()
         yield self.notifyChanged()
 
 
@@ -1060,9 +1080,7 @@
         self._transp = _TRANSP_OPAQUE if use_it else _TRANSP_TRANSPARENT
         cal = self._bindSchema
         yield Update(
-            {
-                cal.TRANSP : self._transp
-            },
+            {cal.TRANSP : self._transp},
             Where=(cal.CALENDAR_HOME_RESOURCE_ID == self.viewerHome()._resourceID).And(cal.CALENDAR_RESOURCE_ID == self._resourceID)
         ).on(self._txn)
         yield self.invalidateQueryCache()
@@ -1778,7 +1796,9 @@
 
         # See if default exists and add using appropriate logic
         alarm = self.calendar().getDefaultAlarm(vevent, timed)
-        if alarm and component.addAlarms(alarm):
+        if alarm is None:
+            alarm = self.calendar().viewerHome().getDefaultAlarm(vevent, timed)
+        if alarm and alarm != "empty" and component.addAlarms(alarm):
             self._componentChanged = True
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/test/test_sql.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/caldav/datastore/test/test_sql.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -1566,3 +1566,129 @@
         obj = (yield self.calendarObjectUnderTest())
         calendarObject = (yield home.objectResourceWithID(obj._resourceID))
         self.assertNotEquals(calendarObject, None)
+
+
+    @inlineCallbacks
+    def test_defaultAlarms(self):
+        """
+        L{ICalendarHome.objectResourceWithID} will return the calendar object..
+        """
+
+        alarmhome1 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT1M
+END:VALARM
+"""
+
+        alarmhome2 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT2M
+END:VALARM
+"""
+
+        alarmhome3 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT3M
+END:VALARM
+"""
+
+        alarmhome4 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT4M
+END:VALARM
+"""
+
+        alarmcalendar1 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT1M
+END:VALARM
+"""
+
+        alarmcalendar2 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT2M
+END:VALARM
+"""
+
+        alarmcalendar3 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT3M
+END:VALARM
+"""
+
+        alarmcalendar4 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT4M
+END:VALARM
+"""
+
+        detailshome = (
+            (True, True, alarmhome1,),
+            (True, False, alarmhome2,),
+            (False, True, alarmhome3,),
+            (False, False, alarmhome4,),
+        )
+
+        home = yield self.homeUnderTest()
+        for vevent, timed, _ignore_alarm in detailshome:
+            alarm_result = (yield home.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, None)
+
+        for vevent, timed, alarm in detailshome:
+            yield home.setDefaultAlarm(alarm, vevent, timed)
+
+        yield self.commit()
+
+        home = yield self.homeUnderTest()
+        for vevent, timed, alarm in detailshome:
+            alarm_result = (yield home.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, alarm)
+
+        for vevent, timed, alarm in detailshome:
+            yield home.setDefaultAlarm(None, vevent, timed)
+
+        yield self.commit()
+
+        home = yield self.homeUnderTest()
+        for vevent, timed, _ignore_alarm in detailshome:
+            alarm_result = (yield home.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, None)
+
+        yield self.commit()
+
+        detailscalendar = (
+            (True, True, alarmcalendar1,),
+            (True, False, alarmcalendar2,),
+            (False, True, alarmcalendar3,),
+            (False, False, alarmcalendar4,),
+        )
+
+        calendar = yield self.calendarUnderTest()
+        for vevent, timed, _ignore_alarm in detailscalendar:
+            alarm_result = (yield calendar.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, None)
+
+        for vevent, timed, alarm in detailscalendar:
+            yield calendar.setDefaultAlarm(alarm, vevent, timed)
+
+        yield self.commit()
+
+        calendar = yield self.calendarUnderTest()
+        for vevent, timed, alarm in detailscalendar:
+            alarm_result = (yield calendar.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, alarm)
+
+        yield self.commit()
+
+        calendar = yield self.calendarUnderTest()
+        for vevent, timed, alarm in detailscalendar:
+            yield calendar.setDefaultAlarm(None, vevent, timed)
+
+        yield self.commit()
+
+        calendar = yield self.calendarUnderTest()
+        for vevent, timed, _ignore_alarm in detailscalendar:
+            alarm_result = (yield calendar.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, None)
+
+        yield self.commit()


Property changes on: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalendarServer/branches/config-separation/txdav/common/datastore/sql.py:4379-4443
/CalendarServer/branches/egg-info-351/txdav/common/datastore/sql.py:4589-4625
/CalendarServer/branches/generic-sqlstore/txdav/common/datastore/sql.py:6167-6191
/CalendarServer/branches/new-store/txdav/common/datastore/sql.py:5594-5934
/CalendarServer/branches/new-store-no-caldavfile/txdav/common/datastore/sql.py:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2/txdav/common/datastore/sql.py:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev/txdav/common/datastore/sql.py:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699/txdav/common/datastore/sql.py:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692/txdav/common/datastore/sql.py:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes/txdav/common/datastore/sql.py:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627/txdav/common/datastore/sql.py:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace/txdav/common/datastore/sql.py:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim/txdav/common/datastore/sql.py:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments/txdav/common/datastore/sql.py:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591/txdav/common/datastore/sql.py:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464/txdav/common/datastore/sql.py:4465-4957
/CalendarServer/branches/users/cdaboo/pods/txdav/common/datastore/sql.py:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar/txdav/common/datastore/sql.py:7085-7206
/CalendarServer/branches/users/cdaboo/pycard/txdav/common/datastore/sql.py:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes/txdav/common/datastore/sql.py:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070/txdav/common/datastore/sql.py:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187/txdav/common/datastore/sql.py:5188-5440
/CalendarServer/branches/users/cdaboo/timezones/txdav/common/datastore/sql.py:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging/txdav/common/datastore/sql.py:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error/txdav/common/datastore/sql.py:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid/txdav/common/datastore/sql.py:8772-8805
/CalendarServer/branches/users/glyph/conn-limit/txdav/common/datastore/sql.py:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge/txdav/common/datastore/sql.py:4971-5080
/CalendarServer/branches/users/glyph/dalify/txdav/common/datastore/sql.py:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect/txdav/common/datastore/sql.py:6824-6876
/CalendarServer/branches/users/glyph/deploybuild/txdav/common/datastore/sql.py:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux/txdav/common/datastore/sql.py:10624-10635
/CalendarServer/branches/users/glyph/disable-quota/txdav/common/datastore/sql.py:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres/txdav/common/datastore/sql.py:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html/txdav/common/datastore/sql.py:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client/txdav/common/datastore/sql.py:9054-9105
/CalendarServer/branches/users/glyph/linux-tests/txdav/common/datastore/sql.py:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge/txdav/common/datastore/sql.py:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes/txdav/common/datastore/sql.py:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6/txdav/common/datastore/sql.py:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7/txdav/common/datastore/sql.py:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete/txdav/common/datastore/sql.py:8321-8330
/CalendarServer/branches/users/glyph/new-export/txdav/common/datastore/sql.py:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api/txdav/common/datastore/sql.py:10048-10073
/CalendarServer/branches/users/glyph/oracle/txdav/common/datastore/sql.py:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls/txdav/common/datastore/sql.py:7340-7351
/CalendarServer/branches/users/glyph/other-html/txdav/common/datastore/sql.py:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim/txdav/common/datastore/sql.py:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade/txdav/common/datastore/sql.py:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1/txdav/common/datastore/sql.py:8571-8583
/CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing/txdav/common/datastore/sql.py:10204-10289
/CalendarServer/branches/users/glyph/quota/txdav/common/datastore/sql.py:7604-7637
/CalendarServer/branches/users/glyph/sendfdport/txdav/common/datastore/sql.py:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes/txdav/common/datastore/sql.py:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2/txdav/common/datastore/sql.py:8155-8174
/CalendarServer/branches/users/glyph/sharedpool/txdav/common/datastore/sql.py:6490-6550
/CalendarServer/branches/users/glyph/sharing-api/txdav/common/datastore/sql.py:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones/txdav/common/datastore/sql.py:8524-8535
/CalendarServer/branches/users/glyph/sql-store/txdav/common/datastore/sql.py:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop/txdav/common/datastore/sql.py:11060-11065
/CalendarServer/branches/users/glyph/subtransactions/txdav/common/datastore/sql.py:7248-7258
/CalendarServer/branches/users/glyph/table-alias/txdav/common/datastore/sql.py:8651-8664
/CalendarServer/branches/users/glyph/uidexport/txdav/common/datastore/sql.py:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked/txdav/common/datastore/sql.py:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted/txdav/common/datastore/sql.py:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize/txdav/common/datastore/sql.py:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files/txdav/common/datastore/sql.py:7757-7769
/CalendarServer/branches/users/sagen/applepush/txdav/common/datastore/sql.py:8126-8184
/CalendarServer/branches/users/sagen/inboxitems/txdav/common/datastore/sql.py:7380-7381
/CalendarServer/branches/users/sagen/locations-resources/txdav/common/datastore/sql.py:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2/txdav/common/datastore/sql.py:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events/txdav/common/datastore/sql.py:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038/txdav/common/datastore/sql.py:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066/txdav/common/datastore/sql.py:4068-4075
/CalendarServer/branches/users/sagen/resources-2/txdav/common/datastore/sql.py:5084-5093
/CalendarServer/branches/users/sagen/testing/txdav/common/datastore/sql.py:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations/txdav/common/datastore/sql.py:5515-5593
/CalendarServer/trunk/txdav/common/datastore/sql.py:11090-11095,11097-11111,11139-11149
   + /CalendarServer/branches/config-separation/txdav/common/datastore/sql.py:4379-4443
/CalendarServer/branches/egg-info-351/txdav/common/datastore/sql.py:4589-4625
/CalendarServer/branches/generic-sqlstore/txdav/common/datastore/sql.py:6167-6191
/CalendarServer/branches/new-store/txdav/common/datastore/sql.py:5594-5934
/CalendarServer/branches/new-store-no-caldavfile/txdav/common/datastore/sql.py:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2/txdav/common/datastore/sql.py:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev/txdav/common/datastore/sql.py:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699/txdav/common/datastore/sql.py:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692/txdav/common/datastore/sql.py:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes/txdav/common/datastore/sql.py:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627/txdav/common/datastore/sql.py:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace/txdav/common/datastore/sql.py:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim/txdav/common/datastore/sql.py:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments/txdav/common/datastore/sql.py:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591/txdav/common/datastore/sql.py:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464/txdav/common/datastore/sql.py:4465-4957
/CalendarServer/branches/users/cdaboo/pods/txdav/common/datastore/sql.py:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar/txdav/common/datastore/sql.py:7085-7206
/CalendarServer/branches/users/cdaboo/pycard/txdav/common/datastore/sql.py:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes/txdav/common/datastore/sql.py:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070/txdav/common/datastore/sql.py:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187/txdav/common/datastore/sql.py:5188-5440
/CalendarServer/branches/users/cdaboo/timezones/txdav/common/datastore/sql.py:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging/txdav/common/datastore/sql.py:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error/txdav/common/datastore/sql.py:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid/txdav/common/datastore/sql.py:8772-8805
/CalendarServer/branches/users/glyph/conn-limit/txdav/common/datastore/sql.py:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge/txdav/common/datastore/sql.py:4971-5080
/CalendarServer/branches/users/glyph/dalify/txdav/common/datastore/sql.py:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect/txdav/common/datastore/sql.py:6824-6876
/CalendarServer/branches/users/glyph/deploybuild/txdav/common/datastore/sql.py:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux/txdav/common/datastore/sql.py:10624-10635
/CalendarServer/branches/users/glyph/disable-quota/txdav/common/datastore/sql.py:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres/txdav/common/datastore/sql.py:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html/txdav/common/datastore/sql.py:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client/txdav/common/datastore/sql.py:9054-9105
/CalendarServer/branches/users/glyph/linux-tests/txdav/common/datastore/sql.py:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge/txdav/common/datastore/sql.py:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes/txdav/common/datastore/sql.py:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6/txdav/common/datastore/sql.py:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7/txdav/common/datastore/sql.py:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete/txdav/common/datastore/sql.py:8321-8330
/CalendarServer/branches/users/glyph/new-export/txdav/common/datastore/sql.py:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api/txdav/common/datastore/sql.py:10048-10073
/CalendarServer/branches/users/glyph/oracle/txdav/common/datastore/sql.py:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls/txdav/common/datastore/sql.py:7340-7351
/CalendarServer/branches/users/glyph/other-html/txdav/common/datastore/sql.py:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim/txdav/common/datastore/sql.py:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade/txdav/common/datastore/sql.py:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1/txdav/common/datastore/sql.py:8571-8583
/CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing/txdav/common/datastore/sql.py:10204-10289
/CalendarServer/branches/users/glyph/quota/txdav/common/datastore/sql.py:7604-7637
/CalendarServer/branches/users/glyph/sendfdport/txdav/common/datastore/sql.py:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes/txdav/common/datastore/sql.py:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2/txdav/common/datastore/sql.py:8155-8174
/CalendarServer/branches/users/glyph/sharedpool/txdav/common/datastore/sql.py:6490-6550
/CalendarServer/branches/users/glyph/sharing-api/txdav/common/datastore/sql.py:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones/txdav/common/datastore/sql.py:8524-8535
/CalendarServer/branches/users/glyph/sql-store/txdav/common/datastore/sql.py:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop/txdav/common/datastore/sql.py:11060-11065
/CalendarServer/branches/users/glyph/subtransactions/txdav/common/datastore/sql.py:7248-7258
/CalendarServer/branches/users/glyph/table-alias/txdav/common/datastore/sql.py:8651-8664
/CalendarServer/branches/users/glyph/uidexport/txdav/common/datastore/sql.py:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked/txdav/common/datastore/sql.py:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted/txdav/common/datastore/sql.py:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize/txdav/common/datastore/sql.py:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files/txdav/common/datastore/sql.py:7757-7769
/CalendarServer/branches/users/sagen/applepush/txdav/common/datastore/sql.py:8126-8184
/CalendarServer/branches/users/sagen/inboxitems/txdav/common/datastore/sql.py:7380-7381
/CalendarServer/branches/users/sagen/locations-resources/txdav/common/datastore/sql.py:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2/txdav/common/datastore/sql.py:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events/txdav/common/datastore/sql.py:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038/txdav/common/datastore/sql.py:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066/txdav/common/datastore/sql.py:4068-4075
/CalendarServer/branches/users/sagen/resources-2/txdav/common/datastore/sql.py:5084-5093
/CalendarServer/branches/users/sagen/testing/txdav/common/datastore/sql.py:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations/txdav/common/datastore/sql.py:5515-5593
/CalendarServer/trunk/txdav/common/datastore/sql.py:11090-11095,11097-11111,11139-11165

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -30,6 +30,10 @@
     "QUOTA_USED_BYTES" integer default 0 not null,
     "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
     "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+    "ALARM_VEVENT_TIMED" nclob default null,
+    "ALARM_VEVENT_ALLDAY" nclob default null,
+    "ALARM_VTODO_TIMED" nclob default null,
+    "ALARM_VTODO_ALLDAY" nclob default null,
     "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
     "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
 );
@@ -65,7 +69,11 @@
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
     "MESSAGE" nclob,
-    "TRANSP" integer default 0 not null, 
+    "TRANSP" integer default 0 not null,
+    "ALARM_VEVENT_TIMED" nclob default null,
+    "ALARM_VEVENT_ALLDAY" nclob default null,
+    "ALARM_VTODO_TIMED" nclob default null,
+    "ALARM_VTODO_ALLDAY" nclob default null, 
     primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"), 
     unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
 );

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/current.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -33,9 +33,9 @@
 -- Note that this must match the node info schema in twext.enterprise.queue.
 create table NODE_INFO (
   HOSTNAME  varchar(255) not null,
-  PID       integer not null,
-  PORT      integer not null,
-  TIME      timestamp not null default timezone('UTC', CURRENT_TIMESTAMP),
+  PID       integer      not null,
+  PORT      integer      not null,
+  TIME      timestamp    not null default timezone('UTC', CURRENT_TIMESTAMP),
 
   primary key (HOSTNAME, PORT)
 );
@@ -70,12 +70,16 @@
 ----------------------------
 
 create table CALENDAR_HOME_METADATA (
-  RESOURCE_ID      integer      primary key references CALENDAR_HOME on delete cascade, -- implicit index
-  QUOTA_USED_BYTES integer      default 0 not null,
-  DEFAULT_EVENTS   integer      default null references CALENDAR on delete set null,
-  DEFAULT_TASKS    integer      default null references CALENDAR on delete set null,
-  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+  RESOURCE_ID              integer     primary key references CALENDAR_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES         integer     default 0 not null,
+  DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
+  DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
+  ALARM_VEVENT_TIMED       text        default null,
+  ALARM_VEVENT_ALLDAY      text        default null,
+  ALARM_VTODO_TIMED        text        default null,
+  ALARM_VTODO_ALLDAY       text        default null,
+  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
 
@@ -84,10 +88,10 @@
 -----------------------
 
 create table CALENDAR_METADATA (
-  RESOURCE_ID           integer   primary key references CALENDAR on delete cascade, -- implicit index
+  RESOURCE_ID           integer      primary key references CALENDAR on delete cascade, -- implicit index
   SUPPORTED_COMPONENTS  varchar(255) default null,
-  CREATED               timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED              timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+  CREATED               timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
 
@@ -107,8 +111,8 @@
   XML_TYPE                      varchar(255) not null,
   XML_DATA                      text         not null,
   MD5                           char(32)     not null,
-  CREATED                       timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  CREATED                       timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
 
   unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
 );
@@ -130,7 +134,11 @@
   BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
   MESSAGE                   text,
-  TRANSP					integer		 default 0 not null, -- enum CALENDAR_TRANSP
+  TRANSP                    integer      default 0 not null, -- enum CALENDAR_TRANSP
+  ALARM_VEVENT_TIMED        text         default null,
+  ALARM_VEVENT_ALLDAY       text         default null,
+  ALARM_VTODO_TIMED         text         default null,
+  ALARM_VTODO_ALLDAY        text         default null,
 
   primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
   unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
@@ -547,7 +555,7 @@
 create table APN_SUBSCRIPTIONS (
   TOKEN                         varchar(255) not null,
   RESOURCE_KEY                  varchar(255) not null,
-  MODIFIED                      integer not null,
+  MODIFIED                      integer      not null,
   SUBSCRIBER_GUID               varchar(255) not null,
   USER_AGENT                    varchar(255) default null,
   IP_ADDR                       varchar(255) default null,
@@ -568,7 +576,7 @@
   ORGANIZER                     varchar(255) not null,
   ATTENDEE                      varchar(255) not null,
   ICALUID                       varchar(255) not null,
-  ACCESSED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
 
   primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
 );
@@ -589,7 +597,7 @@
 ---------------------------
 
 create table IMIP_INVITATION_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   FROM_ADDR                     varchar(255) not null,
   TO_ADDR                       varchar(255) not null,
@@ -602,7 +610,7 @@
 -----------------------
 
 create table IMIP_POLLING_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
@@ -612,7 +620,7 @@
 ---------------------
 
 create table IMIP_REPLY_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   ORGANIZER                     varchar(255) not null,
   ATTENDEE                      varchar(255) not null,
@@ -625,7 +633,7 @@
 ------------------------
 
 create table PUSH_NOTIFICATION_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   PUSH_ID                       varchar(255) not null
 );
@@ -635,7 +643,7 @@
 -----------------
 
 create table GROUP_CACHER_POLLING_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/oracle-dialect/19.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/oracle-dialect/19.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/oracle-dialect/19.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -30,6 +30,10 @@
     "QUOTA_USED_BYTES" integer default 0 not null,
     "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
     "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+    "ALARM_VEVENT_TIMED" nclob default null,
+    "ALARM_VEVENT_ALLDAY" nclob default null,
+    "ALARM_VTODO_TIMED" nclob default null,
+    "ALARM_VTODO_ALLDAY" nclob default null,
     "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
     "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
 );
@@ -65,7 +69,11 @@
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
     "MESSAGE" nclob,
-    "TRANSP" integer default 0 not null, 
+    "TRANSP" integer default 0 not null,
+    "ALARM_VEVENT_TIMED" nclob default null,
+    "ALARM_VEVENT_ALLDAY" nclob default null,
+    "ALARM_VTODO_TIMED" nclob default null,
+    "ALARM_VTODO_ALLDAY" nclob default null, 
     primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"), 
     unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
 );

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/postgres-dialect/19.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/postgres-dialect/19.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/old/postgres-dialect/19.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -31,9 +31,9 @@
 -- Note that this must match the node info schema in twext.enterprise.queue.
 create table NODE_INFO (
   HOSTNAME  varchar(255) not null,
-  PID       integer not null,
-  PORT      integer not null,
-  TIME      timestamp not null default timezone('UTC', CURRENT_TIMESTAMP),
+  PID       integer      not null,
+  PORT      integer      not null,
+  TIME      timestamp    not null default timezone('UTC', CURRENT_TIMESTAMP),
 
   primary key (HOSTNAME, PORT)
 );
@@ -68,12 +68,16 @@
 ----------------------------
 
 create table CALENDAR_HOME_METADATA (
-  RESOURCE_ID      integer      primary key references CALENDAR_HOME on delete cascade, -- implicit index
-  QUOTA_USED_BYTES integer      default 0 not null,
-  DEFAULT_EVENTS   integer      default null references CALENDAR on delete set null,
-  DEFAULT_TASKS    integer      default null references CALENDAR on delete set null,
-  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+  RESOURCE_ID              integer     primary key references CALENDAR_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES         integer     default 0 not null,
+  DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
+  DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
+  ALARM_VEVENT_TIMED       text        default null,
+  ALARM_VEVENT_ALLDAY      text        default null,
+  ALARM_VTODO_TIMED        text        default null,
+  ALARM_VTODO_ALLDAY       text        default null,
+  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
 
@@ -82,10 +86,10 @@
 -----------------------
 
 create table CALENDAR_METADATA (
-  RESOURCE_ID           integer   primary key references CALENDAR on delete cascade, -- implicit index
+  RESOURCE_ID           integer      primary key references CALENDAR on delete cascade, -- implicit index
   SUPPORTED_COMPONENTS  varchar(255) default null,
-  CREATED               timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED              timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+  CREATED               timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
 
@@ -105,8 +109,8 @@
   XML_TYPE                      varchar(255) not null,
   XML_DATA                      text         not null,
   MD5                           char(32)     not null,
-  CREATED                       timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  CREATED                       timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
 
   unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
 );
@@ -127,7 +131,11 @@
   BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
   MESSAGE                   text,
-  TRANSP					integer		 default 0 not null, -- enum CALENDAR_TRANSP
+  TRANSP                    integer      default 0 not null, -- enum CALENDAR_TRANSP
+  ALARM_VEVENT_TIMED        text         default null,
+  ALARM_VEVENT_ALLDAY       text         default null,
+  ALARM_VTODO_TIMED         text         default null,
+  ALARM_VTODO_ALLDAY        text         default null,
 
   primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
   unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
@@ -494,7 +502,7 @@
 create table APN_SUBSCRIPTIONS (
   TOKEN                         varchar(255) not null,
   RESOURCE_KEY                  varchar(255) not null,
-  MODIFIED                      integer not null,
+  MODIFIED                      integer      not null,
   SUBSCRIBER_GUID               varchar(255) not null,
   USER_AGENT                    varchar(255) default null,
   IP_ADDR                       varchar(255) default null,
@@ -514,7 +522,7 @@
   ORGANIZER                     varchar(255) not null,
   ATTENDEE                      varchar(255) not null,
   ICALUID                       varchar(255) not null,
-  ACCESSED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
 
   primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
 );
@@ -533,7 +541,7 @@
 ---------------------------
 
 create table IMIP_INVITATION_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   FROM_ADDR                     varchar(255) not null,
   TO_ADDR                       varchar(255) not null,
@@ -545,7 +553,7 @@
 -----------------------
 
 create table IMIP_POLLING_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
@@ -554,7 +562,7 @@
 ---------------------
 
 create table IMIP_REPLY_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   ORGANIZER                     varchar(255) not null,
   ATTENDEE                      varchar(255) not null,
@@ -566,7 +574,7 @@
 ------------------------
 
 create table PUSH_NOTIFICATION_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   PUSH_ID                       varchar(255) not null
 );
@@ -576,7 +584,7 @@
 -----------------
 
 create table GROUP_CACHER_POLLING_WORK (
-  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null,
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -22,13 +22,21 @@
 
 alter table ATTACHMENT
  add ("DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
- 	  "DEFAULT_TASKS"  integer default null references CALENDAR on delete set null);
+ 	  "DEFAULT_TASKS"  integer default null references CALENDAR on delete set null,
+      "ALARM_VEVENT_TIMED" nclob default null,
+      "ALARM_VEVENT_ALLDAY" nclob default null,
+      "ALARM_VTODO_TIMED" nclob default null,
+      "ALARM_VTODO_ALLDAY" nclob default null);
 
  	  
 -- Calendar bind related updates
 
 alter table CALENDAR_BIND
- add ("TRANSP" integer default 0 not null);
+ add ("TRANSP" integer default 0 not null,
+      "ALARM_VEVENT_TIMED" nclob default null,
+      "ALARM_VEVENT_ALLDAY" nclob default null,
+      "ALARM_VTODO_TIMED" nclob default null,
+      "ALARM_VTODO_ALLDAY" nclob default null);
 
 create table CALENDAR_TRANSP (
     "ID" integer primary key,

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql	2013-05-10 23:18:19 UTC (rev 11168)
@@ -22,14 +22,22 @@
 -- Calendar home related updates
 
 alter table CALENDAR_HOME_METADATA
- add column DEFAULT_EVENTS integer default null references CALENDAR on delete set null,
- add column DEFAULT_TASKS integer default null references CALENDAR on delete set null;
+ add column DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
+ add column DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
+ add column ALARM_VEVENT_TIMED       text        default null,
+ add column ALARM_VEVENT_ALLDAY      text        default null,
+ add column ALARM_VTODO_TIMED        text        default null,
+ add column ALARM_VTODO_ALLDAY       text        default null;
 
 
 -- Calendar bind related updates
 
 alter table CALENDAR_BIND
- add column TRANSP integer default 0 not null;
+ add column TRANSP                   integer     default 0 not null,
+ add column ALARM_VEVENT_TIMED       text        default null,
+ add column ALARM_VEVENT_ALLDAY      text        default null,
+ add column ALARM_VTODO_TIMED        text        default null,
+ add column ALARM_VTODO_ALLDAY       text        default null;
 
 create table CALENDAR_TRANSP (
   ID          integer     primary key,

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -23,11 +23,11 @@
 
 from txdav.base.propertystore.base import PropertyName
 from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
-from txdav.common.datastore.upgrade.sql.upgrades.util import rowsForProperty, \
-    updateAllCalendarHomeDataVersions, removeProperty, cleanPropertyStore, \
-    updateCalendarDataVersion
+from txdav.common.datastore.upgrade.sql.upgrades.util import rowsForProperty, updateDataVersion, \
+    updateAllCalendarHomeDataVersions, removeProperty, cleanPropertyStore
 from txdav.xml.parser import WebDAVDocument
 from txdav.xml import element
+from twisted.python.failure import Failure
 
 """
 Data upgrade from database version 3 to 4
@@ -43,10 +43,11 @@
     """
     yield moveDefaultCalendarProperties(sqlStore)
     yield moveCalendarTranspProperties(sqlStore)
+    yield moveDefaultAlarmProperties(sqlStore)
     yield removeResourceType(sqlStore)
 
     # Always bump the DB value
-    yield updateCalendarDataVersion(sqlStore, UPGRADE_TO_VERSION)
+    yield updateDataVersion(sqlStore, "CALENDAR-DATAVERSION", UPGRADE_TO_VERSION)
     yield updateAllCalendarHomeDataVersions(sqlStore, UPGRADE_TO_VERSION)
 
 
@@ -60,13 +61,13 @@
     """
 
     meta = schema.CALENDAR_HOME_METADATA
-    yield _processProperty(sqlStore, caldavxml.ScheduleDefaultCalendarURL, meta.DEFAULT_EVENTS)
-    yield _processProperty(sqlStore, customxml.ScheduleDefaultTasksURL, meta.DEFAULT_TASKS)
+    yield _processDefaultCalendarProperty(sqlStore, caldavxml.ScheduleDefaultCalendarURL, meta.DEFAULT_EVENTS)
+    yield _processDefaultCalendarProperty(sqlStore, customxml.ScheduleDefaultTasksURL, meta.DEFAULT_TASKS)
 
 
 
 @inlineCallbacks
-def _processProperty(sqlStore, propname, colname):
+def _processDefaultCalendarProperty(sqlStore, propname, colname):
     """
     Move the specified property value to the matching CALENDAR_HOME_METADATA table column.
 
@@ -122,8 +123,9 @@
         yield cleanPropertyStore()
 
     except RuntimeError:
+        f = Failure()
         yield sqlTxn.abort()
-        raise
+        f.raiseException()
 
 
 
@@ -187,12 +189,130 @@
         yield cleanPropertyStore()
 
     except RuntimeError:
+        f = Failure()
         yield sqlTxn.abort()
-        raise
+        f.raiseException()
 
 
 
 @inlineCallbacks
+def moveDefaultAlarmProperties(sqlStore):
+    """
+    Need to move all the CalDAV:default-calendar and CS:default-tasks properties in the
+    RESOURCE_PROPERTY table to the new CALENDAR_HOME_METADATA table columns, extracting
+    the new value from the XML property.
+    """
+
+    yield _processDefaultAlarmProperty(
+        sqlStore,
+        caldavxml.DefaultAlarmVEventDateTime,
+        True,
+        True,
+    )
+    yield _processDefaultAlarmProperty(
+        sqlStore,
+        caldavxml.DefaultAlarmVEventDate,
+        True,
+        False,
+    )
+    yield _processDefaultAlarmProperty(
+        sqlStore,
+        caldavxml.DefaultAlarmVToDoDateTime,
+        False,
+        True,
+    )
+    yield _processDefaultAlarmProperty(
+        sqlStore,
+        caldavxml.DefaultAlarmVToDoDate,
+        False,
+        False,
+    )
+
+
+
+ at inlineCallbacks
+def _processDefaultAlarmProperty(sqlStore, propname, vevent, timed):
+    """
+    Move the specified property value to the matching CALENDAR_HOME_METADATA or CALENDAR_BIND table column.
+
+    Since the number of properties may well be large, we need to do this in batches.
+    """
+
+    hm = schema.CALENDAR_HOME_METADATA
+    cb = schema.CALENDAR_BIND
+    rp = schema.RESOURCE_PROPERTY
+
+    try:
+        calendars_for_id = {}
+        while True:
+            sqlTxn = sqlStore.newTransaction()
+            rows = (yield rowsForProperty(sqlTxn, propname, with_uid=True, batch=BATCH_SIZE))
+            if len(rows) == 0:
+                yield sqlTxn.commit()
+                break
+            delete_ids = []
+            for rid, value, viewer in rows:
+                delete_ids.append(rid)
+
+                prop = WebDAVDocument.fromString(value).root_element
+                alarm = str(prop.children[0]) if prop.children else None
+
+                # First check if the rid is a home - this is the most common case
+                ids = yield Select(
+                    [hm.RESOURCE_ID, ],
+                    From=hm,
+                    Where=hm.RESOURCE_ID == rid,
+                ).on(sqlTxn)
+
+                if len(ids) > 0:
+                    # Home object
+                    calendarHome = (yield sqlTxn.calendarHomeWithResourceID(ids[0][0]))
+                    if calendarHome is not None:
+                        yield calendarHome.setDefaultAlarm(alarm, vevent, timed)
+                else:
+                    # rid is a calendar - we need to find the per-user calendar for the resource viewer
+                    if rid not in calendars_for_id:
+                        ids = yield Select(
+                            [cb.CALENDAR_HOME_RESOURCE_ID, cb.BIND_MODE, ],
+                            From=cb,
+                            Where=cb.CALENDAR_RESOURCE_ID == rid,
+                        ).on(sqlTxn)
+                        calendars_for_id[rid] = ids
+
+                    if viewer:
+                        calendarHome = (yield sqlTxn.calendarHomeWithUID(viewer))
+                    else:
+                        calendarHome = None
+                        for row in calendars_for_id[rid]:
+                            home_id, bind_mode = row
+                            if bind_mode == _BIND_MODE_OWN:
+                                calendarHome = (yield sqlTxn.calendarHomeWithResourceID(home_id))
+                                break
+
+                    if calendarHome is not None:
+                        calendar = yield calendarHome.childWithID(rid)
+                        if calendar is not None:
+                            yield calendar.setDefaultAlarm(alarm, vevent, timed)
+
+                # Always delete the row so that batch processing works correctly
+                yield Delete(
+                    From=rp,
+                    Where=(rp.RESOURCE_ID.In(Parameter("ids", len(delete_ids)))).And
+                          (rp.NAME == PropertyName.fromElement(propname).toString()),
+                ).on(sqlTxn, ids=delete_ids)
+
+            yield sqlTxn.commit()
+
+        yield cleanPropertyStore()
+
+    except RuntimeError:
+        f = Failure()
+        yield sqlTxn.abort()
+        f.raiseException()
+
+
+
+ at inlineCallbacks
 def removeResourceType(sqlStore):
     sqlTxn = sqlStore.newTransaction()
     yield removeProperty(sqlTxn, PropertyName.fromElement(element.ResourceType))

Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py	2013-05-10 22:42:43 UTC (rev 11167)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py	2013-05-10 23:18:19 UTC (rev 11168)
@@ -20,8 +20,10 @@
 from txdav.xml.element import HRef
 from twext.enterprise.dal.syntax import Update
 from txdav.common.datastore.upgrade.sql.upgrades.calendar_upgrade_from_3_to_4 import moveDefaultCalendarProperties, \
-    moveCalendarTranspProperties, removeResourceType
+    moveCalendarTranspProperties, removeResourceType, moveDefaultAlarmProperties
 from txdav.xml import element
+from twistedcaldav import caldavxml
+from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE
 
 """
 Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
@@ -38,16 +40,17 @@
     def test_defaultCalendarUpgrade(self):
 
         # Set dead property on inbox
-        inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
-        inbox.properties()[PropertyName.fromElement(ScheduleDefaultCalendarURL)] = ScheduleDefaultCalendarURL(HRef.fromString("/calendars/__uids__/user01/calendar_1"))
+        for user in ("user01", "user02",):
+            inbox = (yield self.calendarUnderTest(name="inbox", home=user))
+            inbox.properties()[PropertyName.fromElement(ScheduleDefaultCalendarURL)] = ScheduleDefaultCalendarURL(HRef.fromString("/calendars/__uids__/%s/calendar_1" % (user,)))
 
-        # Force current default to null
-        home = (yield self.homeUnderTest(name="user01"))
-        chm = home._homeMetaDataSchema
-        yield Update(
-            {chm.DEFAULT_EVENTS: None},
-            Where=chm.RESOURCE_ID == home._resourceID,
-        ).on(self.transactionUnderTest())
+            # Force current default to null
+            home = (yield self.homeUnderTest(name=user))
+            chm = home._homeMetaDataSchema
+            yield Update(
+                {chm.DEFAULT_EVENTS: None},
+                Where=chm.RESOURCE_ID == home._resourceID,
+            ).on(self.transactionUnderTest())
 
         # Force data version to previous
         ch = home._homeSchema
@@ -62,68 +65,206 @@
         yield moveDefaultCalendarProperties(self._sqlCalendarStore)
 
         # Test results
-        home = (yield self.homeUnderTest(name="user01"))
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        self.assertTrue(home.isDefaultCalendar(calendar))
-        inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
-        self.assertTrue(PropertyName.fromElement(ScheduleDefaultCalendarURL) not in inbox.properties())
+        for user in ("user01", "user02",):
+            home = (yield self.homeUnderTest(name=user))
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            self.assertTrue(home.isDefaultCalendar(calendar))
+            inbox = (yield self.calendarUnderTest(name="inbox", home=user))
+            self.assertTrue(PropertyName.fromElement(ScheduleDefaultCalendarURL) not in inbox.properties())
 
 
     @inlineCallbacks
     def test_calendarTranspUpgrade(self):
 
         # Set dead property on inbox
-        inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
-        inbox.properties()[PropertyName.fromElement(CalendarFreeBusySet)] = CalendarFreeBusySet(HRef.fromString("/calendars/__uids__/user01/calendar_1"))
+        for user in ("user01", "user02",):
+            inbox = (yield self.calendarUnderTest(name="inbox", home=user))
+            inbox.properties()[PropertyName.fromElement(CalendarFreeBusySet)] = CalendarFreeBusySet(HRef.fromString("/calendars/__uids__/%s/calendar_1" % (user,)))
 
-        # Force current to transparent
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        yield calendar.setUsedForFreeBusy(False)
-        calendar.properties()[PropertyName.fromElement(ScheduleCalendarTransp)] = ScheduleCalendarTransp(Opaque())
+            # Force current to transparent
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            yield calendar.setUsedForFreeBusy(False)
+            calendar.properties()[PropertyName.fromElement(ScheduleCalendarTransp)] = ScheduleCalendarTransp(Opaque())
 
-        # Force data version to previous
-        home = (yield self.homeUnderTest(name="user01"))
-        ch = home._homeSchema
-        yield Update(
-            {ch.DATAVERSION: 3},
-            Where=ch.RESOURCE_ID == home._resourceID,
-        ).on(self.transactionUnderTest())
+            # Force data version to previous
+            home = (yield self.homeUnderTest(name=user))
+            ch = home._homeSchema
+            yield Update(
+                {ch.DATAVERSION: 3},
+                Where=ch.RESOURCE_ID == home._resourceID,
+            ).on(self.transactionUnderTest())
 
         yield self.commit()
 
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        self.assertFalse(calendar.isUsedForFreeBusy())
-        self.assertTrue(PropertyName.fromElement(ScheduleCalendarTransp) in calendar.properties())
-        inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
-        self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) in inbox.properties())
+        for user in ("user01", "user02",):
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            self.assertFalse(calendar.isUsedForFreeBusy())
+            self.assertTrue(PropertyName.fromElement(ScheduleCalendarTransp) in calendar.properties())
+            inbox = (yield self.calendarUnderTest(name="inbox", home=user))
+            self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) in inbox.properties())
         yield self.commit()
 
         # Trigger upgrade
         yield moveCalendarTranspProperties(self._sqlCalendarStore)
 
         # Test results
-        home = (yield self.homeUnderTest(name="user01"))
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        self.assertTrue(calendar.isUsedForFreeBusy())
-        inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
-        self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) not in inbox.properties())
+        for user in ("user01", "user02",):
+            home = (yield self.homeUnderTest(name=user))
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            self.assertTrue(calendar.isUsedForFreeBusy())
+            inbox = (yield self.calendarUnderTest(name="inbox", home=user))
+            self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) not in inbox.properties())
 
 
     @inlineCallbacks
+    def test_defaultAlarmUpgrade(self):
+
+        alarmhome1 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT1M
+END:VALARM
+"""
+
+        alarmhome2 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT2M
+END:VALARM
+"""
+
+        alarmhome3 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT3M
+END:VALARM
+"""
+
+        alarmhome4 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT4M
+END:VALARM
+"""
+
+        alarmcalendar1 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT1M
+END:VALARM
+"""
+
+        alarmcalendar2 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT2M
+END:VALARM
+"""
+
+        alarmcalendar3 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT3M
+END:VALARM
+"""
+
+        alarmcalendar4 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT4M
+END:VALARM
+"""
+
+        alarmshared1 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT1M
+END:VALARM
+"""
+
+        alarmshared2 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT2M
+END:VALARM
+"""
+
+        alarmshared3 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT3M
+END:VALARM
+"""
+
+        alarmshared4 = """BEGIN:VALARM
+ACTION:AUDIO
+TRIGGER;RELATED=START:-PT4M
+END:VALARM
+"""
+
+        # Setup old properties
+        detailshome = (
+            (True, True, alarmhome1, caldavxml.DefaultAlarmVEventDateTime,),
+            (True, False, alarmhome2, caldavxml.DefaultAlarmVEventDate,),
+            (False, True, alarmhome3, caldavxml.DefaultAlarmVToDoDateTime,),
+            (False, False, alarmhome4, caldavxml.DefaultAlarmVToDoDate,),
+        )
+        detailscalendar = (
+            (True, True, alarmcalendar1, caldavxml.DefaultAlarmVEventDateTime,),
+            (True, False, alarmcalendar2, caldavxml.DefaultAlarmVEventDate,),
+            (False, True, alarmcalendar3, caldavxml.DefaultAlarmVToDoDateTime,),
+            (False, False, alarmcalendar4, caldavxml.DefaultAlarmVToDoDate,),
+        )
+        detailsshared = (
+            (True, True, alarmshared1, caldavxml.DefaultAlarmVEventDateTime,),
+            (True, False, alarmshared2, caldavxml.DefaultAlarmVEventDate,),
+            (False, True, alarmshared3, caldavxml.DefaultAlarmVToDoDateTime,),
+            (False, False, alarmshared4, caldavxml.DefaultAlarmVToDoDate,),
+        )
+
+        home = yield self.homeUnderTest(name="user01")
+        for _ignore_vevent, _ignore_timed, alarm, prop in detailshome:
+            home.properties()[PropertyName.fromElement(prop)] = prop(alarm)
+        calendar = yield self.calendarUnderTest(name="calendar_1", home="user01")
+        for _ignore_vevent, _ignore_timed, alarm, prop in detailscalendar:
+            calendar.properties()[PropertyName.fromElement(prop)] = prop(alarm)
+        home2 = yield self.homeUnderTest(name="user02")
+        shared_name = yield calendar.shareWith(home2, _BIND_MODE_WRITE)
+        shared = yield self.calendarUnderTest(name=shared_name, home="user02")
+        for _ignore_vevent, _ignore_timed, alarm, prop in detailsshared:
+            shared.properties()[PropertyName.fromElement(prop)] = prop(alarm)
+        yield self.commit()
+
+        # Trigger upgrade
+        yield moveDefaultAlarmProperties(self._sqlCalendarStore)
+
+        # Check each type of collection
+        home = yield self.homeUnderTest(name="user01")
+        for vevent, timed, alarm, prop in detailshome:
+            alarm_result = (yield home.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, alarm)
+            self.assertTrue(PropertyName.fromElement(prop) not in home.properties())
+
+        calendar = yield self.calendarUnderTest(name="calendar_1", home="user01")
+        for vevent, timed, alarm, prop in detailscalendar:
+            alarm_result = (yield calendar.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, alarm)
+            self.assertTrue(PropertyName.fromElement(prop) not in home.properties())
+
+        shared = yield self.calendarUnderTest(name=shared_name, home="user02")
+        for vevent, timed, alarm, prop in detailsshared:
+            alarm_result = (yield shared.getDefaultAlarm(vevent, timed))
+            self.assertEquals(alarm_result, alarm)
+            self.assertTrue(PropertyName.fromElement(prop) not in home.properties())
+
+
+    @inlineCallbacks
     def test_resourceTypeUpgrade(self):
 
         # Set dead property on calendar
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        calendar.properties()[PropertyName.fromElement(element.ResourceType)] = element.ResourceType(element.Collection())
+        for user in ("user01", "user02",):
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            calendar.properties()[PropertyName.fromElement(element.ResourceType)] = element.ResourceType(element.Collection())
         yield self.commit()
 
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        self.assertTrue(PropertyName.fromElement(element.ResourceType) in calendar.properties())
+        for user in ("user01", "user02",):
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            self.assertTrue(PropertyName.fromElement(element.ResourceType) in calendar.properties())
         yield self.commit()
 
         # Trigger upgrade
         yield removeResourceType(self._sqlCalendarStore)
 
         # Test results
-        calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
-        self.assertTrue(PropertyName.fromElement(element.ResourceType) not in calendar.properties())
+        for user in ("user01", "user02",):
+            calendar = (yield self.calendarUnderTest(name="calendar_1", home=user))
+            self.assertTrue(PropertyName.fromElement(element.ResourceType) not in calendar.properties())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130510/c03545ba/attachment-0001.html>


More information about the calendarserver-changes mailing list