[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