<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[11916] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/11916">11916</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2013-11-08 12:46:55 -0800 (Fri, 08 Nov 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Update to new pycalendar api. Add support for JSON iCalendar data. Add support for VPOLL (disabled by config for now).</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkcalendarservertoolsanonymizepy">CalendarServer/trunk/calendarserver/tools/anonymize.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolscalverifypy">CalendarServer/trunk/calendarserver/tools/calverify.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolsdbinspectpy">CalendarServer/trunk/calendarserver/tools/dbinspect.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolsgatewaypy">CalendarServer/trunk/calendarserver/tools/gateway.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolsmanagetimezonespy">CalendarServer/trunk/calendarserver/tools/managetimezones.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolspurgepy">CalendarServer/trunk/calendarserver/tools/purge.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolstesttest_calverifypy">CalendarServer/trunk/calendarserver/tools/test/test_calverify.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolstesttest_purgepy">CalendarServer/trunk/calendarserver/tools/test/test_purge.py</a></li>
<li><a href="#CalendarServertrunkcalendarservertoolstesttest_purge_old_eventspy">CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesticalpy">CalendarServer/trunk/contrib/performance/loadtest/ical.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestprofilespy">CalendarServer/trunk/contrib/performance/loadtest/profiles.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesttest_icalpy">CalendarServer/trunk/contrib/performance/loadtest/test_ical.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancesqlusagerequestsinvitepy">CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancesqlusagerequestsputpy">CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancesqlusagerequestsquerypy">CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancesqlusagerequestssyncpy">CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancesqlusagesqlusagepy">CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancestatspy">CalendarServer/trunk/contrib/performance/stats.py</a></li>
<li><a href="#CalendarServertrunkcontribperformancetest_statspy">CalendarServer/trunk/contrib/performance/test_stats.py</a></li>
<li><a href="#CalendarServertrunkcontribtoolssortrecurrencespy">CalendarServer/trunk/contrib/tools/sortrecurrences.py</a></li>
<li><a href="#CalendarServertrunksupportbuildsh">CalendarServer/trunk/support/build.sh</a></li>
<li><a href="#CalendarServertrunktwextenterprisedalsyntaxpy">CalendarServer/trunk/twext/enterprise/dal/syntax.py</a></li>
<li><a href="#CalendarServertrunktwextenterprisefixturespy">CalendarServer/trunk/twext/enterprise/fixtures.py</a></li>
<li><a href="#CalendarServertrunktwextenterprisequeuepy">CalendarServer/trunk/twext/enterprise/queue.py</a></li>
<li><a href="#CalendarServertrunktwextenterprisetesttest_queuepy">CalendarServer/trunk/twext/enterprise/test/test_queue.py</a></li>
<li><a href="#CalendarServertrunktwextprotocolstesttest_memcachepy">CalendarServer/trunk/twext/protocols/test/test_memcache.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldav__init__py">CalendarServer/trunk/twistedcaldav/__init__.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavaccountingpy">CalendarServer/trunk/twistedcaldav/accounting.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavauthkerbpy">CalendarServer/trunk/twistedcaldav/authkerb.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavbackuppy">CalendarServer/trunk/twistedcaldav/backup.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavcaldavxmlpy">CalendarServer/trunk/twistedcaldav/caldavxml.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavcarddavxmlpy">CalendarServer/trunk/twistedcaldav/carddavxml.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavcustomxmlpy">CalendarServer/trunk/twistedcaldav/customxml.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdatabasepy">CalendarServer/trunk/twistedcaldav/database.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdatafilterscalendardatapy">CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdateopspy">CalendarServer/trunk/twistedcaldav/dateops.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryaddressbookpy">CalendarServer/trunk/twistedcaldav/directory/addressbook.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryopendirectorybackerpy">CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_aggregatepy">CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_cachedirectorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_digestpy">CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_directorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_guidchangepy">CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_livedirectorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_modifypy">CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_opendirectorybackerpy">CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_proxyprincipaldbpy">CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_resourcespy">CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_xmlfilepy">CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytestutilpy">CalendarServer/trunk/twistedcaldav/directory/test/util.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdropboxpy">CalendarServer/trunk/twistedcaldav/dropbox.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavfreebusyurlpy">CalendarServer/trunk/twistedcaldav/freebusyurl.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavicalpy">CalendarServer/trunk/twistedcaldav/ical.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavicaldavpy">CalendarServer/trunk/twistedcaldav/icaldav.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavinstancepy">CalendarServer/trunk/twistedcaldav/instance.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavlinkresourcepy">CalendarServer/trunk/twistedcaldav/linkresource.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavlocalizationpy">CalendarServer/trunk/twistedcaldav/localization.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmemcachelockpy">CalendarServer/trunk/twistedcaldav/memcachelock.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmemcachepoolpy">CalendarServer/trunk/twistedcaldav/memcachepool.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethodgetpy">CalendarServer/trunk/twistedcaldav/method/get.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethodpropfindpy">CalendarServer/trunk/twistedcaldav/method/propfind.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethodreport_calendar_querypy">CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethodreport_commonpy">CalendarServer/trunk/twistedcaldav/method/report_common.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethodreport_freebusypy">CalendarServer/trunk/twistedcaldav/method/report_freebusy.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmkcolxmlpy">CalendarServer/trunk/twistedcaldav/mkcolxml.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavnotificationspy">CalendarServer/trunk/twistedcaldav/notifications.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavquerycalendarqueryfilterpy">CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavquerytesttest_calendarquerypy">CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavquerytesttest_queryfilterpy">CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavresourcepy">CalendarServer/trunk/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavscheduling_storecaldavresourcepy">CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavsharingpy">CalendarServer/trunk/twistedcaldav/sharing.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavsqlpy">CalendarServer/trunk/twistedcaldav/sql.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstdconfigpy">CalendarServer/trunk/twistedcaldav/stdconfig.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstorebridgepy">CalendarServer/trunk/twistedcaldav/storebridge.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_addressbookmultigetpy">CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_caldavxmlpy">CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_calendarquerypy">CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_dateopspy">CalendarServer/trunk/twistedcaldav/test/test_dateops.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_icalendarpy">CalendarServer/trunk/twistedcaldav/test/test_icalendar.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_localizationpy">CalendarServer/trunk/twistedcaldav/test/test_localization.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_multigetpy">CalendarServer/trunk/twistedcaldav/test/test_multiget.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_propspy">CalendarServer/trunk/twistedcaldav/test/test_props.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_timezonespy">CalendarServer/trunk/twistedcaldav/test/test_timezones.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_upgradepy">CalendarServer/trunk/twistedcaldav/test/test_upgrade.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtimezonespy">CalendarServer/trunk/twistedcaldav/timezones.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtimezoneservicepy">CalendarServer/trunk/twistedcaldav/timezoneservice.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavtimezonestdservicepy">CalendarServer/trunk/twistedcaldav/timezonestdservice.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavupgradepy">CalendarServer/trunk/twistedcaldav/upgrade.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavutilpy">CalendarServer/trunk/twistedcaldav/util.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavvcardpy">CalendarServer/trunk/twistedcaldav/vcard.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavxmlutilpy">CalendarServer/trunk/twistedcaldav/xmlutil.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastorefilepy">CalendarServer/trunk/txdav/caldav/datastore/file.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreindex_filepy">CalendarServer/trunk/txdav/caldav/datastore/index_file.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingcaldavtesttest_schedulerpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingfreebusypy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingicaldiffpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingicalsplitterpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingimipoutboundpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_deliverypy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_inboundpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_outboundpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingimplicitpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingischeduleresourcepy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingischeduleschedulerpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingischeduletesttest_resourcepy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingitippy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingprocessingpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingschedulerpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_freebusypy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_icalsplitterpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_implicitpy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_itippy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_utilspy">CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoresqlpy">CalendarServer/trunk/txdav/caldav/datastore/sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretestcommonpy">CalendarServer/trunk/txdav/caldav/datastore/test/common.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_attachmentspy">CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_filepy">CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_index_filepy">CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy">CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_utilpy">CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoreutilpy">CalendarServer/trunk/txdav/caldav/datastore/util.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavicalendarstorepy">CalendarServer/trunk/txdav/caldav/icalendarstore.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresqlpy">CalendarServer/trunk/txdav/common/datastore/sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_legacypy">CalendarServer/trunk/txdav/common/datastore/sql_legacy.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemacurrentoracledialectsql">CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemacurrentsql">CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoretestutilpy">CalendarServer/trunk/txdav/common/datastore/test/util.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoreupgradesqlupgradescalendar_upgrade_from_3_to_4py">CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServertrunktwistedcaldavtesttest_utilpy">CalendarServer/trunk/twistedcaldav/test/test_util.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv24sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv24sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_24_to_25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_25_to_26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_26_to_27sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_24_to_25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_25_to_26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_26_to_27sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv24sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv24sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_24_to_25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_25_to_26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_24_to_25sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_25_to_26sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#CalendarServertrunk">CalendarServer/trunk/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunk"></a>
<div class="propset"><h4>Property changes: CalendarServer/trunk</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4>Modified: svn:mergeinfo</h4></div>
<span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><span class="cx">   + /CalDAVTester/trunk:11193-11198
</span><span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/json:11622-11912
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><a id="CalendarServertrunkcalendarservertoolsanonymizepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/anonymize.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/anonymize.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/anonymize.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -33,8 +33,8 @@
</span><span class="cx"> 
</span><span class="cx"> from twext.python.plistlib import readPlistFromString
</span><span class="cx"> 
</span><del>-from pycalendar.calendar import PyCalendar
-from pycalendar.attribute import PyCalendarAttribute
</del><ins>+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.parameter import Parameter
</ins><span class="cx"> 
</span><span class="cx"> COPY_CAL_XATTRS = (
</span><span class="cx">     'WebDAV:{DAV:}resourcetype',
</span><span class="lines">@@ -67,6 +67,8 @@
</span><span class="cx">     else:
</span><span class="cx">         sys.exit(0)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def main():
</span><span class="cx"> 
</span><span class="cx">     try:
</span><span class="lines">@@ -83,8 +85,6 @@
</span><span class="cx">     # Get configuration
</span><span class="cx">     #
</span><span class="cx">     directoryNode = &quot;/Search&quot;
</span><del>-    sourceDirectory = None
-    destDirectory = None
</del><span class="cx"> 
</span><span class="cx">     for opt, arg in optargs:
</span><span class="cx">         if opt in (&quot;-h&quot;, &quot;--help&quot;):
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx">     directoryMap.dumpDsImports(os.path.join(destDirectory, &quot;dsimports&quot;))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def anonymizeRoot(directoryMap, sourceDirectory, destDirectory):
</span><span class="cx">     # sourceDirectory and destDirectory are DocumentRoots
</span><span class="cx"> 
</span><span class="lines">@@ -244,12 +245,10 @@
</span><span class="cx"> 
</span><span class="cx">                     resources += 1
</span><span class="cx"> 
</span><del>-
</del><span class="cx">                 # Store new ctag on calendar
</span><span class="cx">                 xml = &quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;\r\n&lt;getctag xmlns='http://calendarserver.org/ns/'&gt;%s&lt;/getctag&gt;\r\n&quot; % (str(datetime.datetime.now()),)
</span><span class="cx">                 xattr.setxattr(destCal, &quot;WebDAV:{http:%2F%2Fcalendarserver.org%2Fns%2F}getctag&quot;, zlib.compress(xml))
</span><span class="cx"> 
</span><del>-
</del><span class="cx">             # Calendar home quota
</span><span class="cx">             xml = &quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;\r\n&lt;quota-used xmlns='http://twistedmatrix.com/xml_namespace/dav/private/'&gt;%d&lt;/quota-used&gt;\r\n&quot; % (quotaUsed,)
</span><span class="cx">             xattr.setxattr(destHome, &quot;WebDAV:{http:%2F%2Ftwistedmatrix.com%2Fxml_namespace%2Fdav%2Fprivate%2F}quota-used&quot;, zlib.compress(xml))
</span><span class="lines">@@ -280,9 +279,10 @@
</span><span class="cx">     print(&quot;&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def anonymizeData(directoryMap, data):
</span><span class="cx">     try:
</span><del>-        pyobj = PyCalendar.parseText(data)
</del><ins>+        pyobj = Calendar.parseText(data)
</ins><span class="cx">     except Exception, e:
</span><span class="cx">         print(&quot;Failed to parse (%s): %s&quot; % (e, data))
</span><span class="cx">         return None
</span><span class="lines">@@ -309,13 +309,13 @@
</span><span class="cx">                             comp.removeProperty(prop)
</span><span class="cx">                             continue
</span><span class="cx">                     prop.setValue(&quot;urn:uuid:%s&quot; % (record['guid'],))
</span><del>-                    if prop.hasAttribute('X-CALENDARSERVER-EMAIL'):
-                        prop.replaceAttribute(PyCalendarAttribute('X-CALENDARSERVER-EMAIL', record['email']))
</del><ins>+                    if prop.hasParameter('X-CALENDARSERVER-EMAIL'):
+                        prop.replaceParameter(Parameter('X-CALENDARSERVER-EMAIL', record['email']))
</ins><span class="cx">                     else:
</span><del>-                        prop.removeAttributes('EMAIL')
-                        prop.addAttribute(PyCalendarAttribute('EMAIL', record['email']))
-                    prop.removeAttributes('CN')
-                    prop.addAttribute(PyCalendarAttribute('CN', record['name']))
</del><ins>+                        prop.removeParameters('EMAIL')
+                        prop.addParameter(Parameter('EMAIL', record['email']))
+                    prop.removeParameters('CN')
+                    prop.addParameter(Parameter('CN', record['name']))
</ins><span class="cx">             except KeyError:
</span><span class="cx">                 pass
</span><span class="cx"> 
</span><span class="lines">@@ -345,11 +345,12 @@
</span><span class="cx">     return pyobj.getText(includeTimezones=True)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DirectoryMap(object):
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, node):
</span><span class="cx"> 
</span><del>-        self.map = { }
</del><ins>+        self.map = {}
</ins><span class="cx">         self.byType = {
</span><span class="cx">             'users' : [],
</span><span class="cx">             'groups' : [],
</span><span class="lines">@@ -373,10 +374,10 @@
</span><span class="cx"> 
</span><span class="cx">         print(&quot;Fetching records from directory: %s&quot; % (node,))
</span><span class="cx"> 
</span><del>-        for internalType, (recordType, friendlyType) in self.strings.iteritems():
</del><ins>+        for internalType, (recordType, _ignore_friendlyType) in self.strings.iteritems():
</ins><span class="cx">             print(&quot; %s...&quot; % (internalType,))
</span><span class="cx">             child = Popen(
</span><del>-                args = [
</del><ins>+                args=[
</ins><span class="cx">                     &quot;/usr/bin/dscl&quot;, &quot;-plist&quot;, node, &quot;-readall&quot;,
</span><span class="cx">                     &quot;/%s&quot; % (recordType,),
</span><span class="cx">                     &quot;GeneratedUID&quot;, &quot;RecordName&quot;, &quot;EMailAddress&quot;, &quot;GroupMembers&quot;
</span><span class="lines">@@ -405,6 +406,7 @@
</span><span class="cx">         print(&quot;Done.&quot;)
</span><span class="cx">         print(&quot;&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def addRecord(self, internalType=&quot;users&quot;, guid=None, names=None,
</span><span class="cx">         emails=None, members=None, cua=None):
</span><span class="cx"> 
</span><span class="lines">@@ -458,6 +460,7 @@
</span><span class="cx">                 keys.append(email)
</span><span class="cx">         return keys
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def cua2key(self, cua):
</span><span class="cx">         key = cua.lower()
</span><span class="cx"> 
</span><span class="lines">@@ -473,10 +476,11 @@
</span><span class="cx"> 
</span><span class="cx">         return key
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def lookupCUA(self, cua):
</span><span class="cx">         key = self.cua2key(cua)
</span><span class="cx"> 
</span><del>-        if key and self.map.has_key(key):
</del><ins>+        if key and key in self.map:
</ins><span class="cx">             return self.map[key]
</span><span class="cx">         else:
</span><span class="cx">             return None
</span><span class="lines">@@ -491,6 +495,7 @@
</span><span class="cx">         if unknown:
</span><span class="cx">             print(&quot; Principals not found in directory: %d&quot; % (unknown,))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def dumpDsImports(self, dirPath):
</span><span class="cx">         if not os.path.exists(dirPath):
</span><span class="cx">             os.makedirs(dirPath)
</span><span class="lines">@@ -567,6 +572,8 @@
</span><span class="cx">     Error trying to access dscl
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class DatabaseError(Exception):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Error trying to access sqlite3
</span><span class="lines">@@ -574,8 +581,6 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
-
</del><span class="cx"> def anonymize(text):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Return a string whose value is the hex digest of text, repeated as needed
</span><span class="lines">@@ -592,19 +597,18 @@
</span><span class="cx">     h = hashlib.md5(text)
</span><span class="cx">     h = h.hexdigest()
</span><span class="cx">     l = len(text)
</span><del>-    return (h*((l/32)+1))[:-(32-(l%32))]
</del><ins>+    return (h * ((l / 32) + 1))[:-(32 - (l % 32))]
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> nameChars = &quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
</span><span class="cx"> def randomName(length):
</span><span class="cx">     l = []
</span><del>-    for i in xrange(length):
</del><ins>+    for _ignore in xrange(length):
</ins><span class="cx">         l.append(random.choice(nameChars))
</span><span class="cx">     return &quot;&quot;.join(l)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> if __name__ == &quot;__main__&quot;:
</span><span class="cx">     main()
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolscalverifypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/calverify.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/calverify.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/calverify.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -47,12 +47,12 @@
</span><span class="cx"> import traceback
</span><span class="cx"> import uuid
</span><span class="cx"> 
</span><del>-from pycalendar import definitions
-from pycalendar.calendar import PyCalendar
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.exceptions import PyCalendarError
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.icalendar import definitions
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.datetime import DateTime
+from pycalendar.exceptions import ErrorBase
+from pycalendar.period import Period
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twisted.application.service import Service
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="lines">@@ -543,7 +543,7 @@
</span><span class="cx">         tr = schema.TIME_RANGE
</span><span class="cx">         kwds = {
</span><span class="cx">             &quot;Start&quot; : pyCalendarTodatetime(start),
</span><del>-            &quot;Max&quot;   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0))
</del><ins>+            &quot;Max&quot;   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0))
</ins><span class="cx">         }
</span><span class="cx">         rows = (yield Select(
</span><span class="cx">             [ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED],
</span><span class="lines">@@ -596,7 +596,7 @@
</span><span class="cx">         tr = schema.TIME_RANGE
</span><span class="cx">         kwds = {
</span><span class="cx">             &quot;Start&quot; : pyCalendarTodatetime(start),
</span><del>-            &quot;Max&quot;   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
</del><ins>+            &quot;Max&quot;   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
</ins><span class="cx">             &quot;UUID&quot; : uuid,
</span><span class="cx">         }
</span><span class="cx">         rows = (yield Select(
</span><span class="lines">@@ -626,7 +626,7 @@
</span><span class="cx"> 
</span><span class="cx">         kwds = {
</span><span class="cx">             &quot;Start&quot; : pyCalendarTodatetime(start),
</span><del>-            &quot;Max&quot;   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
</del><ins>+            &quot;Max&quot;   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
</ins><span class="cx">             &quot;UUID&quot; : uuid,
</span><span class="cx">         }
</span><span class="cx">         rows = (yield Select(
</span><span class="lines">@@ -704,8 +704,8 @@
</span><span class="cx">             ),
</span><span class="cx">         ).on(self.txn, **kwds))
</span><span class="cx">         try:
</span><del>-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
</del><ins>+            caldata = Calendar.parseText(rows[0][0]) if rows else None
+        except ErrorBase:
</ins><span class="cx">             caltxt = rows[0][0] if rows else None
</span><span class="cx">             if caltxt:
</span><span class="cx">                 caltxt = caltxt.replace(&quot;\r\n &quot;, &quot;&quot;)
</span><span class="lines">@@ -713,8 +713,8 @@
</span><span class="cx">                     if doFix:
</span><span class="cx">                         caltxt = (yield self.fixBadOldCua(resid, caltxt))
</span><span class="cx">                         try:
</span><del>-                            caldata = PyCalendar.parseText(caltxt) if rows else None
-                        except PyCalendarError:
</del><ins>+                            caldata = Calendar.parseText(caltxt) if rows else None
+                        except ErrorBase:
</ins><span class="cx">                             self.parseError = &quot;No fix bad CALENDARSERVER-OLD-CUA&quot;
</span><span class="cx">                             returnValue(None)
</span><span class="cx">                     else:
</span><span class="lines">@@ -746,8 +746,8 @@
</span><span class="cx">         ).on(self.txn, **kwds))
</span><span class="cx"> 
</span><span class="cx">         try:
</span><del>-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
</del><ins>+            caldata = Calendar.parseText(rows[0][0]) if rows else None
+        except ErrorBase:
</ins><span class="cx">             returnValue((None, None, None, None,))
</span><span class="cx"> 
</span><span class="cx">         returnValue((caldata, rows[0][1], rows[0][2], rows[0][3],) if rows else (None, None, None, None,))
</span><span class="lines">@@ -1056,14 +1056,14 @@
</span><span class="cx"> 
</span><span class="cx">         self.output.write(&quot;\n---- Scanning calendar data ----\n&quot;)
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = PyCalendarDateTime.getToday()
</del><ins>+        self.now = DateTime.getNowUTC()
+        self.start = DateTime.getToday()
</ins><span class="cx">         self.start.setDateOnly(False)
</span><span class="cx">         self.end = self.start.duplicate()
</span><span class="cx">         self.end.offsetYear(1)
</span><span class="cx">         self.fix = self.options[&quot;fix&quot;]
</span><span class="cx"> 
</span><del>-        self.tzid = PyCalendarTimezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
</del><ins>+        self.tzid = Timezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
</ins><span class="cx"> 
</span><span class="cx">         self.txn = self.store.newTransaction()
</span><span class="cx"> 
</span><span class="lines">@@ -1426,14 +1426,14 @@
</span><span class="cx"> 
</span><span class="cx">         self.output.write(&quot;\n---- Scanning calendar data ----\n&quot;)
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = self.options[&quot;start&quot;] if &quot;start&quot; in self.options else PyCalendarDateTime.getToday()
</del><ins>+        self.now = DateTime.getNowUTC()
+        self.start = self.options[&quot;start&quot;] if &quot;start&quot; in self.options else DateTime.getToday()
</ins><span class="cx">         self.start.setDateOnly(False)
</span><span class="cx">         self.end = self.start.duplicate()
</span><span class="cx">         self.end.offsetYear(1)
</span><span class="cx">         self.fix = self.options[&quot;fix&quot;]
</span><span class="cx"> 
</span><del>-        self.tzid = PyCalendarTimezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
</del><ins>+        self.tzid = Timezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
</ins><span class="cx"> 
</span><span class="cx">         self.txn = self.store.newTransaction()
</span><span class="cx"> 
</span><span class="lines">@@ -2028,7 +2028,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return the master iCal component in this calendar.
</span><span class="cx"> 
</span><del>-        @return: the L{PyCalendarComponent} for the master component,
</del><ins>+        @return: the L{Component} for the master component,
</ins><span class="cx">             or C{None} if there isn't one.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         for component in calendar.getComponents(definitions.cICalComponent_VEVENT):
</span><span class="lines">@@ -2042,7 +2042,7 @@
</span><span class="cx">         # Expand events into instances in the start/end range
</span><span class="cx">         results = []
</span><span class="cx">         calendar.getVEvents(
</span><del>-            PyCalendarPeriod(
</del><ins>+            Period(
</ins><span class="cx">                 start=start,
</span><span class="cx">                 end=end,
</span><span class="cx">             ),
</span><span class="lines">@@ -2082,10 +2082,10 @@
</span><span class="cx">                 if cancelled:
</span><span class="cx">                     partstat = &quot;CANCELLED&quot;
</span><span class="cx">                 else:
</span><del>-                    if not prop.hasAttribute(definitions.cICalAttribute_PARTSTAT):
-                        partstat = definitions.cICalAttribute_PARTSTAT_NEEDSACTION
</del><ins>+                    if not prop.hasParameter(definitions.cICalParameter_PARTSTAT):
+                        partstat = definitions.cICalParameter_PARTSTAT_NEEDSACTION
</ins><span class="cx">                     else:
</span><del>-                        partstat = prop.getAttributeValue(definitions.cICalAttribute_PARTSTAT)
</del><ins>+                        partstat = prop.getParameterValue(definitions.cICalParameter_PARTSTAT)
</ins><span class="cx"> 
</span><span class="cx">                 attendees.setdefault(caladdr, set()).add((instance_id, partstat))
</span><span class="cx"> 
</span><span class="lines">@@ -2140,9 +2140,9 @@
</span><span class="cx"> 
</span><span class="cx">         self.output.write(&quot;\n---- Scanning calendar data ----\n&quot;)
</span><span class="cx"> 
</span><del>-        self.tzid = PyCalendarTimezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = PyCalendarDateTime.getToday()
</del><ins>+        self.tzid = Timezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
+        self.now = DateTime.getNowUTC()
+        self.start = DateTime.getToday()
</ins><span class="cx">         self.start.setDateOnly(False)
</span><span class="cx">         self.start.setTimezone(self.tzid)
</span><span class="cx">         self.end = self.start.duplicate()
</span><span class="lines">@@ -2328,7 +2328,7 @@
</span><span class="cx">                     continue
</span><span class="cx">                 dtstart = instance.component.propertyValue(&quot;DTSTART&quot;)
</span><span class="cx">                 if tzid is None and dtstart.getTimezoneID():
</span><del>-                    tzid = PyCalendarTimezone(tzid=dtstart.getTimezoneID())
</del><ins>+                    tzid = Timezone(tzid=dtstart.getTimezoneID())
</ins><span class="cx">                 hasFloating |= dtstart.isDateOnly() or dtstart.floating()
</span><span class="cx"> 
</span><span class="cx">                 details.append(InstanceDetails(resid, uid, instance.start, instance.end, instance.component.getOrganizer(), instance.component.propertyValue(&quot;SUMMARY&quot;)))
</span><span class="lines">@@ -2369,7 +2369,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Adjust floating and sort
</span><span class="cx">         if hasFloating and tzid is not None:
</span><del>-            utc = PyCalendarTimezone(utc=True)
</del><ins>+            utc = Timezone(utc=True)
</ins><span class="cx">             for item in details:
</span><span class="cx">                 if item.start.floating():
</span><span class="cx">                     item.start.setTimezone(tzid)
</span><span class="lines">@@ -2449,9 +2449,9 @@
</span><span class="cx"> 
</span><span class="cx">         self.output.write(&quot;\n---- Scanning calendar data ----\n&quot;)
</span><span class="cx"> 
</span><del>-        self.tzid = PyCalendarTimezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = self.options[&quot;start&quot;] if &quot;start&quot; in self.options else PyCalendarDateTime.getToday()
</del><ins>+        self.tzid = Timezone(tzid=self.options[&quot;tzid&quot;] if self.options[&quot;tzid&quot;] else &quot;America/Los_Angeles&quot;)
+        self.now = DateTime.getNowUTC()
+        self.start = self.options[&quot;start&quot;] if &quot;start&quot; in self.options else DateTime.getToday()
</ins><span class="cx">         self.start.setDateOnly(False)
</span><span class="cx">         self.start.setTimezone(self.tzid)
</span><span class="cx">         self.fix = self.options[&quot;fix&quot;]
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolsdbinspectpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/dbinspect.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/dbinspect.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/dbinspect.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> 
</span><span class="cx"> from calendarserver.tools import tables
</span><span class="cx"> from calendarserver.tools.cmdline import utilityMain
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twext.enterprise.dal.syntax import Select, Parameter, Count, Delete, \
</span><span class="cx">     Constant
</span><span class="cx"> from twisted.application.service import Service
</span><span class="lines">@@ -715,12 +715,12 @@
</span><span class="cx">             end += &quot;T000000Z&quot;
</span><span class="cx"> 
</span><span class="cx">         try:
</span><del>-            start = PyCalendarDateTime.parseText(start)
</del><ins>+            start = DateTime.parseText(start)
</ins><span class="cx">         except ValueError:
</span><span class="cx">             print(&quot;Invalid start value&quot;)
</span><span class="cx">             returnValue(None)
</span><span class="cx">         try:
</span><del>-            end = PyCalendarDateTime.parseText(end)
</del><ins>+            end = DateTime.parseText(end)
</ins><span class="cx">         except ValueError:
</span><span class="cx">             print(&quot;Invalid end value&quot;)
</span><span class="cx">             returnValue(None)
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolsgatewaypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/gateway.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/gateway.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/gateway.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -36,9 +36,9 @@
</span><span class="cx"> from calendarserver.tools.purge import WorkerService, PurgeOldEventsService, DEFAULT_BATCH_SIZE, DEFAULT_RETAIN_DAYS
</span><span class="cx"> from calendarserver.tools.cmdline import utilityMain
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><del>-from twistedcaldav.config import config, ConfigDict 
</del><ins>+from twistedcaldav.config import config, ConfigDict
</ins><span class="cx"> 
</span><span class="cx"> from calendarserver.tools.config import WRITABLE_CONFIG_KEYS, setKeyPath, getKeyPath, flattenDictionary, WritableConfig
</span><span class="cx"> 
</span><span class="lines">@@ -373,7 +373,7 @@
</span><span class="cx">             return
</span><span class="cx">         self.respondWithRecordsOfTypes(self.dir, command, [&quot;resources&quot;])
</span><span class="cx"> 
</span><del>-        
</del><ins>+
</ins><span class="cx">     def command_getLocationAndResourceList(self, command):
</span><span class="cx">         self.respondWithRecordsOfTypes(self.dir, command, [&quot;locations&quot;, &quot;resources&quot;])
</span><span class="cx"> 
</span><span class="lines">@@ -424,10 +424,8 @@
</span><span class="cx">             self.command_readConfig(command)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     # Proxies
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def command_listWriteProxies(self, command):
</span><span class="cx">         principal = principalForPrincipalID(command['Principal'], directory=self.dir)
</span><span class="lines">@@ -538,14 +536,13 @@
</span><span class="cx">         @type command: C{dict}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         retainDays = command.get(&quot;RetainDays&quot;, DEFAULT_RETAIN_DAYS)
</span><del>-        cutoff = PyCalendarDateTime.getToday()
</del><ins>+        cutoff = DateTime.getToday()
</ins><span class="cx">         cutoff.setDateOnly(False)
</span><span class="cx">         cutoff.offsetDay(-retainDays)
</span><span class="cx">         eventCount = (yield PurgeOldEventsService.purgeOldEvents(self.store, cutoff, DEFAULT_BATCH_SIZE))
</span><span class="cx">         self.respond(command, {'EventsRemoved' : eventCount, &quot;RetainDays&quot; : retainDays})
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def respondWithProxies(self, directory, command, principal, proxyType):
</span><span class="cx">         proxies = []
</span><span class="lines">@@ -562,7 +559,6 @@
</span><span class="cx">         })
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     def respondWithRecordsOfTypes(self, directory, command, recordTypes):
</span><span class="cx">         result = []
</span><span class="cx">         for recordType in recordTypes:
</span><span class="lines">@@ -572,7 +568,6 @@
</span><span class="cx">         self.respond(command, result)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     def respond(self, command, result):
</span><span class="cx">         self.output.write(writePlistToString({'command' : command['command'], 'result' : result}))
</span><span class="cx"> 
</span><span class="lines">@@ -581,6 +576,7 @@
</span><span class="cx">         self.output.write(writePlistToString({'error' : msg, }))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def recordToDict(record):
</span><span class="cx">     recordDict = {}
</span><span class="cx">     for key, info in attrMap.iteritems():
</span><span class="lines">@@ -596,6 +592,8 @@
</span><span class="cx">             pass
</span><span class="cx">     return recordDict
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def respondWithError(msg, status=1):
</span><span class="cx">     sys.stdout.write(writePlistToString({'error' : msg, }))
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolsmanagetimezonespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/managetimezones.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/managetimezones.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/managetimezones.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,8 +16,8 @@
</span><span class="cx"> ##
</span><span class="cx"> from __future__ import print_function
</span><span class="cx"> 
</span><del>-from pycalendar.calendar import PyCalendar
-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> from twext.python.log import StandardIOObserver
</span><span class="lines">@@ -95,11 +95,11 @@
</span><span class="cx">         pass
</span><span class="cx"> 
</span><span class="cx">     if not tzvers:
</span><del>-        tzvers = PyCalendarDateTime.getToday().getText()
</del><ins>+        tzvers = DateTime.getToday().getText()
</ins><span class="cx">     print(&quot;Converting data (version: %s) at: %s&quot; % (tzvers, zonedir,))
</span><span class="cx">     startYear = 1800
</span><del>-    endYear = PyCalendarDateTime.getToday().getYear() + 10
-    PyCalendar.sProdID = &quot;-//calendarserver.org//Zonal//EN&quot;
</del><ins>+    endYear = DateTime.getToday().getYear() + 10
+    Calendar.sProdID = &quot;-//calendarserver.org//Zonal//EN&quot;
</ins><span class="cx">     zonefiles = &quot;northamerica&quot;, &quot;southamerica&quot;, &quot;europe&quot;, &quot;africa&quot;, &quot;asia&quot;, &quot;australasia&quot;, &quot;antarctica&quot;, &quot;etcetera&quot;, &quot;backward&quot;
</span><span class="cx">     parser = tzconvert()
</span><span class="cx">     for file in zonefiles:
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolspurgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/purge.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/purge.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/purge.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx"> 
</span><span class="cx"> from getopt import getopt, GetoptError
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> 
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx">         if dryrun:
</span><span class="cx">             verbose = True
</span><span class="cx"> 
</span><del>-        cutoff = PyCalendarDateTime.getToday()
</del><ins>+        cutoff = DateTime.getToday()
</ins><span class="cx">         cutoff.setDateOnly(False)
</span><span class="cx">         cutoff.offsetDay(-days)
</span><span class="cx">         cls.cutoff = cutoff
</span><span class="lines">@@ -328,7 +328,7 @@
</span><span class="cx"> 
</span><span class="cx">         cls.uuid = uuid
</span><span class="cx">         if days &gt; 0:
</span><del>-            cutoff = PyCalendarDateTime.getToday()
</del><ins>+            cutoff = DateTime.getToday()
</ins><span class="cx">             cutoff.setDateOnly(False)
</span><span class="cx">             cutoff.offsetDay(-days)
</span><span class="cx">             cls.cutoff = cutoff
</span><span class="lines">@@ -352,7 +352,7 @@
</span><span class="cx">         service = cls(store)
</span><span class="cx">         service.uuid = uuid
</span><span class="cx">         if days &gt; 0:
</span><del>-            cutoff = PyCalendarDateTime.getToday()
</del><ins>+            cutoff = DateTime.getToday()
</ins><span class="cx">             cutoff.setDateOnly(False)
</span><span class="cx">             cutoff.offsetDay(-days)
</span><span class="cx">             service.cutoff = cutoff
</span><span class="lines">@@ -732,7 +732,7 @@
</span><span class="cx">     def _purgeUID(self, uid):
</span><span class="cx"> 
</span><span class="cx">         if self.when is None:
</span><del>-            self.when = PyCalendarDateTime.getNowUTC()
</del><ins>+            self.when = DateTime.getNowUTC()
</ins><span class="cx"> 
</span><span class="cx">         # Does the record exist?
</span><span class="cx">         record = self.directory.recordWithUID(uid)
</span><span class="lines">@@ -1020,7 +1020,7 @@
</span><span class="cx">         @type event: L{twistedcaldav.ical.Component}
</span><span class="cx"> 
</span><span class="cx">         @param when: the cutoff date (anything after which is removed)
</span><del>-        @type when: PyCalendarDateTime
</del><ins>+        @type when: DateTime
</ins><span class="cx"> 
</span><span class="cx">         @param cua: Calendar User Address of principal being purged, to compare
</span><span class="cx">             to see if it's the organizer of the event or just an attendee
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolstesttest_calverifypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/test/test_calverify.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/test/test_calverify.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/test/test_calverify.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> from calendarserver.tools.calverify import BadDataService, \
</span><span class="cx">     SchedulingMismatchService, DoubleBookingService, DarkPurgeService
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twisted.internet import reactor
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks
</span><span class="lines">@@ -969,7 +969,7 @@
</span><span class="cx">         self.notifierFactory.reset()
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-now = PyCalendarDateTime.getToday()
</del><ins>+now = DateTime.getToday()
</ins><span class="cx"> now.setDay(1)
</span><span class="cx"> now.offsetMonth(2)
</span><span class="cx"> nowYear = now.getYear()
</span><span class="lines">@@ -1404,7 +1404,7 @@
</span><span class="cx"> 
</span><span class="cx">         home = (yield self.homeUnderTest(name=self.uuid3))
</span><span class="cx">         calendar = (yield self.calendarUnderTest(name=&quot;calendar2&quot;, home=self.uuid3))
</span><del>-        yield home.setDefaultCalendar(calendar)
</del><ins>+        yield home.setDefaultCalendar(calendar, &quot;VEVENT&quot;)
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1431,7 +1431,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -1498,7 +1498,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -1707,7 +1707,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -1758,7 +1758,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -1934,7 +1934,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: CalVerifyMismatchTestsBase.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -1983,7 +1983,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: CalVerifyMismatchTestsBase.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -2446,7 +2446,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: self.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;utc&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">         }
</span><span class="cx">         output = StringIO()
</span><span class="cx">         calverify = DoubleBookingService(self._sqlCalendarStore, options, output, reactor, config)
</span><span class="lines">@@ -2609,7 +2609,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: self.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;utc&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">             &quot;no-organizer&quot;: False,
</span><span class="cx">             &quot;invalid-organizer&quot;: False,
</span><span class="cx">             &quot;disabled-organizer&quot;: False,
</span><span class="lines">@@ -2656,7 +2656,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: self.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;utc&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">             &quot;no-organizer&quot;: False,
</span><span class="cx">             &quot;invalid-organizer&quot;: False,
</span><span class="cx">             &quot;disabled-organizer&quot;: False,
</span><span class="lines">@@ -2715,7 +2715,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: self.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;utc&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">             &quot;no-organizer&quot;: True,
</span><span class="cx">             &quot;invalid-organizer&quot;: False,
</span><span class="cx">             &quot;disabled-organizer&quot;: False,
</span><span class="lines">@@ -2774,7 +2774,7 @@
</span><span class="cx">             &quot;uid&quot;: &quot;&quot;,
</span><span class="cx">             &quot;uuid&quot;: self.uuidl1,
</span><span class="cx">             &quot;tzid&quot;: &quot;utc&quot;,
</span><del>-            &quot;start&quot;: PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+            &quot;start&quot;: DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx">             &quot;no-organizer&quot;: True,
</span><span class="cx">             &quot;invalid-organizer&quot;: True,
</span><span class="cx">             &quot;disabled-organizer&quot;: True,
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolstesttest_purgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/test/test_purge.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/test/test_purge.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/test/test_purge.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -21,8 +21,8 @@
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> from twistedcaldav.test.util import StoreTestCase
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks
</span><span class="cx"> from txdav.common.datastore.test.util import populateCalendarsFrom
</span><span class="lines">@@ -33,11 +33,11 @@
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-future = PyCalendarDateTime.getNowUTC()
</del><ins>+future = DateTime.getNowUTC()
</ins><span class="cx"> future.offsetDay(1)
</span><span class="cx"> future = future.getText()
</span><span class="cx"> 
</span><del>-past = PyCalendarDateTime.getNowUTC()
</del><ins>+past = DateTime.getNowUTC()
</ins><span class="cx"> past.offsetDay(-1)
</span><span class="cx"> past = past.getText()
</span><span class="cx"> 
</span><span class="lines">@@ -230,7 +230,7 @@
</span><span class="cx">     def test_cancelRepeating(self):
</span><span class="cx">         # A repeating event where purged CUA is organizer
</span><span class="cx">         event = Component.fromString(REPEATING_1_ICS_BEFORE)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_MODIFIED)
</span><span class="cx">         self.assertEquals(str(event), REPEATING_1_ICS_AFTER)
</span><span class="lines">@@ -239,7 +239,7 @@
</span><span class="cx">     def test_cancelAllDayRepeating(self):
</span><span class="cx">         # A repeating All Day event where purged CUA is organizer
</span><span class="cx">         event = Component.fromString(REPEATING_2_ICS_BEFORE)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_MODIFIED)
</span><span class="cx">         self.assertEquals(str(event), REPEATING_2_ICS_AFTER)
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx">     def test_cancelFutureEvent(self):
</span><span class="cx">         # A future event
</span><span class="cx">         event = Component.fromString(FUTURE_EVENT_ICS)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
</span><span class="cx"> 
</span><span class="lines">@@ -256,7 +256,7 @@
</span><span class="cx">     def test_cancelNonMeeting(self):
</span><span class="cx">         # A repeating non-meeting event
</span><span class="cx">         event = Component.fromString(REPEATING_NON_MEETING_ICS)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
</span><span class="cx"> 
</span><span class="lines">@@ -264,7 +264,7 @@
</span><span class="cx">     def test_cancelAsAttendee(self):
</span><span class="cx">         # A repeating meeting event where purged CUA is an attendee
</span><span class="cx">         event = Component.fromString(REPEATING_ATTENDEE_MEETING_ICS)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
</span><span class="cx"> 
</span><span class="lines">@@ -273,7 +273,7 @@
</span><span class="cx">         # A repeating meeting occurrence with no master, where purged CUA is
</span><span class="cx">         # an attendee
</span><span class="cx">         event = Component.fromString(INVITED_TO_OCCURRENCE_ICS)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
</span><span class="cx"> 
</span><span class="lines">@@ -282,7 +282,7 @@
</span><span class="cx">         # Multiple meeting occurrences with no master, where purged CUA is
</span><span class="cx">         # an attendee
</span><span class="cx">         event = Component.fromString(INVITED_TO_MULTIPLE_OCCURRENCES_ICS)
</span><del>-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             &quot;urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66&quot;)
</span><span class="cx">         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcalendarservertoolstesttest_purge_old_eventspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -21,8 +21,8 @@
</span><span class="cx"> from calendarserver.tools.purge import PurgeOldEventsService, PurgeAttachmentsService, \
</span><span class="cx">     PurgePrincipalService
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.enterprise.dal.syntax import Update, Delete
</span><span class="cx"> from twext.web2.http_headers import MimeType
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-now = PyCalendarDateTime.getToday().getYear()
</del><ins>+now = DateTime.getToday().getYear()
</ins><span class="cx"> 
</span><span class="cx"> OLD_ICS = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -443,7 +443,7 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_eventsOlderThan(self):
</span><del>-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
</del><ins>+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
</ins><span class="cx">         txn = self._sqlCalendarStore.newTransaction()
</span><span class="cx"> 
</span><span class="cx">         # Query for all old events
</span><span class="lines">@@ -475,7 +475,7 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_removeOldEvents(self):
</span><del>-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
</del><ins>+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
</ins><span class="cx">         txn = self._sqlCalendarStore.newTransaction()
</span><span class="cx"> 
</span><span class="cx">         # Remove oldest event - except we don't know what that is because of the dummy timestamps
</span><span class="lines">@@ -598,7 +598,7 @@
</span><span class="cx">         self.assertTrue(os.path.exists(mattachmentPath2))
</span><span class="cx"> 
</span><span class="cx">         # Delete all old events (including the event containing the attachment)
</span><del>-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
</del><ins>+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
</ins><span class="cx">         count = (yield self.transactionUnderTest().removeOldEvents(cutoff))
</span><span class="cx"> 
</span><span class="cx">         # See which events have gone and which exist
</span><span class="lines">@@ -633,7 +633,7 @@
</span><span class="cx">         # Dry run
</span><span class="cx">         total = (yield PurgeOldEventsService.purgeOldEvents(
</span><span class="cx">             self._sqlCalendarStore,
</span><del>-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
</del><ins>+            DateTime(now, 4, 1, 0, 0, 0),
</ins><span class="cx">             2,
</span><span class="cx">             dryrun=True,
</span><span class="cx">             verbose=False
</span><span class="lines">@@ -643,7 +643,7 @@
</span><span class="cx">         # Actually remove
</span><span class="cx">         total = (yield PurgeOldEventsService.purgeOldEvents(
</span><span class="cx">             self._sqlCalendarStore,
</span><del>-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
</del><ins>+            DateTime(now, 4, 1, 0, 0, 0),
</ins><span class="cx">             2,
</span><span class="cx">             verbose=False
</span><span class="cx">         ))
</span><span class="lines">@@ -652,7 +652,7 @@
</span><span class="cx">         # There should be no more left
</span><span class="cx">         total = (yield PurgeOldEventsService.purgeOldEvents(
</span><span class="cx">             self._sqlCalendarStore,
</span><del>-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
</del><ins>+            DateTime(now, 4, 1, 0, 0, 0),
</ins><span class="cx">             2,
</span><span class="cx">             verbose=False
</span><span class="cx">         ))
</span><span class="lines">@@ -681,7 +681,7 @@
</span><span class="cx">         # Purge home1
</span><span class="cx">         total, ignored = (yield PurgePrincipalService.purgeUIDs(self._sqlCalendarStore, self.directory,
</span><span class="cx">             self.rootResource, (&quot;home1&quot;,), verbose=False, proxies=False,
</span><del>-            when=PyCalendarDateTime(now, 4, 1, 12, 0, 0, 0, PyCalendarTimezone(utc=True))))
</del><ins>+            when=DateTime(now, 4, 1, 12, 0, 0, 0, Timezone(utc=True))))
</ins><span class="cx"> 
</span><span class="cx">         # 4 items deleted: 3 events and 1 vcard
</span><span class="cx">         self.assertEquals(total, 4)
</span><span class="lines">@@ -768,7 +768,7 @@
</span><span class="cx">         # Remove old events first
</span><span class="cx">         total = (yield PurgeOldEventsService.purgeOldEvents(
</span><span class="cx">             self._sqlCalendarStore,
</span><del>-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
</del><ins>+            DateTime(now, 4, 1, 0, 0, 0),
</ins><span class="cx">             2,
</span><span class="cx">             verbose=False
</span><span class="cx">         ))
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesticalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/ical.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -29,9 +29,9 @@
</span><span class="cx"> from contrib.performance.httpclient import StringProducer, readBody
</span><span class="cx"> from contrib.performance.loadtest.subscribe import Periodical
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.internet.adaptendpoint import connect
</span><span class="cx"> from twext.internet.gaiendpoint import GAIEndpoint
</span><span class="lines">@@ -1609,13 +1609,13 @@
</span><span class="cx">             msg(&quot;Availability request spanning multiple days (%r to %r), &quot;
</span><span class="cx">                 &quot;dropping the end date.&quot; % (start, end))
</span><span class="cx"> 
</span><del>-        start.setTimezone(PyCalendarTimezone(utc=True))
</del><ins>+        start.setTimezone(Timezone(utc=True))
</ins><span class="cx">         start.setHHMMSS(0, 0, 0)
</span><del>-        end = start + PyCalendarDuration(hours=24)
</del><ins>+        end = start + Duration(hours=24)
</ins><span class="cx"> 
</span><span class="cx">         start = start.getText()
</span><span class="cx">         end = end.getText()
</span><del>-        now = PyCalendarDateTime.getNowUTC().getText()
</del><ins>+        now = DateTime.getNowUTC().getText()
</ins><span class="cx"> 
</span><span class="cx">         label_suffix = &quot;small&quot;
</span><span class="cx">         if len(users) &gt; 5:
</span><span class="lines">@@ -1919,7 +1919,7 @@
</span><span class="cx">         # the sim can fire a PUT between the PROPFIND and when process the removals.
</span><span class="cx">         old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
</span><span class="cx"> 
</span><del>-        now = PyCalendarDateTime.getNowUTC()
</del><ins>+        now = DateTime.getNowUTC()
</ins><span class="cx">         now.setDateOnly(True)
</span><span class="cx">         now.offsetMonth(-1) # 1 month back default
</span><span class="cx">         result = yield self._report(
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestprofilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -42,8 +42,8 @@
</span><span class="cx"> from contrib.performance.loadtest.logger import SummarizingMixin
</span><span class="cx"> from contrib.performance.loadtest.ical import IncorrectResponseCode
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
</ins><span class="cx"> 
</span><span class="cx"> class ProfileBase(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -407,9 +407,9 @@
</span><span class="cx">             vevent = vcalendar.mainComponent()
</span><span class="cx">             uid = str(uuid4())
</span><span class="cx">             dtstart = self._eventStartDistribution.sample()
</span><del>-            dtend = dtstart + PyCalendarDuration(seconds=self._eventDurationDistribution.sample())
-            vevent.replaceProperty(Property(&quot;CREATED&quot;, PyCalendarDateTime.getNowUTC()))
-            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx">             vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
</span><span class="cx">             vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
</span><span class="cx">             vevent.replaceProperty(Property(&quot;UID&quot;, uid))
</span><span class="lines">@@ -650,9 +650,9 @@
</span><span class="cx">             vevent = vcalendar.mainComponent()
</span><span class="cx">             uid = str(uuid4())
</span><span class="cx">             dtstart = self._eventStartDistribution.sample()
</span><del>-            dtend = dtstart + PyCalendarDuration(seconds=self._eventDurationDistribution.sample())
-            vevent.replaceProperty(Property(&quot;CREATED&quot;, PyCalendarDateTime.getNowUTC()))
-            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx">             vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
</span><span class="cx">             vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
</span><span class="cx">             vevent.replaceProperty(Property(&quot;UID&quot;, uid))
</span><span class="lines">@@ -719,8 +719,8 @@
</span><span class="cx">             vtodo = vcalendar.mainComponent()
</span><span class="cx">             uid = str(uuid4())
</span><span class="cx">             due = self._taskStartDistribution.sample()
</span><del>-            vtodo.replaceProperty(Property(&quot;CREATED&quot;, PyCalendarDateTime.getNowUTC()))
-            vtodo.replaceProperty(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+            vtodo.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vtodo.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx">             vtodo.replaceProperty(Property(&quot;DUE&quot;, due))
</span><span class="cx">             vtodo.replaceProperty(Property(&quot;UID&quot;, uid))
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesttest_icalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/test_ical.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_ical.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -24,8 +24,8 @@
</span><span class="cx"> from contrib.performance.loadtest.ical import XMPPPush, Event, Calendar, OS_X_10_6
</span><span class="cx"> from contrib.performance.loadtest.sim import _DirectoryRecord
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
</span><span class="cx"> from twisted.internet.protocol import ProtocolToConsumerAdapter
</span><span class="lines">@@ -1957,8 +1957,8 @@
</span><span class="cx">         self.client.outbox = &quot;/calendars/__uids__/%s/outbox/&quot; % (self.record.uid,)
</span><span class="cx">         requests = self.interceptRequests()
</span><span class="cx"> 
</span><del>-        start = PyCalendarDateTime(2011, 6, 10, 10, 45, 0, tzid=PyCalendarTimezone(utc=True))
-        end = PyCalendarDateTime(2011, 6, 10, 11, 15, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        start = DateTime(2011, 6, 10, 10, 45, 0, tzid=Timezone(utc=True))
+        end = DateTime(2011, 6, 10, 11, 15, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         d = self.client.requestAvailability(
</span><span class="cx">             start, end, [u&quot;urn:uuid:user05&quot;, u&quot;urn:uuid:user10&quot;])
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancesqlusagerequestsinvitepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> from caldavclientlibrary.protocol.url import URL
</span><span class="cx"> from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twext.web2.dav.util import joinURL
</span><span class="cx"> from caldavclientlibrary.protocol.webdav.definitions import davxml
</span><span class="cx"> 
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Invite as user02
</span><del>-        now = PyCalendarDateTime.getNowUTC()
</del><ins>+        now = DateTime.getNowUTC()
</ins><span class="cx">         href = joinURL(self.sessions[1].calendarHref, &quot;organizer.ics&quot;)
</span><span class="cx">         self.sessions[1].writeData(URL(path=href), ICAL % (now.getYear() + 1,), &quot;text/calendar&quot;)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancesqlusagerequestsputpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> from caldavclientlibrary.protocol.url import URL
</span><span class="cx"> from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twext.web2.dav.util import joinURL
</span><span class="cx"> 
</span><span class="cx"> ICAL = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">         Execute the actual HTTP request.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        now = PyCalendarDateTime.getNowUTC()
</del><ins>+        now = DateTime.getNowUTC()
</ins><span class="cx">         href = joinURL(self.sessions[0].calendarHref, &quot;put.ics&quot;)
</span><span class="cx">         self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1,), &quot;text/calendar&quot;)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancesqlusagerequestsquerypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
</span><span class="cx"> from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
</span><span class="cx"> from twext.web2.dav.util import joinURL
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
</span><span class="cx"> from caldavclientlibrary.protocol.http.data.string import ResponseDataString
</span><span class="cx"> 
</span><span class="lines">@@ -70,7 +70,7 @@
</span><span class="cx">         Do some setup prior to the real request.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # Add resources to create required number of changes
</span><del>-        self.start = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.start = DateTime.getNowUTC()
</ins><span class="cx">         self.start.setHHMMSS(12, 0, 0)
</span><span class="cx">         self.end = self.start.duplicate()
</span><span class="cx">         self.end.offsetHours(1)
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancesqlusagerequestssyncpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> from caldavclientlibrary.protocol.webdav.definitions import davxml
</span><span class="cx"> from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
</span><span class="cx"> from twext.web2.dav.util import joinURL
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> ICAL = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">             self.synctoken = results[davxml.sync_token]
</span><span class="cx"> 
</span><span class="cx">             # Add resources to create required number of changes
</span><del>-            now = PyCalendarDateTime.getNowUTC()
</del><ins>+            now = DateTime.getNowUTC()
</ins><span class="cx">             for i in range(self.count):
</span><span class="cx">                 href = joinURL(self.sessions[0].calendarHref, &quot;sync-collection-%d.ics&quot; % (i + 1,))
</span><span class="cx">                 self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1, i + 1,), &quot;text/calendar&quot;)
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancesqlusagesqlusagepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> from contrib.performance.sqlusage.requests.put import PutTest
</span><span class="cx"> from contrib.performance.sqlusage.requests.query import QueryTest
</span><span class="cx"> from contrib.performance.sqlusage.requests.sync import SyncTest
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twext.web2.dav.util import joinURL
</span><span class="cx"> import getopt
</span><span class="cx"> import itertools
</span><span class="lines">@@ -183,7 +183,7 @@
</span><span class="cx">         @param n: number of events
</span><span class="cx">         @type n: C{int}
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        now = PyCalendarDateTime.getNowUTC()
</del><ins>+        now = DateTime.getNowUTC()
</ins><span class="cx">         for i in range(n - self.currentCount):
</span><span class="cx">             index = self.currentCount + i + 1
</span><span class="cx">             href = joinURL(calendarhref, &quot;%d.ics&quot; % (index,))
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancestatspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/stats.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/stats.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/stats.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,10 +16,10 @@
</span><span class="cx"> 
</span><span class="cx"> from __future__ import print_function
</span><span class="cx"> from math import log, sqrt
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.property import PyCalendarProperty
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration as PyDuration
+from pycalendar.icalendar.property import Property
+from pycalendar.timezone import Timezone
</ins><span class="cx"> from twisted.python.util import FancyEqMixin
</span><span class="cx"> from zope.interface import Interface, implements
</span><span class="cx"> import random
</span><span class="lines">@@ -338,7 +338,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def sample(self):
</span><del>-        now = PyCalendarDateTime.getNowUTC()
</del><ins>+        now = DateTime.getNowUTC()
</ins><span class="cx">         now.offsetSeconds(int(self._offset.sample()))
</span><span class="cx">         return now
</span><span class="cx"> 
</span><span class="lines">@@ -390,7 +390,7 @@
</span><span class="cx">             60 * 60 * 8 * 6,
</span><span class="cx">             # Standard deviation of 4 workdays
</span><span class="cx">             60 * 60 * 8 * 4)
</span><del>-        self.now = PyCalendarDateTime.getNow
</del><ins>+        self.now = DateTime.getNow
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def astimestamp(self, dt):
</span><span class="lines">@@ -406,7 +406,7 @@
</span><span class="cx">         # Find a workday that follows the timestamp
</span><span class="cx">         weekday = when.getDayOfWeek()
</span><span class="cx">         for i in range(NUM_WEEKDAYS):
</span><del>-            day = when + PyCalendarDuration(days=i)
</del><ins>+            day = when + PyDuration(days=i)
</ins><span class="cx">             if (weekday + i) % NUM_WEEKDAYS in self._daysOfWeek:
</span><span class="cx">                 # Joy, a day on which work might occur.  Find the first hour on
</span><span class="cx">                 # this day when work may start.
</span><span class="lines">@@ -419,8 +419,8 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def sample(self):
</span><del>-        offset = PyCalendarDuration(seconds=int(self._helperDistribution.sample()))
-        beginning = self.now(PyCalendarTimezone(tzid=self._tzname))
</del><ins>+        offset = PyDuration(seconds=int(self._helperDistribution.sample()))
+        beginning = self.now(Timezone(tzid=self._tzname))
</ins><span class="cx">         while offset:
</span><span class="cx">             start, end = self._findWorkAfter(beginning)
</span><span class="cx">             if end - start &gt; offset:
</span><span class="lines">@@ -463,8 +463,7 @@
</span><span class="cx">             index = self._helperDistribution.sample()
</span><span class="cx">             rrule = self._rrules[index]
</span><span class="cx">             if rrule:
</span><del>-                prop = PyCalendarProperty()
-                prop.parse(rrule)
</del><ins>+                prop = Property.parseText(rrule)
</ins><span class="cx">                 return prop
</span><span class="cx"> 
</span><span class="cx">         return None
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformancetest_statspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/test_stats.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/test_stats.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/performance/test_stats.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -20,8 +20,8 @@
</span><span class="cx">     SQLDuration, LogNormalDistribution, UniformDiscreteDistribution,
</span><span class="cx">     UniformIntegerDistribution, WorkDistribution, quantize,
</span><span class="cx">     RecurrenceDistribution)
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> class SQLDurationTests(TestCase):
</span><span class="cx">     def setUp(self):
</span><span class="lines">@@ -90,21 +90,21 @@
</span><span class="cx">         tzname = &quot;US/Eastern&quot;
</span><span class="cx">         dist = WorkDistribution([&quot;mon&quot;, &quot;wed&quot;, &quot;thu&quot;, &quot;sat&quot;], 10, 20, tzname)
</span><span class="cx">         dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
</span><del>-        dist.now = lambda tzname = None: PyCalendarDateTime(2011, 5, 29, 18, 5, 36, tzid=tzname)
</del><ins>+        dist.now = lambda tzname = None: DateTime(2011, 5, 29, 18, 5, 36, tzid=tzname)
</ins><span class="cx">         value = dist.sample()
</span><span class="cx">         self.assertEqual(
</span><span class="cx">             # Move past three workdays - monday, wednesday, thursday - using 30
</span><span class="cx">             # of the hours, and then five and a half hours into the fourth
</span><span class="cx">             # workday, saturday.  Workday starts at 10am, so the sample value
</span><span class="cx">             # is 3:30pm, ie 1530 hours.
</span><del>-            PyCalendarDateTime(2011, 6, 4, 15, 30, 0, tzid=PyCalendarTimezone(tzid=tzname)),
</del><ins>+            DateTime(2011, 6, 4, 15, 30, 0, tzid=Timezone(tzid=tzname)),
</ins><span class="cx">             value
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         dist = WorkDistribution([&quot;mon&quot;, &quot;tue&quot;, &quot;wed&quot;, &quot;thu&quot;, &quot;fri&quot;], 10, 20, tzname)
</span><span class="cx">         dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
</span><span class="cx">         value = dist.sample()
</span><del>-        self.assertTrue(isinstance(value, PyCalendarDateTime))
</del><ins>+        self.assertTrue(isinstance(value, DateTime))
</ins><span class="cx"> 
</span><span class="cx">     # twisted.trial.unittest.FailTest: not equal:
</span><span class="cx">     # a = datetime.datetime(2011, 6, 4, 15, 30, tzinfo=&lt;DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD&gt;)
</span></span></pre></div>
<a id="CalendarServertrunkcontribtoolssortrecurrencespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/tools/sortrecurrences.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/tools/sortrecurrences.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/contrib/tools/sortrecurrences.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -20,7 +20,7 @@
</span><span class="cx"> import os
</span><span class="cx"> import sys
</span><span class="cx"> import traceback
</span><del>-from pycalendar.calendar import PyCalendar
</del><ins>+from pycalendar.icalendar.calendar import Calendar
</ins><span class="cx"> 
</span><span class="cx"> def usage(error_msg=None):
</span><span class="cx">     if error_msg:
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">                 print(&quot;Path does not exist: '%s'. Ignoring.&quot; % (arg,))
</span><span class="cx">                 continue
</span><span class="cx"> 
</span><del>-            cal = PyCalendar()
</del><ins>+            cal = Calendar()
</ins><span class="cx">             cal.parse(open(arg))
</span><span class="cx">             print(str(cal.serialize()))
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunksupportbuildsh"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/support/build.sh (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/support/build.sh        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/support/build.sh        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -808,7 +808,7 @@
</span><span class="cx">     &quot;${pypi}/p/${n}/${p}.tar.gz&quot;;
</span><span class="cx"> 
</span><span class="cx">   # XXX actually PyCalendar should be imported in-place.
</span><del>-  py_dependency -fe -i &quot;src&quot; -r 11458 \
</del><ins>+  py_dependency -fe -i &quot;src&quot; -r 11914 \
</ins><span class="cx">     &quot;PyCalendar&quot; &quot;pycalendar&quot; &quot;pycalendar&quot; \
</span><span class="cx">     &quot;${svn_uri_base}/PyCalendar/trunk&quot;;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwextenterprisedalsyntaxpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/enterprise/dal/syntax.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twext/enterprise/dal/syntax.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twext/enterprise/dal/syntax.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1686,6 +1686,7 @@
</span><span class="cx">             SQLFragment(' in %s mode' % (self.mode,)))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DatabaseLock(_LockingStatement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     An SQL exclusive session level advisory lock
</span><span class="lines">@@ -1706,6 +1707,7 @@
</span><span class="cx">         return succeed(None)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DatabaseUnlock(_LockingStatement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     An SQL exclusive session level advisory lock
</span><span class="lines">@@ -1726,6 +1728,7 @@
</span><span class="cx">         return succeed(None)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class Savepoint(_LockingStatement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     An SQL 'savepoint' statement.
</span></span></pre></div>
<a id="CalendarServertrunktwextenterprisefixturespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/enterprise/fixtures.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twext/enterprise/fixtures.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twext/enterprise/fixtures.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -194,7 +194,6 @@
</span><span class="cx">         No implementation.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     def callFromThread(self, thunk, *a, **kw):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         No implementation.
</span><span class="lines">@@ -223,14 +222,16 @@
</span><span class="cx">             self.factory = ConnectionFactory()
</span><span class="cx">             connect = self.factory.connect
</span><span class="cx">         self.connect = connect
</span><del>-        self.paused             = False
-        self.holders            = []
-        self.pool               = ConnectionPool(connect,
-                                                 maxConnections=2,
-                                                 dialect=self.dialect,
-                                                 paramstyle=self.paramstyle)
</del><ins>+        self.paused = False
+        self.holders = []
+        self.pool = ConnectionPool(
+            connect,
+            maxConnections=2,
+            dialect=self.dialect,
+            paramstyle=self.paramstyle
+        )
</ins><span class="cx">         self.pool._createHolder = self.makeAHolder
</span><del>-        self.clock              = self.pool.reactor = ClockWithThreads()
</del><ins>+        self.clock = self.pool.reactor = ClockWithThreads()
</ins><span class="cx">         self.pool.startService()
</span><span class="cx">         test.addCleanup(self.flushHolders)
</span><span class="cx"> 
</span><span class="lines">@@ -239,7 +240,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Flush all pending C{submit}s since C{pauseHolders} was called.  This
</span><span class="cx">         makes sure the service is stopped and the fake ThreadHolders are all
</span><del>-        executing their queues so failed tsets can exit cleanly.
</del><ins>+        executing their queues so failed tests can exit cleanly.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         self.paused = False
</span><span class="cx">         for holder in self.holders:
</span></span></pre></div>
<a id="CalendarServertrunktwextenterprisequeuepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/enterprise/queue.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twext/enterprise/queue.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twext/enterprise/queue.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     (in the worst case) pass from worker-&gt;controller-&gt;controller-&gt;worker.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def performWork(table, workID):
</del><ins>+    def performWork(table, workID): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @param table: The table where work is waiting.
</span><span class="cx">         @type table: L{TableSyntax}
</span><span class="lines">@@ -371,7 +371,6 @@
</span><span class="cx">         will be taken care of by the job queueing machinery.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @classmethod
</span><span class="cx">     def forTable(cls, table):
</span><span class="cx">         &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktwextenterprisetesttest_queuepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/enterprise/test/test_queue.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twext/enterprise/test/test_queue.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twext/enterprise/test/test_queue.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -563,8 +563,8 @@
</span><span class="cx">             t = StringTransport()
</span><span class="cx">             p.makeConnection(t)
</span><span class="cx">             return p, t
</span><del>-        worker1, trans1 = peer()
-        worker2, trans2 = peer()
</del><ins>+        worker1, _ignore_trans1 = peer()
+        worker2, _ignore_trans2 = peer()
</ins><span class="cx">         # Ask the worker to do something.
</span><span class="cx">         worker1.performWork(schema.DUMMY_WORK_ITEM, 1)
</span><span class="cx">         self.assertEquals(worker1.currentLoad, 1)
</span><span class="lines">@@ -678,7 +678,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Keep relaying data until there's no more.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        for x in range(turns):
</del><ins>+        for _ignore_x in range(turns):
</ins><span class="cx">             if not (self.pump() or self.pump()):
</span><span class="cx">                 return
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwextprotocolstesttest_memcachepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/protocols/test/test_memcache.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twext/protocols/test/test_memcache.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twext/protocols/test/test_memcache.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -329,7 +329,7 @@
</span><span class="cx">         def check(result):
</span><span class="cx">             self.assertEquals(result, (0, &quot;bar&quot;))
</span><span class="cx">             self.assertEquals(len(self.clock.calls), 1)
</span><del>-            for i in range(self.proto.persistentTimeOut):
</del><ins>+            for _ignore_i in range(self.proto.persistentTimeOut):
</ins><span class="cx">                 self.clock.advance(1)
</span><span class="cx">             return self.assertFailure(d2, TimeoutError).addCallback(checkTime)
</span><span class="cx">         def checkTime(ignored):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldav__init__py"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/__init__.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/__init__.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/__init__.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -59,12 +59,14 @@
</span><span class="cx"> })
</span><span class="cx"> 
</span><span class="cx"> # Do some PyCalendar init
</span><del>-from pycalendar.calendar import PyCalendar
-from pycalendar.property import PyCalendarProperty
-from pycalendar.value import PyCalendarValue
</del><ins>+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.icalendar.property import Property
+from pycalendar.vcard.card import Card
+from pycalendar.value import Value
</ins><span class="cx"> 
</span><del>-PyCalendar.setPRODID(&quot;-//CALENDARSERVER.ORG//NONSGML Version 1//EN&quot;)
</del><ins>+Calendar.setPRODID(&quot;-//CALENDARSERVER.ORG//NONSGML Version 1//EN&quot;)
+Card.setPRODID(&quot;-//CALENDARSERVER.ORG//NONSGML Version 1//EN&quot;)
</ins><span class="cx"> 
</span><span class="cx"> # These are properties we use directly and we want the default value type set for TEXT
</span><del>-PyCalendarProperty.registerDefaultValue(&quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;, PyCalendarValue.VALUETYPE_TEXT)
-PyCalendarProperty.registerDefaultValue(&quot;X-CALENDARSERVER-ATTENDEE-COMMENT&quot;, PyCalendarValue.VALUETYPE_TEXT)
</del><ins>+Property.registerDefaultValue(&quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;, Value.VALUETYPE_TEXT)
+Property.registerDefaultValue(&quot;X-CALENDARSERVER-ATTENDEE-COMMENT&quot;, Value.VALUETYPE_TEXT)
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavaccountingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/accounting.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/accounting.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/accounting.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -42,6 +42,8 @@
</span><span class="cx">         accountingEnabledForPrincipal(principal)
</span><span class="cx">     )
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def accountingEnabledForCategory(category):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Determine if accounting is enabled for the given category.
</span><span class="lines">@@ -51,6 +53,8 @@
</span><span class="cx">         return False
</span><span class="cx">     return AccountingCategories.get(category, False)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def accountingEnabledForPrincipal(principal):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Determine if accounting is enabled for the given principal.
</span><span class="lines">@@ -69,6 +73,8 @@
</span><span class="cx"> 
</span><span class="cx">     return False
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def emitAccounting(category, principal, data, tag=None):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Write the supplied data to the appropriate location for the given
</span><span class="lines">@@ -80,7 +86,7 @@
</span><span class="cx">     @type category: C{tuple}
</span><span class="cx">     @param data: data to write.
</span><span class="cx">     @type data: C{str}
</span><del>-    &quot;&quot;&quot;    
</del><ins>+    &quot;&quot;&quot;
</ins><span class="cx">     if isinstance(principal, str):
</span><span class="cx">         principalLogPath = principal
</span><span class="cx">     elif accountingEnabled(category, principal):
</span><span class="lines">@@ -107,7 +113,7 @@
</span><span class="cx">             logDirectory,
</span><span class="cx">             datetime.datetime.now().isoformat()
</span><span class="cx">         )
</span><del>-    
</del><ins>+
</ins><span class="cx">         if not os.path.isdir(os.path.join(logRoot, logDirectory)):
</span><span class="cx">             os.makedirs(os.path.join(logRoot, logDirectory))
</span><span class="cx">             logFilename = &quot;%s-01&quot; % (logFilename,)
</span><span class="lines">@@ -128,7 +134,7 @@
</span><span class="cx">                     log.error(&quot;Too many %s accounting files for %s&quot; % (category, principal))
</span><span class="cx">                     return None
</span><span class="cx">                 index += 1
</span><del>-    
</del><ins>+
</ins><span class="cx">         #
</span><span class="cx">         # Now write out the data to the log file
</span><span class="cx">         #
</span><span class="lines">@@ -137,7 +143,7 @@
</span><span class="cx">             logFile.write(data)
</span><span class="cx">         finally:
</span><span class="cx">             logFile.close()
</span><del>-            
</del><ins>+
</ins><span class="cx">         return logFilename
</span><span class="cx"> 
</span><span class="cx">     except OSError, e:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavauthkerbpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/authkerb.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/authkerb.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/authkerb.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> 
</span><span class="cx">     1. An alternative to password based BASIC authentication in which the BASIC credentials are
</span><span class="cx">         verified against Kerberos.
</span><del>-   
</del><ins>+
</ins><span class="cx">     2. The NEGOTIATE mechanism (as defined in http://www.ietf.org/rfc/rfc4559.txt)
</span><span class="cx">         that implements full GSSAPI authentication.
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, principal=None, type=None, hostname=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com@EXAMPLE.COM'). If C{None}
</span><span class="cx">             then the type and hostname arguments are used instead.
</span><span class="cx">         @type service:     str
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.service, self.realm = self._splitPrincipal(principal)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _splitPrincipal(self, principal):
</span><span class="cx"> 
</span><span class="cx">         try:
</span><span class="lines">@@ -93,12 +94,14 @@
</span><span class="cx">         except IndexError:
</span><span class="cx">             self.log.error(&quot;Invalid Kerberos principal: %s&quot; % (principal,))
</span><span class="cx">             raise ValueError('Authentication System Failure: Invalid Kerberos principal: %s' % (principal,))
</span><del>-                
</del><ins>+
</ins><span class="cx">         service = &quot;%s@%s&quot; % (servicetype, service,)
</span><span class="cx">         realm = realm
</span><del>-        
</del><ins>+
</ins><span class="cx">         return (service, realm,)
</span><del>-        
</del><ins>+
+
+
</ins><span class="cx"> class BasicKerberosCredentials(credentials.UsernamePassword):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A set of user/password credentials that checks itself against Kerberos.
</span><span class="lines">@@ -106,7 +109,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, username, password, service, realm):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param username:   user name of user to authenticate
</span><span class="cx">         @type username:    str
</span><span class="cx">         @param password:   password for user being authenticated
</span><span class="lines">@@ -117,11 +120,13 @@
</span><span class="cx">         @type hostname:    str
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         credentials.UsernamePassword.__init__(self, username, password)
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Convert Kerberos principal spec into service and realm
</span><span class="cx">         self.service = service
</span><span class="cx">         self.default_realm = realm
</span><del>-        
</del><ins>+
+
+
</ins><span class="cx"> class BasicKerberosCredentialFactory(KerberosCredentialFactoryBase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Authorizer for insecure Basic (base64-encoded plaintext) authentication.
</span><span class="lines">@@ -134,7 +139,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, principal=None, type=None, hostname=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com@EXAMPLE.COM'). If C{None}
</span><span class="cx">             then the type and hostname arguments are used instead.
</span><span class="cx">         @type service:     str
</span><span class="lines">@@ -146,9 +151,11 @@
</span><span class="cx"> 
</span><span class="cx">         super(BasicKerberosCredentialFactory, self).__init__(principal, type, hostname)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getChallenge(self, _ignore_peer):
</span><span class="cx">         return succeed({'realm': self.realm})
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def decode(self, response, request): #@UnusedVariable
</span><span class="cx">         try:
</span><span class="cx">             creds = (response + '===').decode('base64')
</span><span class="lines">@@ -161,6 +168,8 @@
</span><span class="cx">             return succeed(c)
</span><span class="cx">         raise error.LoginFailed('Invalid credentials')
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class BasicKerberosCredentialsChecker(object):
</span><span class="cx">     log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -187,9 +196,11 @@
</span><span class="cx">                     pcreds.authnPrincipal,
</span><span class="cx">                     pcreds.authzPrincipal,
</span><span class="cx">                 ))
</span><del>-        
</del><ins>+
</ins><span class="cx">         raise error.UnauthorizedLogin(&quot;Bad credentials for: %s&quot; % (pcreds.authnURI,))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class NegotiateCredentials(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A set of user/password credentials that checks itself against Kerberos.
</span><span class="lines">@@ -198,10 +209,12 @@
</span><span class="cx">     implements(credentials.ICredentials)
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, principal, username):
</span><del>-        
</del><ins>+
</ins><span class="cx">         self.principal = principal
</span><span class="cx">         self.username = username
</span><del>-        
</del><ins>+
+
+
</ins><span class="cx"> class NegotiateCredentialFactory(KerberosCredentialFactoryBase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Authorizer for Negotiate authentication (http://www.ietf.org/rfc/rfc4559.txt).
</span><span class="lines">@@ -211,7 +224,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, principal=None, type=None, hostname=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com@EXAMPLE.COM'). If C{None}
</span><span class="cx">             then the type and hostname arguments are used instead.
</span><span class="cx">         @type service:     str
</span><span class="lines">@@ -223,22 +236,24 @@
</span><span class="cx"> 
</span><span class="cx">         super(NegotiateCredentialFactory, self).__init__(principal, type, hostname)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getChallenge(self, _ignore_peer):
</span><span class="cx">         return succeed({})
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def decode(self, base64data, request):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Init GSSAPI first - we won't specify the service now as we need to accept a target
</span><span class="cx">         # name that is case-insenstive as some clients will use &quot;http&quot; instead of &quot;HTTP&quot;
</span><span class="cx">         try:
</span><del>-            _ignore_result, context = kerberos.authGSSServerInit(&quot;&quot;);
</del><ins>+            _ignore_result, context = kerberos.authGSSServerInit(&quot;&quot;)
</ins><span class="cx">         except kerberos.GSSError, ex:
</span><span class="cx">             self.log.error(&quot;authGSSServerInit: %s(%s)&quot; % (ex[0][0], ex[1][0],))
</span><span class="cx">             raise error.LoginFailed('Authentication System Failure: %s(%s)' % (ex[0][0], ex[1][0],))
</span><span class="cx"> 
</span><span class="cx">         # Do the GSSAPI step and get response and username
</span><span class="cx">         try:
</span><del>-            kerberos.authGSSServerStep(context, base64data);
</del><ins>+            kerberos.authGSSServerStep(context, base64data)
</ins><span class="cx">         except kerberos.GSSError, ex:
</span><span class="cx">             self.log.error(&quot;authGSSServerStep: %s(%s)&quot; % (ex[0][0], ex[1][0],))
</span><span class="cx">             kerberos.authGSSServerClean(context)
</span><span class="lines">@@ -264,13 +279,13 @@
</span><span class="cx">         principal = kerberos.authGSSServerUserName(context)
</span><span class="cx">         username = principal
</span><span class="cx">         realmname = &quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Username may include realm suffix which we want to strip
</span><span class="cx">         if username.find(&quot;@&quot;) != -1:
</span><span class="cx">             splits = username.split(&quot;@&quot;, 1)
</span><span class="cx">             username = splits[0]
</span><span class="cx">             realmname = splits[1]
</span><del>-        
</del><ins>+
</ins><span class="cx">         # We currently do not support cross-realm authentication, so we
</span><span class="cx">         # must verify that the realm we got exactly matches the one we expect.
</span><span class="cx">         if realmname != self.realm:
</span><span class="lines">@@ -278,11 +293,11 @@
</span><span class="cx"> 
</span><span class="cx">         # Close the context
</span><span class="cx">         try:
</span><del>-            kerberos.authGSSServerClean(context);
</del><ins>+            kerberos.authGSSServerClean(context)
</ins><span class="cx">         except kerberos.GSSError, ex:
</span><span class="cx">             self.log.error(&quot;authGSSServerClean: %s&quot; % (ex[0][0], ex[1][0],))
</span><span class="cx">             raise error.LoginFailed('Authentication System Failure %s(%s)' % (ex[0][0], ex[1][0],))
</span><del>-        
</del><ins>+
</ins><span class="cx">         # If we successfully decoded and verified the Kerberos credentials we need to add the Kerberos
</span><span class="cx">         # response data to the outgoing request
</span><span class="cx"> 
</span><span class="lines">@@ -299,6 +314,8 @@
</span><span class="cx"> 
</span><span class="cx">         return succeed(NegotiateCredentials(principal, username))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class NegotiateCredentialsChecker(object):
</span><span class="cx"> 
</span><span class="cx">     implements(checkers.ICredentialsChecker)
</span><span class="lines">@@ -320,6 +337,5 @@
</span><span class="cx">                 pcreds.authnPrincipal,
</span><span class="cx">                 pcreds.authzPrincipal,
</span><span class="cx">             ))
</span><del>-        
</del><ins>+
</ins><span class="cx">         raise error.UnauthorizedLogin(&quot;Bad credentials for: %s&quot; % (pcreds.authnURI,))
</span><del>-
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavbackuppy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/backup.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/backup.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/backup.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -38,19 +38,22 @@
</span><span class="cx">         for x in xrange(0, len(argv)):
</span><span class="cx">             opt = argv[x]
</span><span class="cx">             if opt.startswith('-'):
</span><del>-                self[opt.strip('-')] = argv[x+1]
</del><ins>+                self[opt.strip('-')] = argv[x + 1]
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def debug(string):
</span><span class="cx">     if VERBOSE:
</span><span class="cx">         print(&quot;DEBUG:&quot;, string)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def funclog(string):
</span><span class="cx">     if FUNCLOG:
</span><span class="cx">         print(&quot;FUNCLOG:&quot;, string)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def logFuncCall(func):
</span><span class="cx">     def printArgs(args):
</span><span class="cx">         a = []
</span><span class="lines">@@ -60,6 +63,7 @@
</span><span class="cx"> 
</span><span class="cx">         return ''.join(a).strip(', ')
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def printKwargs(kwargs):
</span><span class="cx">         a = []
</span><span class="cx">         for kwarg, value in kwargs:
</span><span class="lines">@@ -67,8 +71,9 @@
</span><span class="cx"> 
</span><span class="cx">         return ''.join(a).strip(', ')
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _(*args, **kwargs):
</span><del>-        funclog(&quot;%s(%s)&quot; % (func.func_name, 
</del><ins>+        funclog(&quot;%s(%s)&quot; % (func.func_name,
</ins><span class="cx">                             ', '.join((printArgs(args),
</span><span class="cx">                                        printKwargs(kwargs))).strip(', ')))
</span><span class="cx"> 
</span><span class="lines">@@ -77,10 +82,11 @@
</span><span class="cx">         funclog(&quot;%s - &gt; %s&quot; % (func.func_name, retval))
</span><span class="cx"> 
</span><span class="cx">         return retval
</span><del>-    
</del><ins>+
</ins><span class="cx">     return _
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def readConfig(configFile):
</span><span class="cx">     config = readPlist(configFile + '.default')
</span><span class="lines">@@ -89,14 +95,16 @@
</span><span class="cx">         config.update(readPlist(configFile))
</span><span class="cx"> 
</span><span class="cx">     return config
</span><del>-        
</del><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def mkroot(path):
</span><span class="cx">     root = '/'.join(path.rstrip('/').split('/')[:-1])
</span><span class="cx">     os.makedirs(root)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def serveradmin(action, service):
</span><span class="cx">     cmd = ' '.join((
</span><span class="lines">@@ -112,6 +120,7 @@
</span><span class="cx">     return status
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def isRunning(service):
</span><span class="cx">     cmd = ' '.join((
</span><span class="lines">@@ -134,21 +143,25 @@
</span><span class="cx">         return False
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def copy(src, dst):
</span><span class="cx">     shutil.copytree(src, dst)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def move(src, dst):
</span><span class="cx">     os.rename(src, dst)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def remove(dst):
</span><span class="cx">     shutil.rmtree(dst)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @logFuncCall
</span><span class="cx"> def purge(root, patterns):
</span><span class="cx">     removed = []
</span><span class="lines">@@ -175,5 +188,5 @@
</span><span class="cx">                     os.remove(full)
</span><span class="cx"> 
</span><span class="cx">                     removed.append(full)
</span><del>-                    
</del><ins>+
</ins><span class="cx">     return removed
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavcaldavxmlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/caldavxml.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/caldavxml.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/caldavxml.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -25,8 +25,8 @@
</span><span class="cx"> See draft spec: http://ietf.webdav.org/caldav/draft-dusseault-caldav.txt
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from txdav.xml.element import registerElement, dav_namespace
</span><span class="cx"> from txdav.xml.element import WebDAVElement, PCDATAElement
</span><span class="lines">@@ -110,8 +110,8 @@
</span><span class="cx">         if &quot;start&quot; not in attributes and &quot;end&quot; not in attributes:
</span><span class="cx">             raise ValueError(&quot;One of 'start' or 'end' must be present in CALDAV:time-range&quot;)
</span><span class="cx"> 
</span><del>-        self.start = PyCalendarDateTime.parseText(attributes[&quot;start&quot;]) if &quot;start&quot; in attributes else None
-        self.end = PyCalendarDateTime.parseText(attributes[&quot;end&quot;]) if &quot;end&quot; in attributes else None
</del><ins>+        self.start = DateTime.parseText(attributes[&quot;start&quot;]) if &quot;start&quot; in attributes else None
+        self.end = DateTime.parseText(attributes[&quot;end&quot;]) if &quot;end&quot; in attributes else None
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def valid(self, level=0):
</span><span class="lines">@@ -139,23 +139,102 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class CalDAVTimeZoneElement (CalDAVTextElement):
</del><ins>+class CalDAVDataMixin(object):
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    CalDAV element containing iCalendar data with a single VTIMEZONE component.
</del><ins>+    A mixin to support accept/returning data in various formats.
</ins><span class="cx">     &quot;&quot;&quot;
</span><ins>+
+    def __init__(self, *children, **attributes):
+
+        if &quot;content-type&quot; in attributes:
+            self.content_type = attributes[&quot;content-type&quot;]
+        else:
+            self.content_type = &quot;text/calendar&quot;
+
+        if &quot;version&quot; in attributes:
+            self.version = attributes[&quot;version&quot;]
+        else:
+            self.version = &quot;2.0&quot;
+
+        super(CalDAVDataMixin, self).__init__(*children, **attributes)
+
+
+    def verifyTypeVersion(self):
+        &quot;&quot;&quot;
+        Make sure any content-type and version matches at least one supported set.
+
+        @return: C{True} if there is at least one match, C{False} otherwise.
+        &quot;&quot;&quot;
+        allowedTypes = set()
+        allowedTypes.add((&quot;text/calendar&quot;, &quot;2.0&quot;,))
+        if config.EnableJSONData:
+            allowedTypes.add((&quot;application/calendar+json&quot;, &quot;2.0&quot;,))
+        for format, version in allowedTypes:
+            if (format == self.content_type) and (version == self.version):
+                return True
+
+        return False
+
+
+    @classmethod
+    def fromCalendar(clazz, calendar, format=None):
+        attrs = {}
+        if format is not None and format != &quot;text/calendar&quot;:
+            attrs[&quot;content-type&quot;] = format
+
+        if isinstance(calendar, str):
+            if not calendar:
+                raise ValueError(&quot;Missing calendar data&quot;)
+            return clazz(PCDATAElement(calendar), **attrs)
+        elif isinstance(calendar, iComponent):
+            assert calendar.name() == &quot;VCALENDAR&quot;, &quot;Not a calendar: %r&quot; % (calendar,)
+            return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference, format=format)), **attrs)
+        else:
+            raise ValueError(&quot;Not a calendar: %s&quot; % (calendar,))
+
+    fromTextData = fromCalendar
+    fromComponent = fromCalendar
+
</ins><span class="cx">     def calendar(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        Returns a calendar component derived from this element, which contains
-        exactly one VTIMEZONE component.
</del><ins>+        Returns a calendar component derived from this element.
</ins><span class="cx">         &quot;&quot;&quot;
</span><del>-        return iComponent.fromString(str(self))
</del><ins>+        data = self.calendarData()
+        if data:
+            return iComponent.fromString(data, format=self.content_type)
+        else:
+            return None
</ins><span class="cx"> 
</span><ins>+    generateComponent = calendar
</ins><span class="cx"> 
</span><ins>+
+    def calendarData(self):
+        &quot;&quot;&quot;
+        Returns the calendar data derived from this element.
+        &quot;&quot;&quot;
+        for data in self.children:
+            if not isinstance(data, PCDATAElement):
+                return None
+            else:
+                # We guaranteed in __init__() that there is only one child...
+                break
+
+        return str(data)
+
+    textData = calendarData
+
+
+
+class CalDAVTimeZoneElement (CalDAVDataMixin, CalDAVTextElement):
+    &quot;&quot;&quot;
+    CalDAV element containing iCalendar data with a single VTIMEZONE component.
+    &quot;&quot;&quot;
+
</ins><span class="cx">     def gettimezone(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get the timezone to use. If none, return UTC timezone.
</span><span class="cx"> 
</span><del>-        @return: the L{PyCalendarTimezone} derived from the VTIMEZONE or utc.
</del><ins>+        @return: the L{Timezone} derived from the VTIMEZONE or utc.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         calendar = self.calendar()
</span><span class="cx">         if calendar is not None:
</span><span class="lines">@@ -164,7 +243,7 @@
</span><span class="cx">                 return tz
</span><span class="cx"> 
</span><span class="cx">         # Default to using utc tzinfo
</span><del>-        return PyCalendarTimezone(utc=True)
</del><ins>+        return Timezone(utc=True)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def valid(self):
</span><span class="lines">@@ -231,8 +310,13 @@
</span><span class="cx">     name = &quot;calendar-timezone&quot;
</span><span class="cx">     hidden = True
</span><span class="cx"> 
</span><ins>+    allowed_attributes = {
+        &quot;content-type&quot;: False,
+        &quot;version&quot;     : False,
+    }
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class SupportedCalendarComponentSets (CalDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -428,7 +512,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> @registerElement
</span><del>-class CalendarData (CalDAVElement):
</del><ins>+class CalendarData (CalDAVDataMixin, CalDAVElement):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Defines which parts of a calendar component object should be returned by a
</span><span class="cx">     report.
</span><span class="lines">@@ -448,21 +532,6 @@
</span><span class="cx">         &quot;version&quot;     : False,
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    @classmethod
-    def fromCalendar(clazz, calendar):
-        if isinstance(calendar, str):
-            if not calendar:
-                raise ValueError(&quot;Missing calendar data&quot;)
-            return clazz(PCDATAElement(calendar))
-        elif isinstance(calendar, iComponent):
-            assert calendar.name() == &quot;VCALENDAR&quot;, &quot;Not a calendar: %r&quot; % (calendar,)
-            return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference)))
-        else:
-            raise ValueError(&quot;Not a calendar: %s&quot; % (calendar,))
-
-    fromTextData = fromCalendar
-
-
</del><span class="cx">     def __init__(self, *children, **attributes):
</span><span class="cx">         super(CalendarData, self).__init__(*children, **attributes)
</span><span class="cx"> 
</span><span class="lines">@@ -515,61 +584,8 @@
</span><span class="cx">                 # optimize them originals away
</span><span class="cx">                 self.children = (data,)
</span><span class="cx"> 
</span><del>-        if &quot;content-type&quot; in attributes:
-            self.content_type = attributes[&quot;content-type&quot;]
-        else:
-            self.content_type = &quot;text/calendar&quot;
</del><span class="cx"> 
</span><del>-        if &quot;version&quot; in attributes:
-            self.version = attributes[&quot;version&quot;]
-        else:
-            self.version = &quot;2.0&quot;
</del><span class="cx"> 
</span><del>-
-    def verifyTypeVersion(self, types_and_versions):
-        &quot;&quot;&quot;
-        Make sure any content-type and version matches at least one of the supplied set.
-
-        @param types_and_versions: a list of (content-type, version) tuples to test against.
-        @return:                   True if there is at least one match, False otherwise.
-        &quot;&quot;&quot;
-        for item in types_and_versions:
-            if (item[0] == self.content_type) and (item[1] == self.version):
-                return True
-
-        return False
-
-
-    def calendar(self):
-        &quot;&quot;&quot;
-        Returns a calendar component derived from this element.
-        &quot;&quot;&quot;
-        data = self.calendarData()
-        if data:
-            return iComponent.fromString(data)
-        else:
-            return None
-
-    generateComponent = calendar
-
-
-    def calendarData(self):
-        &quot;&quot;&quot;
-        Returns the calendar data derived from this element.
-        &quot;&quot;&quot;
-        for data in self.children:
-            if not isinstance(data, PCDATAElement):
-                return None
-            else:
-                # We guaranteed in __init__() that there is only one child...
-                break
-
-        return str(data)
-
-    textData = calendarData
-
-
-
</del><span class="cx"> @registerElement
</span><span class="cx"> class CalendarComponent (CalDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -882,8 +898,13 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;timezone&quot;
</span><span class="cx"> 
</span><ins>+    allowed_attributes = {
+        &quot;content-type&quot;: False,
+        &quot;version&quot;     : False,
+    }
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class TimeRange (CalDAVTimeRangeElement):
</span><span class="cx">     &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavcarddavxmlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/carddavxml.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/carddavxml.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/carddavxml.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> This API is considered private to static.py and is therefore subject to
</span><span class="cx"> change.
</span><span class="cx"> 
</span><del>-See draft spec: 
</del><ins>+See draft spec:
</ins><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx"> from txdav.xml.element import registerElement, dav_namespace
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> from txdav.xml.element import WebDAVEmptyElement, WebDAVTextElement
</span><span class="cx"> from txdav.xml.element import ResourceType, Collection
</span><span class="cx"> 
</span><ins>+from twistedcaldav.config import config
</ins><span class="cx"> from twistedcaldav.vcard import Component
</span><span class="cx"> 
</span><span class="cx"> ##
</span><span class="lines">@@ -50,6 +51,7 @@
</span><span class="cx">     namespace = carddav_namespace
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class CardDAVEmptyElement (WebDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CardDAV element with no contents.
</span><span class="lines">@@ -57,6 +59,7 @@
</span><span class="cx">     namespace = carddav_namespace
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class CardDAVTextElement (WebDAVTextElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CardDAV element containing PCDATA.
</span><span class="lines">@@ -64,6 +67,93 @@
</span><span class="cx">     namespace = carddav_namespace
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
+class CardDAVDataMixin(object):
+    &quot;&quot;&quot;
+    A mixin to support accept/returning data in various formats.
+    &quot;&quot;&quot;
+
+    def __init__(self, *children, **attributes):
+
+        if &quot;content-type&quot; in attributes:
+            self.content_type = attributes[&quot;content-type&quot;]
+        else:
+            self.content_type = &quot;text/vcard&quot;
+
+        if &quot;version&quot; in attributes:
+            self.version = attributes[&quot;version&quot;]
+        else:
+            self.version = &quot;3.0&quot;
+
+        super(CardDAVDataMixin, self).__init__(*children, **attributes)
+
+
+    def verifyTypeVersion(self):
+        &quot;&quot;&quot;
+        Make sure any content-type and version matches at least one supported set.
+
+        @return: C{True} if there is at least one match, C{False} otherwise.
+        &quot;&quot;&quot;
+        allowedTypes = set()
+        allowedTypes.add((&quot;text/vcard&quot;, &quot;3.0&quot;,))
+        if config.EnableJSONData:
+            allowedTypes.add((&quot;application/vcard+json&quot;, &quot;3.0&quot;,))
+        for format, version in allowedTypes:
+            if (format == self.content_type) and (version == self.version):
+                return True
+
+        return False
+
+
+    @classmethod
+    def fromAddress(clazz, address, format=None):
+        attrs = {}
+        if format is not None and format != &quot;text/vcard&quot;:
+            attrs[&quot;content-type&quot;] = format
+
+        if isinstance(address, str):
+            if not address:
+                raise ValueError(&quot;Missing address data&quot;)
+            return clazz(PCDATAElement(address), **attrs)
+        elif isinstance(address, Component):
+            assert address.name() == &quot;VCARD&quot;, &quot;Not a vCard: %r&quot; % (address,)
+            return clazz(PCDATAElement(address.getText(format)), **attrs)
+        else:
+            raise ValueError(&quot;Not an address: %s&quot; % (address,))
+
+    fromTextData = fromAddress
+    fromComponent = fromAddress
+
+    def address(self):
+        &quot;&quot;&quot;
+        Returns an address component derived from this element.
+        &quot;&quot;&quot;
+        data = self.addressData()
+        if data:
+            return Component.fromString(data, format=self.content_type)
+        else:
+            return None
+
+    generateComponent = address
+
+
+    def addressData(self):
+        &quot;&quot;&quot;
+        Returns the address data derived from this element.
+        &quot;&quot;&quot;
+        for data in self.children:
+            if not isinstance(data, PCDATAElement):
+                return None
+            else:
+                # We guaranteed in __init__() that there is only one child...
+                break
+
+        return str(data)
+
+    textData = addressData
+
+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressBookHomeSet (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -73,9 +163,10 @@
</span><span class="cx">     name = &quot;addressbook-home-set&quot;
</span><span class="cx">     hidden = True
</span><span class="cx"> 
</span><del>-    allowed_children = { (dav_namespace, &quot;href&quot;): (0, None) }
</del><ins>+    allowed_children = {(dav_namespace, &quot;href&quot;): (0, None)}
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressBookDescription (CardDAVTextElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -88,6 +179,7 @@
</span><span class="cx">     # May be protected; but we'll let the client set this if they like.
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class SupportedAddressData (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -98,9 +190,10 @@
</span><span class="cx">     hidden = True
</span><span class="cx">     protected = True
</span><span class="cx"> 
</span><del>-    allowed_children = { (carddav_namespace, &quot;address-data-type&quot;): (0, None) }
</del><ins>+    allowed_children = {(carddav_namespace, &quot;address-data-type&quot;): (0, None)}
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class MaxResourceSize (CardDAVTextElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -112,6 +205,7 @@
</span><span class="cx">     protected = True
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressBook (CardDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -121,6 +215,7 @@
</span><span class="cx">     name = &quot;addressbook&quot;
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressBookQuery (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -130,11 +225,11 @@
</span><span class="cx">     name = &quot;addressbook-query&quot;
</span><span class="cx"> 
</span><span class="cx">     allowed_children = {
</span><del>-        (dav_namespace,     &quot;allprop&quot; ): (0, None),
-        (dav_namespace,     &quot;propname&quot;): (0, None),
-        (dav_namespace,     &quot;prop&quot;    ): (0, None),
-        (carddav_namespace, &quot;filter&quot;  ): (0, 1), # Actually (1, 1) unless element is empty
-        (carddav_namespace, &quot;limit&quot;    ): (0, None),
</del><ins>+        (dav_namespace, &quot;allprop&quot;): (0, None),
+        (dav_namespace, &quot;propname&quot;): (0, None),
+        (dav_namespace, &quot;prop&quot;): (0, None),
+        (carddav_namespace, &quot;filter&quot;): (0, 1), # Actually (1, 1) unless element is empty
+        (carddav_namespace, &quot;limit&quot;): (0, None),
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, *children, **attributes):
</span><span class="lines">@@ -148,9 +243,9 @@
</span><span class="cx">             qname = child.qname()
</span><span class="cx"> 
</span><span class="cx">             if qname in (
</span><del>-                (dav_namespace, &quot;allprop&quot; ),
</del><ins>+                (dav_namespace, &quot;allprop&quot;),
</ins><span class="cx">                 (dav_namespace, &quot;propname&quot;),
</span><del>-                (dav_namespace, &quot;prop&quot;    ),
</del><ins>+                (dav_namespace, &quot;prop&quot;),
</ins><span class="cx">             ):
</span><span class="cx">                 if props is not None:
</span><span class="cx">                     raise ValueError(&quot;Only one of CardDAV:allprop, CardDAV:propname, CardDAV:prop allowed&quot;)
</span><span class="lines">@@ -159,7 +254,7 @@
</span><span class="cx">             elif qname == (carddav_namespace, &quot;filter&quot;):
</span><span class="cx">                 filter = child
</span><span class="cx">             elif qname == (carddav_namespace, &quot;limit&quot;):
</span><del>-                # type check 
</del><ins>+                # type check
</ins><span class="cx">                 child.childOfType(NResults)
</span><span class="cx">                 limit = child
</span><span class="cx"> 
</span><span class="lines">@@ -170,11 +265,12 @@
</span><span class="cx">             if filter is None:
</span><span class="cx">                 raise ValueError(&quot;CARDDAV:filter required&quot;)
</span><span class="cx"> 
</span><del>-        self.props  = props
</del><ins>+        self.props = props
</ins><span class="cx">         self.filter = filter
</span><span class="cx">         self.limit = limit
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressDataType (CardDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -190,8 +286,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><del>-class AddressData (CardDAVElement):
</del><ins>+class AddressData (CardDAVDataMixin, CardDAVElement):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Defines which parts of a address component object should be returned by a
</span><span class="cx">     report.
</span><span class="lines">@@ -201,7 +298,7 @@
</span><span class="cx"> 
</span><span class="cx">     allowed_children = {
</span><span class="cx">         (carddav_namespace, &quot;allprop&quot;): (0, 1),
</span><del>-        (carddav_namespace, &quot;prop&quot;   ): (0, None),
</del><ins>+        (carddav_namespace, &quot;prop&quot;): (0, None),
</ins><span class="cx">         PCDATAElement                 : (0, None),
</span><span class="cx">     }
</span><span class="cx">     allowed_attributes = {
</span><span class="lines">@@ -209,27 +306,11 @@
</span><span class="cx">         &quot;version&quot;     : False,
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    @classmethod
-    def fromAddress(clazz, address):
-        assert address.name() == &quot;VCARD&quot;, &quot;Not a vCard: %r&quot; % (address,)
-        return clazz(PCDATAElement(str(address)))
-
-    @classmethod
-    def fromAddressData(clazz, addressdata):
-        &quot;&quot;&quot;
-        Return a AddressData element comprised of the supplied address data.
-        @param addressdata: a string of valid address data.
-        @return: a L{Addressata} element.
-        &quot;&quot;&quot;
-        return clazz(PCDATAElement(addressdata))
-
-    fromTextData = fromAddressData
-
</del><span class="cx">     def __init__(self, *children, **attributes):
</span><span class="cx">         super(AddressData, self).__init__(*children, **attributes)
</span><span class="cx"> 
</span><span class="cx">         properties = None
</span><del>-        data       = None
</del><ins>+        data = None
</ins><span class="cx"> 
</span><span class="cx">         for child in self.children:
</span><span class="cx">             qname = child.qname()
</span><span class="lines">@@ -256,73 +337,25 @@
</span><span class="cx">                 else:
</span><span class="cx">                     data += child
</span><span class="cx"> 
</span><del>-            else: raise AssertionError(&quot;We shouldn't be here&quot;)
</del><ins>+            else:
+                raise AssertionError(&quot;We shouldn't be here&quot;)
</ins><span class="cx"> 
</span><del>-
</del><span class="cx">         self.properties = properties
</span><span class="cx"> 
</span><span class="cx">         if data is not None:
</span><span class="cx">             try:
</span><span class="cx">                 if properties is not None:
</span><del>-                    raise ValueError(&quot;Only one of allprop, prop (%r) or PCDATA (%r) allowed&quot;% (properties, str(data)))
</del><ins>+                    raise ValueError(&quot;Only one of allprop, prop (%r) or PCDATA (%r) allowed&quot; % (properties, str(data)))
</ins><span class="cx">             except ValueError:
</span><del>-                if not data.isWhitespace(): raise
</del><ins>+                if not data.isWhitespace():
+                    raise
</ins><span class="cx">             else:
</span><span class="cx">                 # Since we've already combined PCDATA elements, we'd may as well
</span><span class="cx">                 # optimize them originals away
</span><span class="cx">                 self.children = (data,)
</span><span class="cx"> 
</span><del>-        if &quot;content-type&quot; in attributes:
-            self.content_type = attributes[&quot;content-type&quot;]
-        else:
-            self.content_type = &quot;text/vcard&quot;
</del><span class="cx"> 
</span><del>-        if &quot;version&quot; in attributes:
-            self.version = attributes[&quot;version&quot;]
-        else:
-            self.version = &quot;3.0&quot;
</del><span class="cx"> 
</span><del>-    def verifyTypeVersion(self, types_and_versions):
-        &quot;&quot;&quot;
-        Make sure any content-type and version matches at least one of the supplied set.
-        
-        @param types_and_versions: a list of (content-type, version) tuples to test against.
-        @return:                   True if there is at least one match, False otherwise.
-        &quot;&quot;&quot;
-        for item in types_and_versions:
-            if (item[0] == self.content_type) and (item[1] == self.version):
-                return True
-        
-        return False
-
-    def address(self):
-        &quot;&quot;&quot;
-        Returns an address component derived from this element.
-        &quot;&quot;&quot;
-        data = self.addressData()
-        if data:
-            return Component.fromString(data)
-        else:
-            return None
-
-    generateComponent = address
-
-    def addressData(self):
-        &quot;&quot;&quot;
-        Returns an address component derived from this element.
-        &quot;&quot;&quot;
-        for data in self.children:
-            if not isinstance(data, PCDATAElement):
-                return None
-            else:
-                # We guaranteed in __init__() that there is only one child...
-                break
-
-        return str(data)
-
-    textData = addressData
-
-
</del><span class="cx"> @registerElement
</span><span class="cx"> class AllProperties (CardDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -332,6 +365,7 @@
</span><span class="cx">     name = &quot;allprop&quot;
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class Property (CardDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -362,6 +396,7 @@
</span><span class="cx">             self.novalue = False
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class Filter (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -370,10 +405,11 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;filter&quot;
</span><span class="cx"> 
</span><del>-    allowed_children = { (carddav_namespace, &quot;prop-filter&quot;): (0, None) }
-    allowed_attributes = { &quot;test&quot;: False }
-        
</del><ins>+    allowed_children = {(carddav_namespace, &quot;prop-filter&quot;): (0, None)}
+    allowed_attributes = {&quot;test&quot;: False}
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class PropertyFilter (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -383,9 +419,9 @@
</span><span class="cx">     name = &quot;prop-filter&quot;
</span><span class="cx"> 
</span><span class="cx">     allowed_children = {
</span><del>-        (carddav_namespace, &quot;is-not-defined&quot; ): (0, 1),
-        (carddav_namespace, &quot;text-match&quot;     ): (0, None),
-        (carddav_namespace, &quot;param-filter&quot;   ): (0, None),
</del><ins>+        (carddav_namespace, &quot;is-not-defined&quot;): (0, 1),
+        (carddav_namespace, &quot;text-match&quot;): (0, None),
+        (carddav_namespace, &quot;param-filter&quot;): (0, None),
</ins><span class="cx">     }
</span><span class="cx">     allowed_attributes = {
</span><span class="cx">         &quot;name&quot;: True,
</span><span class="lines">@@ -393,6 +429,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class ParameterFilter (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -402,12 +439,13 @@
</span><span class="cx">     name = &quot;param-filter&quot;
</span><span class="cx"> 
</span><span class="cx">     allowed_children = {
</span><del>-        (carddav_namespace, &quot;is-not-defined&quot; ): (0, 1),
-        (carddav_namespace, &quot;text-match&quot;     ): (0, 1),
</del><ins>+        (carddav_namespace, &quot;is-not-defined&quot;): (0, 1),
+        (carddav_namespace, &quot;text-match&quot;): (0, 1),
</ins><span class="cx">     }
</span><del>-    allowed_attributes = { &quot;name&quot;: True }
</del><ins>+    allowed_attributes = {&quot;name&quot;: True}
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class Limit (WebDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -416,10 +454,11 @@
</span><span class="cx">     namespace = carddav_namespace
</span><span class="cx">     name = &quot;limit&quot;
</span><span class="cx">     allowed_children = {
</span><del>-        (carddav_namespace, &quot;nresults&quot; )  : (1, 1),
</del><ins>+        (carddav_namespace, &quot;nresults&quot;)  : (1, 1),
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class NResults (WebDAVTextElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -439,6 +478,7 @@
</span><span class="cx">     name = &quot;is-not-defined&quot;
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class TextMatch (CardDAVTextElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -464,6 +504,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class AddressBookMultiGet (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -475,10 +516,10 @@
</span><span class="cx">     # To allow for an empty element in a supported-report-set property we need
</span><span class="cx">     # to relax the child restrictions
</span><span class="cx">     allowed_children = {
</span><del>-        (dav_namespace, &quot;allprop&quot; ): (0, 1),
</del><ins>+        (dav_namespace, &quot;allprop&quot;): (0, 1),
</ins><span class="cx">         (dav_namespace, &quot;propname&quot;): (0, 1),
</span><del>-        (dav_namespace, &quot;prop&quot;    ): (0, 1),
-        (dav_namespace, &quot;href&quot;    ): (0, None),    # Actually ought to be (1, None)
</del><ins>+        (dav_namespace, &quot;prop&quot;): (0, 1),
+        (dav_namespace, &quot;href&quot;): (0, None),    # Actually ought to be (1, None)
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, *children, **attributes):
</span><span class="lines">@@ -491,9 +532,9 @@
</span><span class="cx">             qname = child.qname()
</span><span class="cx"> 
</span><span class="cx">             if qname in (
</span><del>-                (dav_namespace, &quot;allprop&quot; ),
</del><ins>+                (dav_namespace, &quot;allprop&quot;),
</ins><span class="cx">                 (dav_namespace, &quot;propname&quot;),
</span><del>-                (dav_namespace, &quot;prop&quot;    ),
</del><ins>+                (dav_namespace, &quot;prop&quot;),
</ins><span class="cx">             ):
</span><span class="cx">                 if property is not None:
</span><span class="cx">                     raise ValueError(&quot;Only one of DAV:allprop, DAV:propname, DAV:prop allowed&quot;)
</span><span class="lines">@@ -502,10 +543,11 @@
</span><span class="cx">             elif qname == (dav_namespace, &quot;href&quot;):
</span><span class="cx">                 resources.append(child)
</span><span class="cx"> 
</span><del>-        self.property  = property
</del><ins>+        self.property = property
</ins><span class="cx">         self.resources = resources
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class NoUIDConflict(CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -514,9 +556,10 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;no-uid-conflict&quot;
</span><span class="cx"> 
</span><del>-    allowed_children = { (dav_namespace, &quot;href&quot;): (1, 1) }
-    
</del><ins>+    allowed_children = {(dav_namespace, &quot;href&quot;): (1, 1)}
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class SupportedFilter(CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -527,11 +570,12 @@
</span><span class="cx">     name = &quot;supported-filter&quot;
</span><span class="cx"> 
</span><span class="cx">     allowed_children = {
</span><del>-        (carddav_namespace, &quot;prop-filter&quot; ): (0, None),
</del><ins>+        (carddav_namespace, &quot;prop-filter&quot;): (0, None),
</ins><span class="cx">         (carddav_namespace, &quot;param-filter&quot;): (0, None)
</span><span class="cx">     }
</span><del>-    
</del><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class DirectoryGateway(CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -541,17 +585,19 @@
</span><span class="cx">     hidden = True
</span><span class="cx">     protected = True
</span><span class="cx"> 
</span><del>-    allowed_children = { (dav_namespace, &quot;href&quot;): (0, None) }
-    
</del><ins>+    allowed_children = {(dav_namespace, &quot;href&quot;): (0, None)}
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class Directory(CardDAVEmptyElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CardDAV property on a principal to indicate where the directory resource is.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;directory&quot;
</span><del>-    
</del><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class DefaultAddressBookURL (CardDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -559,14 +605,17 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;default-addressbook-URL&quot;
</span><span class="cx"> 
</span><del>-    allowed_children = { (dav_namespace, &quot;href&quot;): (0, 1) }
</del><ins>+    allowed_children = {(dav_namespace, &quot;href&quot;): (0, 1)}
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> ##
</span><span class="cx"> # Extensions to ResourceType
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-def _isAddressBook(self): return bool(self.childrenOfType(AddressBook))
</del><ins>+def _isAddressBook(self):
+    return bool(self.childrenOfType(AddressBook))
</ins><span class="cx"> ResourceType.isAddressBook = _isAddressBook
</span><span class="cx"> 
</span><span class="cx"> ResourceType.addressbook = ResourceType(Collection(), AddressBook())
</span><del>-ResourceType.directory   = ResourceType(Collection(), AddressBook(), Directory())
</del><ins>+ResourceType.directory = ResourceType(Collection(), AddressBook(), Directory())
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavcustomxmlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/customxml.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/customxml.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/customxml.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> from twistedcaldav.caldavxml import caldav_namespace
</span><span class="cx"> from twistedcaldav.ical import Component as iComponent
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> calendarserver_namespace = &quot;http://calendarserver.org/ns/&quot;
</span><span class="lines">@@ -640,7 +640,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, *children):
</span><span class="cx">         super(DTStamp, self).__init__(children)
</span><del>-        self.children = (PCDATAElement(PyCalendarDateTime.getNowUTC().getText()),)
</del><ins>+        self.children = (PCDATAElement(DateTime.getNowUTC().getText()),)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdatabasepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/database.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/database.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/database.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -44,14 +44,15 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A ThreadPool that closes connections for each worker thread
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     def _worker(self):
</span><span class="cx">         log.debug(&quot;Starting ADBAPI thread: %s&quot; % (thread.get_ident(),))
</span><span class="cx">         ThreadPool._worker(self)
</span><span class="cx">         self._closeConnection()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _closeConnection(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         tid = thread.get_ident()
</span><span class="cx">         log.debug(&quot;Closing ADBAPI thread: %s&quot; % (tid,))
</span><span class="cx"> 
</span><span class="lines">@@ -59,6 +60,8 @@
</span><span class="cx">         self.pool._close(conn)
</span><span class="cx">         del self.pool.connections[tid]
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class AbstractADBAPIDatabase(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A generic SQL database.
</span><span class="lines">@@ -66,7 +69,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, dbID, dbapiName, dbapiArgs, persistent, **kwargs):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param persistent: C{True} if the data in the DB must be perserved during upgrades,
</span><span class="cx">             C{False} if the DB data can be re-created from an external source.
</span><span class="cx">         @type persistent: bool
</span><span class="lines">@@ -77,12 +80,14 @@
</span><span class="cx">         self.dbapikwargs = kwargs
</span><span class="cx"> 
</span><span class="cx">         self.persistent = persistent
</span><del>-        
</del><ins>+
</ins><span class="cx">         self.initialized = False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def __repr__(self):
</span><span class="cx">         return &quot;&lt;%s %r&gt;&quot; % (self.__class__.__name__, self.pool)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def open(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -92,7 +97,7 @@
</span><span class="cx">         if not self.initialized:
</span><span class="cx"> 
</span><span class="cx">             self.pool = ConnectionPool(self.dbapiName, *self.dbapiArgs, **self.dbapikwargs)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # sqlite3 is not thread safe which means we have to close the sqlite3 connections in the same thread that
</span><span class="cx">             # opened them. We need a special thread pool class that has a thread worker function that does a close
</span><span class="cx">             # when a thread is closed.
</span><span class="lines">@@ -126,7 +131,7 @@
</span><span class="cx">                         elif version != self._db_version():
</span><span class="cx">                             log.error(&quot;Database %s has different schema (v.%s vs. v.%s)&quot;
</span><span class="cx">                                       % (self.dbID, version, self._db_version()))
</span><del>-                            
</del><ins>+
</ins><span class="cx">                             # Upgrade the DB
</span><span class="cx">                             yield self._db_upgrade(version)
</span><span class="cx"> 
</span><span class="lines">@@ -139,8 +144,9 @@
</span><span class="cx">                 self.pool = None
</span><span class="cx">                 raise
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def close(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         if self.initialized:
</span><span class="cx">             try:
</span><span class="cx">                 self.pool.close()
</span><span class="lines">@@ -149,9 +155,10 @@
</span><span class="cx">             self.pool = None
</span><span class="cx">             self.initialized = False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def clean(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="lines">@@ -165,14 +172,15 @@
</span><span class="cx">             else:
</span><span class="cx">                 break
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def execute(self, sql, *query_params):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="cx">                 yield self.open()
</span><del>-    
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 yield self._db_execute(sql, *query_params)
</span><span class="cx">             except Exception, e:
</span><span class="lines">@@ -181,14 +189,15 @@
</span><span class="cx">             else:
</span><span class="cx">                 break
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def executescript(self, script):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="cx">                 yield self.open()
</span><del>-    
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 yield self._db_execute_script(script)
</span><span class="cx">             except Exception, e:
</span><span class="lines">@@ -197,14 +206,15 @@
</span><span class="cx">             else:
</span><span class="cx">                 break
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def query(self, sql, *query_params):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="cx">                 yield self.open()
</span><del>-    
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 result = (yield self._db_all_values_for_sql(sql, *query_params))
</span><span class="cx">             except Exception, e:
</span><span class="lines">@@ -215,14 +225,15 @@
</span><span class="cx"> 
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def queryList(self, sql, *query_params):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="cx">                 yield self.open()
</span><del>-            
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 result = (yield self._db_values_for_sql(sql, *query_params))
</span><span class="cx">             except Exception, e:
</span><span class="lines">@@ -233,14 +244,15 @@
</span><span class="cx"> 
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def queryOne(self, sql, *query_params):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Re-try at least once
</span><span class="cx">         for _ignore in (0, 1):
</span><span class="cx">             if not self.initialized:
</span><span class="cx">                 yield self.open()
</span><del>-    
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 result = (yield self._db_value_for_sql(sql, *query_params))
</span><span class="cx">             except Exception, e:
</span><span class="lines">@@ -251,21 +263,25 @@
</span><span class="cx"> 
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_version(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the schema version assigned to this DB.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _db_type(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the collection type assigned to this DB.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _test_schema_table(self):
</span><span class="cx">         return self._test_table(&quot;CALDAV&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_init(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -275,12 +291,12 @@
</span><span class="cx"> 
</span><span class="cx">         # TODO we need an exclusive lock of some kind here to prevent a race condition
</span><span class="cx">         # in which multiple processes try to create the tables.
</span><del>-        
</del><span class="cx"> 
</span><span class="cx">         yield self._db_init_schema_table()
</span><span class="cx">         yield self._db_init_data_tables()
</span><span class="cx">         yield self._db_recreate()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_init_schema_table(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -310,12 +326,14 @@
</span><span class="cx">             &quot;&quot;&quot;, (self._db_type(),)
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_init_data_tables(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Initialise the underlying database tables.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_empty_data_tables(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Delete the database tables.
</span><span class="lines">@@ -323,7 +341,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Implementations can override this to re-create data
</span><span class="cx">         pass
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _db_recreate(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Recreate the database tables.
</span><span class="lines">@@ -332,12 +351,13 @@
</span><span class="cx">         # Implementations can override this to re-create data
</span><span class="cx">         pass
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_upgrade(self, old_version):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the database tables.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if self.persistent:
</span><span class="cx">             yield self._db_upgrade_data_tables(old_version)
</span><span class="cx">             yield self._db_upgrade_schema()
</span><span class="lines">@@ -346,7 +366,8 @@
</span><span class="cx">             # DB upgrades they SHOULD override this method and handle those for better performance.
</span><span class="cx">             yield self._db_remove()
</span><span class="cx">             yield self._db_init()
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def _db_upgrade_data_tables(self, old_version):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the data from an older version of the DB.
</span><span class="lines">@@ -372,12 +393,14 @@
</span><span class="cx">         yield self._db_remove_data_tables()
</span><span class="cx">         yield self._db_remove_schema()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_remove_data_tables(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Remove all the data from an older version of the DB.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError(&quot;Each database must remove its own tables.&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_remove_schema(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -385,6 +408,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         yield self._db_execute(&quot;drop table if exists CALDAV&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_all_values_for_sql(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -395,11 +419,12 @@
</span><span class="cx">             resulting from executing C{sql} with C{query_params}.
</span><span class="cx">         @raise AssertionError: if the query yields multiple columns.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         sql = self._prepare_statement(sql)
</span><span class="cx">         results = (yield self.pool.runQuery(sql, *query_params))
</span><span class="cx">         returnValue(tuple(results))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_values_for_sql(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -411,11 +436,12 @@
</span><span class="cx">             resulting from executing C{sql} with C{query_params}.
</span><span class="cx">         @raise AssertionError: if the query yields multiple columns.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         sql = self._prepare_statement(sql)
</span><span class="cx">         results = (yield self.pool.runQuery(sql, *query_params))
</span><span class="cx">         returnValue(tuple([row[0] for row in results]))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _db_value_for_sql(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -433,6 +459,7 @@
</span><span class="cx">             value = row
</span><span class="cx">         returnValue(value)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_execute(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute an SQL operation that returns None.
</span><span class="lines">@@ -442,7 +469,7 @@
</span><span class="cx">         @return: an iterable of tuples for each row resulting from executing
</span><span class="cx">             C{sql} with C{query_params}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         sql = self._prepare_statement(sql)
</span><span class="cx">         return self.pool.runOperation(sql, *query_params)
</span><span class="cx"> 
</span><span class="lines">@@ -450,37 +477,43 @@
</span><span class="cx">     Since different databases support different types of columns and modifiers on those we need to
</span><span class="cx">     have an &quot;abstract&quot; way of specifying columns in our code and then map the abstract specifiers to
</span><span class="cx">     the underlying DB's allowed types.
</span><del>-    
</del><ins>+
</ins><span class="cx">     Types we can use are:
</span><del>-    
</del><ins>+
</ins><span class="cx">     integer
</span><span class="cx">     text
</span><span class="cx">     text(n)
</span><span class="cx">     date
</span><span class="cx">     serial
</span><del>-    
</del><ins>+
</ins><span class="cx">     The &quot; unique&quot; modifier can be appended to any of those.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def _map_column_types(self, type):
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _create_table(self, name, columns, ifnotexists=False):
</span><span class="cx">         raise NotImplementedError
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _test_table(self, name):
</span><span class="cx">         raise NotImplementedError
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _create_index(self, name, ontable, columns, ifnotexists=False):
</span><span class="cx">         raise NotImplementedError
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _prepare_statement(self, sql):
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
+
</ins><span class="cx"> class ADBAPISqliteMixin(object):
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><span class="cx">     def _map_column_types(self, coltype):
</span><del>-        
</del><ins>+
</ins><span class="cx">         result = &quot;&quot;
</span><span class="cx">         splits = coltype.split()
</span><span class="cx">         if splits[0] == &quot;integer&quot;:
</span><span class="lines">@@ -493,15 +526,16 @@
</span><span class="cx">             result = &quot;date&quot;
</span><span class="cx">         elif splits[0] == &quot;serial&quot;:
</span><span class="cx">             result = &quot;integer primary key autoincrement&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if len(splits) &gt; 1 and splits[1] == &quot;unique&quot;:
</span><span class="cx">             result += &quot; unique&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         return result
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _create_table(self, name, columns, ifnotexists=False):
</span><del>-        
</del><ins>+
</ins><span class="cx">         colDefs = [&quot;%s %s&quot; % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
</span><span class="cx">         statement = &quot;create table %s%s (%s)&quot; % (
</span><span class="cx">             &quot;if not exists &quot; if ifnotexists else &quot;&quot;,
</span><span class="lines">@@ -510,6 +544,7 @@
</span><span class="cx">         )
</span><span class="cx">         yield self._db_execute(statement)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _test_table(self, name):
</span><span class="cx">         result = (yield self._db_value_for_sql(&quot;&quot;&quot;
</span><span class="lines">@@ -518,9 +553,10 @@
</span><span class="cx">         &quot;&quot;&quot; % (name,)))
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _create_index(self, name, ontable, columns, ifnotexists=False):
</span><del>-        
</del><ins>+
</ins><span class="cx">         statement = &quot;create index %s%s on %s (%s)&quot; % (
</span><span class="cx">             &quot;if not exists &quot; if ifnotexists else &quot;&quot;,
</span><span class="cx">             name,
</span><span class="lines">@@ -529,6 +565,7 @@
</span><span class="cx">         )
</span><span class="cx">         yield self._db_execute(statement)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _prepare_statement(self, sql):
</span><span class="cx">         # We are going to use the sqlite syntax of :1, :2 etc for our
</span><span class="cx">         # internal statements so we do not need to remap those
</span><span class="lines">@@ -537,10 +574,10 @@
</span><span class="cx"> if pgdb:
</span><span class="cx"> 
</span><span class="cx">     class ADBAPIPostgreSQLMixin(object):
</span><del>-        
</del><ins>+
</ins><span class="cx">         @classmethod
</span><span class="cx">         def _map_column_types(self, coltype):
</span><del>-            
</del><ins>+
</ins><span class="cx">             result = &quot;&quot;
</span><span class="cx">             splits = coltype.split()
</span><span class="cx">             if splits[0] == &quot;integer&quot;:
</span><span class="lines">@@ -553,32 +590,34 @@
</span><span class="cx">                 result = &quot;date&quot;
</span><span class="cx">             elif splits[0] == &quot;serial&quot;:
</span><span class="cx">                 result = &quot;serial&quot;
</span><del>-            
</del><ins>+
</ins><span class="cx">             if len(splits) &gt; 1 and splits[1] == &quot;unique&quot;:
</span><span class="cx">                 result += &quot; unique&quot;
</span><del>-            
</del><ins>+
</ins><span class="cx">             return result
</span><del>-    
</del><ins>+
+
</ins><span class="cx">         @inlineCallbacks
</span><span class="cx">         def _create_table(self, name, columns, ifnotexists=False):
</span><del>-            
</del><ins>+
</ins><span class="cx">             colDefs = [&quot;%s %s&quot; % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
</span><span class="cx">             statement = &quot;create table %s (%s)&quot; % (
</span><span class="cx">                 name,
</span><span class="cx">                 &quot;, &quot;.join(colDefs),
</span><span class="cx">             )
</span><del>-            
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 yield self._db_execute(statement)
</span><span class="cx">             except pgdb.DatabaseError:
</span><del>-                
</del><ins>+
</ins><span class="cx">                 if not ifnotexists:
</span><span class="cx">                     raise
</span><del>-                
</del><ins>+
</ins><span class="cx">                 result = (yield self._test_table(name))
</span><span class="cx">                 if not result:
</span><del>-                    raise 
-    
</del><ins>+                    raise
+
+
</ins><span class="cx">         @inlineCallbacks
</span><span class="cx">         def _test_table(self, name):
</span><span class="cx">             result = (yield self._db_value_for_sql(&quot;&quot;&quot;
</span><span class="lines">@@ -586,27 +625,29 @@
</span><span class="cx">              where tablename = '%s'
</span><span class="cx">             &quot;&quot;&quot; % (name.lower(),)))
</span><span class="cx">             returnValue(result)
</span><del>-    
</del><ins>+
+
</ins><span class="cx">         @inlineCallbacks
</span><span class="cx">         def _create_index(self, name, ontable, columns, ifnotexists=False):
</span><del>-            
</del><ins>+
</ins><span class="cx">             statement = &quot;create index %s on %s (%s)&quot; % (
</span><span class="cx">                 name,
</span><span class="cx">                 ontable,
</span><span class="cx">                 &quot;, &quot;.join(columns),
</span><span class="cx">             )
</span><del>-            
</del><ins>+
</ins><span class="cx">             try:
</span><span class="cx">                 yield self._db_execute(statement)
</span><span class="cx">             except pgdb.DatabaseError:
</span><del>-                
</del><ins>+
</ins><span class="cx">                 if not ifnotexists:
</span><span class="cx">                     raise
</span><del>-                
</del><ins>+
</ins><span class="cx">                 result = (yield self._test_table(name))
</span><span class="cx">                 if not result:
</span><del>-                    raise 
-    
</del><ins>+                    raise
+
+
</ins><span class="cx">         @inlineCallbacks
</span><span class="cx">         def _db_init_schema_table(self):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="lines">@@ -614,7 +655,7 @@
</span><span class="cx">             @param db_filename: the file name of the index database.
</span><span class="cx">             @param q:           a database cursor to use.
</span><span class="cx">             &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">             #
</span><span class="cx">             # CALDAV table keeps track of our schema version and type
</span><span class="cx">             #
</span><span class="lines">@@ -623,7 +664,7 @@
</span><span class="cx">                     (&quot;KEY&quot;, &quot;text unique&quot;),
</span><span class="cx">                     (&quot;VALUE&quot;, &quot;text unique&quot;),
</span><span class="cx">                 ), True)
</span><del>-    
</del><ins>+
</ins><span class="cx">                 yield self._db_execute(
</span><span class="cx">                     &quot;&quot;&quot;
</span><span class="cx">                     insert into CALDAV (KEY, VALUE)
</span><span class="lines">@@ -638,7 +679,8 @@
</span><span class="cx">                 )
</span><span class="cx">             except pgdb.DatabaseError:
</span><span class="cx">                 pass
</span><del>-    
</del><ins>+
+
</ins><span class="cx">         def _prepare_statement(self, sql):
</span><span class="cx">             # Convert :1, :2 etc format into %s
</span><span class="cx">             ctr = 1
</span><span class="lines">@@ -649,6 +691,6 @@
</span><span class="cx"> 
</span><span class="cx"> else:
</span><span class="cx">     class ADBAPIPostgreSQLMixin(object):
</span><del>-        
</del><ins>+
</ins><span class="cx">         def __init__(self):
</span><span class="cx">             raise ConfigurationError(&quot;PostgreSQL module not available.&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdatafilterscalendardatapy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -19,7 +19,7 @@
</span><span class="cx"> from twistedcaldav.datafilters.filter import CalendarFilter
</span><span class="cx"> from twistedcaldav.dateops import clipPeriod
</span><span class="cx"> from twistedcaldav.ical import Component
</span><del>-from pycalendar.period import PyCalendarPeriod
</del><ins>+from pycalendar.period import Period
</ins><span class="cx"> 
</span><span class="cx"> __all__ = [
</span><span class="cx">     &quot;CalendarDataFilter&quot;,
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx">             for property in component.properties(&quot;FREEBUSY&quot;):
</span><span class="cx">                 newvalue = []
</span><span class="cx">                 for period in property.value():
</span><del>-                    clipped = clipPeriod(period.getValue(), PyCalendarPeriod(self.calendardata.freebusy_set.start, self.calendardata.freebusy_set.end))
</del><ins>+                    clipped = clipPeriod(period.getValue(), Period(self.calendardata.freebusy_set.start, self.calendardata.freebusy_set.end))
</ins><span class="cx">                     if clipped:
</span><span class="cx">                         newvalue.append(clipped)
</span><span class="cx">                 if len(newvalue):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdateopspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/dateops.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/dateops.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/dateops.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -28,9 +28,9 @@
</span><span class="cx">     &quot;clipPeriod&quot;
</span><span class="cx"> ]
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.period import PyCalendarPeriod
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
+from pycalendar.period import Period
</ins><span class="cx"> 
</span><span class="cx"> import datetime
</span><span class="cx"> import dateutil.tz
</span><span class="lines">@@ -39,14 +39,14 @@
</span><span class="cx"> 
</span><span class="cx"> def normalizeForIndex(dt):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Normalize a L{PyCalendarDateTime} object for use in the Index.
</del><ins>+    Normalize a L{DateTime} object for use in the Index.
</ins><span class="cx">     Convert to date-time in UTC.
</span><del>-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @return: the normalized PyCalendarDateTime
</del><ins>+    @param dt: a L{DateTime} object to normalize
+    @return: the normalized DateTime
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError(&quot;%r is not a PyCalendarDateTime instance&quot; % (dt,))
-    
</del><ins>+    if not isinstance(dt, DateTime):
+        raise TypeError(&quot;%r is not a DateTime instance&quot; % (dt,))
+
</ins><span class="cx">     dt = dt.duplicate()
</span><span class="cx">     if dt.isDateOnly():
</span><span class="cx">         dt.setDateOnly(False)
</span><span class="lines">@@ -59,13 +59,15 @@
</span><span class="cx">         dt.adjustToUTC()
</span><span class="cx">         return dt
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def normalizeToUTC(dt):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Normalize a L{PyCalendarDateTime} object to UTC.
</del><ins>+    Normalize a L{DateTime} object to UTC.
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError(&quot;%r is not a PyCalendarDateTime instance&quot; % (dt,))
-    
</del><ins>+    if not isinstance(dt, DateTime):
+        raise TypeError(&quot;%r is not a DateTime instance&quot; % (dt,))
+
</ins><span class="cx">     dt = dt.duplicate()
</span><span class="cx">     if dt.isDateOnly():
</span><span class="cx">         dt.setDateOnly(False)
</span><span class="lines">@@ -79,16 +81,18 @@
</span><span class="cx">         dt.adjustToUTC()
</span><span class="cx">         return dt
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def normalizeForExpand(dt):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Normalize a L{PyCalendarDateTime} object for use with the CalDAV expand option.
</del><ins>+    Normalize a L{DateTime} object for use with the CalDAV expand option.
</ins><span class="cx">     Convert to date-time in UTC, leave date only and floating alone.
</span><del>-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @return: the normalized PyCalendarDateTime
</del><ins>+    @param dt: a L{DateTime} object to normalize
+    @return: the normalized DateTime
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError(&quot;%r is not a PyCalendarDateTime instance&quot; % (dt,))
-    
</del><ins>+    if not isinstance(dt, DateTime):
+        raise TypeError(&quot;%r is not a DateTime instance&quot; % (dt,))
+
</ins><span class="cx">     dt = dt.duplicate()
</span><span class="cx">     if dt.isDateOnly() or dt.floating():
</span><span class="cx">         return dt
</span><span class="lines">@@ -96,41 +100,49 @@
</span><span class="cx">         dt.adjustToUTC()
</span><span class="cx">         return dt
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def floatoffset(dt, pytz):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Apply the timezone offset to the supplied time, then force tz to utc. This gives the local
</span><span class="cx">     date-time as if the local tz were UTC. It can be used in floating time comparisons with UTC date-times.
</span><del>-    
-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @param pytz: a L{PyCalendarTimezone} object to apply offset from
-    @return: the normalized PyCalendarDateTime
</del><ins>+
+    @param dt: a L{DateTime} object to normalize
+    @param pytz: a L{Timezone} object to apply offset from
+    @return: the normalized DateTime
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     if pytz is None:
</span><del>-        pytz = PyCalendarTimezone(utc=True)
-    
</del><ins>+        pytz = Timezone(utc=True)
+
</ins><span class="cx">     dt = dt.duplicate()
</span><span class="cx">     dt.adjustTimezone(pytz)
</span><span class="cx">     dt.setTimezoneUTC(True)
</span><span class="cx">     return dt
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def adjustFloatingToTimezone(dtadjust, dtcopyfrom, pytz=None):
</span><del>-    
</del><ins>+
</ins><span class="cx">     dtadjust = dtadjust.duplicate()
</span><span class="cx">     dtadjust.setTimezone(pytz if pytz else dtcopyfrom.getTimezone())
</span><span class="cx">     return dtadjust
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def compareDateTime(dt1, dt2, defaulttz=None):
</span><del>-    
</del><ins>+
</ins><span class="cx">     if dt1.floating() and not dt2.floating():
</span><span class="cx">         dt1 = adjustFloatingToTimezone(dt1, dt2, defaulttz)
</span><span class="cx">     elif dt2.floating() and not dt1.floating():
</span><span class="cx">         dt2 = adjustFloatingToTimezone(dt2, dt1, defaulttz)
</span><del>-    
</del><ins>+
</ins><span class="cx">     return dt1.compareDateTime(dt2)
</span><span class="cx"> 
</span><del>-def differenceDateTime(start, end, defaulttz = None):
</del><span class="cx"> 
</span><ins>+
+def differenceDateTime(start, end, defaulttz=None):
+
</ins><span class="cx">     if start.floating() and not end.floating():
</span><span class="cx">         start = adjustFloatingToTimezone(start, end, defaulttz)
</span><span class="cx">     elif end.floating() and not start.floating():
</span><span class="lines">@@ -138,13 +150,19 @@
</span><span class="cx"> 
</span><span class="cx">     return end - start
</span><span class="cx"> 
</span><del>-def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
</del><ins>+
+
+def timeRangesOverlap(start1, end1, start2, end2, defaulttz=None):
</ins><span class="cx">     # Can't compare date-time and date only, so normalize
</span><span class="cx">     # to date only if they are mixed.
</span><del>-    if (start1 is not None) and not start1.isDateOnly() and (start2 is not None) and start2.isDateOnly(): start1.setDateOnly(True)
-    if (start2 is not None) and not start2.isDateOnly() and (start1 is not None) and start1.isDateOnly(): start2.setDateOnly(True)
-    if (end1 is not None) and not end1.isDateOnly() and (end2 is not None) and end2.isDateOnly(): end1.setDateOnly(True)
-    if (end2 is not None) and not end2.isDateOnly() and (end1 is not None) and end1.isDateOnly(): end2.setDateOnly(True)
</del><ins>+    if (start1 is not None) and not start1.isDateOnly() and (start2 is not None) and start2.isDateOnly():
+        start1.setDateOnly(True)
+    if (start2 is not None) and not start2.isDateOnly() and (start1 is not None) and start1.isDateOnly():
+        start2.setDateOnly(True)
+    if (end1 is not None) and not end1.isDateOnly() and (end2 is not None) and end2.isDateOnly():
+        end1.setDateOnly(True)
+    if (end2 is not None) and not end2.isDateOnly() and (end1 is not None) and end1.isDateOnly():
+        end2.setDateOnly(True)
</ins><span class="cx"> 
</span><span class="cx">     # Note that start times are inclusive and end times are not.
</span><span class="cx">     if start1 is not None and start2 is not None:
</span><span class="lines">@@ -163,40 +181,41 @@
</span><span class="cx">     else:
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def normalizePeriodList(periods):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Normalize the list of periods by merging overlapping or consecutive ranges
</span><span class="cx">     and sorting the list by each periods start.
</span><del>-    @param list: a list of tuples of L{PyCalendarPeriod}. The list is changed in place.
</del><ins>+    @param list: a list of tuples of L{Period}. The list is changed in place.
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     # First sort the list
</span><span class="cx">     def sortPeriods(p1, p2):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Compare two periods. Sort by their start and then end times.
</span><del>-        A period is a L{PyCalendarPeriod}.
</del><ins>+        A period is a L{Period}.
</ins><span class="cx">         @param p1: first period
</span><span class="cx">         @param p2: second period
</span><span class="cx">         @return: 1 if p1&gt;p2, 0 if p1==p2, -1 if p1&lt;p2
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        assert isinstance(p1, PyCalendarPeriod), &quot;Period is not a PyCalendarPeriod: %r&quot; % (p1,)
-        assert isinstance(p2, PyCalendarPeriod), &quot;Period is not a PyCalendarPeriod: %r&quot; % (p2,)
-        
-        
</del><ins>+        assert isinstance(p1, Period), &quot;Period is not a Period: %r&quot; % (p1,)
+        assert isinstance(p2, Period), &quot;Period is not a Period: %r&quot; % (p2,)
+
</ins><span class="cx">         if p1.getStart() == p2.getStart():
</span><span class="cx">             cmp1 = p1.getEnd()
</span><span class="cx">             cmp2 = p2.getEnd()
</span><span class="cx">         else:
</span><span class="cx">             cmp1 = p1.getStart()
</span><span class="cx">             cmp2 = p2.getStart()
</span><del>-        
</del><ins>+
</ins><span class="cx">         return compareDateTime(cmp1, cmp2)
</span><span class="cx"> 
</span><span class="cx">     for period in periods:
</span><span class="cx">         period.adjustToUTC()
</span><span class="cx">     periods.sort(cmp=sortPeriods)
</span><del>-    
</del><ins>+
</ins><span class="cx">     # Now merge overlaps and consecutive periods
</span><span class="cx">     index = None
</span><span class="cx">     p = None
</span><span class="lines">@@ -210,15 +229,17 @@
</span><span class="cx">         ie = periods[i].getEnd()
</span><span class="cx">         if (pe &gt;= periods[i].getStart()):
</span><span class="cx">             if ie &gt; pe:
</span><del>-                periods[index] = PyCalendarPeriod(periods[index].getStart(), ie)
</del><ins>+                periods[index] = Period(periods[index].getStart(), ie)
</ins><span class="cx">                 pe = ie
</span><span class="cx">             periods[i] = None
</span><span class="cx">         else:
</span><span class="cx">             index = i
</span><span class="cx">             p = periods[i]
</span><del>-            pe =p.getEnd()
</del><ins>+            pe = p.getEnd()
</ins><span class="cx">     periods[:] = [x for x in periods if x]
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def clipPeriod(period, clipPeriod):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Clip the start/end period so that it lies entirely within the clip period.
</span><span class="lines">@@ -234,20 +255,22 @@
</span><span class="cx"> 
</span><span class="cx">     if start &lt; clipStart:
</span><span class="cx">         start = clipStart
</span><del>-    
</del><ins>+
</ins><span class="cx">     if end &gt; clipEnd:
</span><span class="cx">         end = clipEnd
</span><del>-    
</del><ins>+
</ins><span class="cx">     if start &gt;= end:
</span><span class="cx">         return None
</span><span class="cx">     else:
</span><span class="cx">         # Try to preserve use of duration in period
</span><del>-        result = PyCalendarPeriod(start, end)
</del><ins>+        result = Period(start, end)
</ins><span class="cx">         result.setUseDuration(period.getUseDuration())
</span><span class="cx">         return result
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def pyCalendarTodatetime(pydt):
</span><del>-    
</del><ins>+
</ins><span class="cx">     if pydt.isDateOnly():
</span><span class="cx">         return datetime.date(year=pydt.getYear(), month=pydt.getMonth(), day=pydt.getDay())
</span><span class="cx">     else:
</span><span class="lines">@@ -261,17 +284,19 @@
</span><span class="cx">             tzinfo=dateutil.tz.tzutc()
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def parseSQLTimestampToPyCalendar(ts):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Parse an SQL formated timestamp into a PyCalendarDateTime
</del><ins>+    Parse an SQL formated timestamp into a DateTime
</ins><span class="cx">     @param ts: the SQL timestamp
</span><span class="cx">     @type ts: C{str}
</span><del>-    
-    @return: L{PyCalendarDateTime} result
</del><ins>+
+    @return: L{DateTime} result
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     # Format is &quot;%Y-%m-%d %H:%M:%S&quot;
</span><del>-    return PyCalendarDateTime(
</del><ins>+    return DateTime(
</ins><span class="cx">         year=int(ts[0:4]),
</span><span class="cx">         month=int(ts[5:7]),
</span><span class="cx">         day=int(ts[8:10]),
</span><span class="lines">@@ -280,22 +305,26 @@
</span><span class="cx">         seconds=int(ts[17:19])
</span><span class="cx">     )
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def parseSQLDateToPyCalendar(ts):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Parse an SQL formated date into a PyCalendarDateTime
</del><ins>+    Parse an SQL formated date into a DateTime
</ins><span class="cx">     @param ts: the SQL date
</span><span class="cx">     @type ts: C{str}
</span><del>-    
-    @return: L{PyCalendarDateTime} result
</del><ins>+
+    @return: L{DateTime} result
</ins><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     # Format is &quot;%Y-%m-%d&quot;, though Oracle may add zero time which we ignore
</span><del>-    return PyCalendarDateTime(
</del><ins>+    return DateTime(
</ins><span class="cx">         year=int(ts[0:4]),
</span><span class="cx">         month=int(ts[5:7]),
</span><span class="cx">         day=int(ts[8:10])
</span><span class="cx">     )
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def datetimeMktime(dt):
</span><span class="cx"> 
</span><span class="cx">     assert isinstance(dt, datetime.date)
</span><span class="lines">@@ -303,4 +332,3 @@
</span><span class="cx">     if dt.tzinfo is None:
</span><span class="cx">         dt.replace(tzinfo=dateutil.tz.tzutc())
</span><span class="cx">     return calendar.timegm(dt.utctimetuple())
</span><del>-
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryaddressbookpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/addressbook.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/addressbook.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/addressbook.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -56,6 +56,8 @@
</span><span class="cx">             + config.CalDAVComplianceClasses
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class DirectoryAddressBookProvisioningResource (
</span><span class="cx">     ReadOnlyResourceMixIn,
</span><span class="cx">     CalDAVComplianceMixIn,
</span><span class="lines">@@ -65,18 +67,21 @@
</span><span class="cx">     def defaultAccessControlList(self):
</span><span class="cx">         return config.ProvisioningResourceACL
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def etag(self):
</span><span class="cx">         return succeed(ETag(str(uuid4())))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def contentType(self):
</span><span class="cx">         return MimeType(&quot;httpd&quot;, &quot;unix-directory&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DirectoryAddressBookHomeProvisioningResource (
</span><span class="cx">         DirectoryAddressBookProvisioningResource
</span><span class="cx">     ):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Resource which provisions address book home collections as needed.    
</del><ins>+    Resource which provisions address book home collections as needed.
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def __init__(self, directory, url, store):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -103,22 +108,27 @@
</span><span class="cx"> 
</span><span class="cx">         self.putChild(uidsResourceName, DirectoryAddressBookHomeUIDProvisioningResource(self))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def url(self):
</span><span class="cx">         return self._url
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def listChildren(self):
</span><span class="cx">         return self.directory.recordTypes()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def principalCollections(self):
</span><span class="cx">         # FIXME: directory.principalCollection smells like a hack
</span><span class="cx">         # See DirectoryPrincipalProvisioningResource.__init__()
</span><span class="cx">         return self.directory.principalCollection.principalCollections()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def principalForRecord(self, record):
</span><span class="cx">         # FIXME: directory.principalCollection smells like a hack
</span><span class="cx">         # See DirectoryPrincipalProvisioningResource.__init__()
</span><span class="cx">         return self.directory.principalCollection.principalForRecord(record)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def homeForDirectoryRecord(self, record, request):
</span><span class="cx">         uidResource = self.getChild(uidsResourceName)
</span><span class="cx">         if uidResource is None:
</span><span class="lines">@@ -126,17 +136,20 @@
</span><span class="cx">         else:
</span><span class="cx">             return uidResource.homeResourceForRecord(record, request)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     ##
</span><span class="cx">     # DAV
</span><span class="cx">     ##
</span><del>-    
</del><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return True
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def displayName(self):
</span><span class="cx">         return &quot;addressbooks&quot;
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DirectoryAddressBookHomeTypeProvisioningResource (
</span><span class="cx">         CommonHomeTypeProvisioningResource,
</span><span class="cx">         DirectoryAddressBookProvisioningResource
</span><span class="lines">@@ -159,6 +172,7 @@
</span><span class="cx">         self.recordType = recordType
</span><span class="cx">         self._parent = parent
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def url(self):
</span><span class="cx">         return joinURL(self._parent.url(), self.recordType)
</span><span class="cx"> 
</span><span class="lines">@@ -177,16 +191,19 @@
</span><span class="cx">             # Not a listable collection
</span><span class="cx">             raise HTTPError(responsecode.FORBIDDEN)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def makeChild(self, name):
</span><span class="cx">         return None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     ##
</span><span class="cx">     # DAV
</span><span class="cx">     ##
</span><del>-    
</del><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return True
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def displayName(self):
</span><span class="cx">         return self.recordType
</span><span class="cx"> 
</span><span class="lines">@@ -194,13 +211,16 @@
</span><span class="cx">     # ACL
</span><span class="cx">     ##
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def principalCollections(self):
</span><span class="cx">         return self._parent.principalCollections()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def principalForRecord(self, record):
</span><span class="cx">         return self._parent.principalForRecord(record)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DirectoryAddressBookHomeUIDProvisioningResource (
</span><span class="cx">         CommonUIDProvisioningResource,
</span><span class="cx">         DirectoryAddressBookProvisioningResource
</span><span class="lines">@@ -210,11 +230,13 @@
</span><span class="cx"> 
</span><span class="cx">     enabledAttribute = 'enabledForAddressBooks'
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def homeResourceCreator(self, record, transaction):
</span><span class="cx">         return DirectoryAddressBookHomeResource.createHomeResource(
</span><span class="cx">             self, record, transaction)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DirectoryAddressBookHomeResource (AddressBookHomeResource):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Address book home collection resource.
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryopendirectorybackerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -35,9 +35,9 @@
</span><span class="cx"> from tempfile import mkstemp, gettempdir
</span><span class="cx"> from random import random
</span><span class="cx"> 
</span><del>-from pycalendar.n import N
-from pycalendar.adr import Adr
-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.vcard.n import N
+from pycalendar.vcard.adr import Adr
+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from socket import getfqdn
</span><span class="cx"> 
</span><span class="lines">@@ -1494,7 +1494,7 @@
</span><span class="cx"> 
</span><span class="cx">             birthdate = self.isoDateStringForDateAttribute(dsattributes.kDS1AttrBirthday)
</span><span class="cx">             if birthdate:
</span><del>-                vcard.addProperty(Property(&quot;BDAY&quot;, PyCalendarDateTime.parseText(birthdate, fullISO=True)))
</del><ins>+                vcard.addProperty(Property(&quot;BDAY&quot;, DateTime.parseText(birthdate, fullISO=True)))
</ins><span class="cx"> 
</span><span class="cx">             # 3.2 Delivery Addressing Types http://tools.ietf.org/html/rfc2426#section-3.2
</span><span class="cx">             #
</span><span class="lines">@@ -1685,7 +1685,7 @@
</span><span class="cx">             # 3.6.4 REV Type Definition
</span><span class="cx">             revDate = self.isoDateStringForDateAttribute(dsattributes.kDS1AttrModificationTimestamp)
</span><span class="cx">             if revDate:
</span><del>-                vcard.addProperty(Property(&quot;REV&quot;, PyCalendarDateTime.parseText(revDate, fullISO=True)))
</del><ins>+                vcard.addProperty(Property(&quot;REV&quot;, DateTime.parseText(revDate, fullISO=True)))
</ins><span class="cx"> 
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             # UNIMPLEMENTED:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_aggregatepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -36,7 +36,8 @@
</span><span class="cx">                 recordTypes.add(prefix + recordType)
</span><span class="cx">         return recordTypes
</span><span class="cx"> 
</span><del>-    def _records(key):
</del><ins>+
+    def _records(key): #@NoSelf
</ins><span class="cx">         def get(self):
</span><span class="cx">             records = {}
</span><span class="cx">             for prefix, testClass in testServices:
</span><span class="lines">@@ -58,6 +59,7 @@
</span><span class="cx"> 
</span><span class="cx">     recordTypePrefixes = tuple(s[0] for s in testServices)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def service(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Returns an IDirectoryService.
</span><span class="lines">@@ -71,9 +73,9 @@
</span><span class="cx">         )
</span><span class="cx">         xmlService.recordTypePrefix = xml_prefix
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         return AggregateDirectoryService((xmlService,), None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_setRealm(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         setRealm gets propagated to nested services
</span><span class="lines">@@ -82,4 +84,3 @@
</span><span class="cx">         aggregatedService.setRealm(&quot;foo.example.com&quot;)
</span><span class="cx">         for service in aggregatedService._recordTypes.values():
</span><span class="cx">             self.assertEquals(&quot;foo.example.com&quot;, service.realmName)
</span><del>-
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_cachedirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx">             DirectoryService.recordType_resources,
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def queryDirectory(self, recordTypes, indexType, indexKey):
</span><span class="cx"> 
</span><span class="cx">         self.queried = True
</span><span class="lines">@@ -58,42 +59,47 @@
</span><span class="cx"> 
</span><span class="cx">                 if cacheIt:
</span><span class="cx">                     cacheRecord = CachingDirectoryRecord(
</span><del>-                        service               = self,
-                        recordType            = recordType,
-                        guid                  = record.get(&quot;guid&quot;),
-                        shortNames            = record.get(&quot;shortname&quot;),
-                        authIDs               = record.get(&quot;authid&quot;),
-                        fullName              = record.get(&quot;fullName&quot;),
-                        firstName             = &quot;&quot;,
-                        lastName              = &quot;&quot;,
-                        emailAddresses        = record.get(&quot;email&quot;),
-                    ) 
-                    
</del><ins>+                        service=self,
+                        recordType=recordType,
+                        guid=record.get(&quot;guid&quot;),
+                        shortNames=record.get(&quot;shortname&quot;),
+                        authIDs=record.get(&quot;authid&quot;),
+                        fullName=record.get(&quot;fullName&quot;),
+                        firstName=&quot;&quot;,
+                        lastName=&quot;&quot;,
+                        emailAddresses=record.get(&quot;email&quot;),
+                    )
+
</ins><span class="cx">                     augmentRecord = AugmentRecord(
</span><del>-                        uid = cacheRecord.guid,
</del><ins>+                        uid=cacheRecord.guid,
</ins><span class="cx">                         enabled=True,
</span><del>-                        enabledForCalendaring = True,
</del><ins>+                        enabledForCalendaring=True,
</ins><span class="cx">                     )
</span><del>-                    
</del><ins>+
</ins><span class="cx">                     cacheRecord.addAugmentInformation(augmentRecord)
</span><span class="cx"> 
</span><span class="cx">                     self.recordCacheForType(recordType).addRecord(cacheRecord,
</span><span class="cx">                         indexType, indexKey)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class CachingDirectoryTest(TestCase):
</span><del>-    
</del><ins>+
</ins><span class="cx">     baseGUID = str(uuid4())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def setUp(self):
</span><span class="cx">         super(CachingDirectoryTest, self).setUp()
</span><span class="cx">         self.service = TestDirectoryService()
</span><span class="cx">         self.service.queried = False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def loadRecords(self, records):
</span><span class="cx">         self.service._initCaches()
</span><span class="cx">         self.service.fakerecords = records
</span><span class="cx">         self.service.queried = False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def fakeRecord(
</span><span class="cx">         self,
</span><span class="cx">         fullName,
</span><span class="lines">@@ -109,15 +115,15 @@
</span><span class="cx">             shortNames = (self.shortNameForFullName(fullName),)
</span><span class="cx">             if multinames:
</span><span class="cx">                 shortNames += (fullName,)
</span><del>-    
</del><ins>+
</ins><span class="cx">         if guid is None:
</span><span class="cx">             guid = self.guidForShortName(shortNames[0], recordType=recordType)
</span><span class="cx">         else:
</span><span class="cx">             guid = guid.lower()
</span><del>-    
</del><ins>+
</ins><span class="cx">         if emails is None:
</span><span class="cx">             emails = (&quot;%s@example.com&quot; % (shortNames[0],),)
</span><del>-    
</del><ins>+
</ins><span class="cx">         attrs = {
</span><span class="cx">             &quot;fullName&quot;: fullName,
</span><span class="cx">             &quot;guid&quot;: guid,
</span><span class="lines">@@ -126,35 +132,38 @@
</span><span class="cx">             &quot;cua&quot;: tuple([&quot;mailto:%s&quot; % email for email in emails]),
</span><span class="cx">             &quot;authid&quot;: tuple([&quot;Kerberos:%s&quot; % email for email in emails])
</span><span class="cx">         }
</span><del>-        
</del><ins>+
</ins><span class="cx">         if members:
</span><span class="cx">             attrs[&quot;members&quot;] = members
</span><del>-    
</del><ins>+
</ins><span class="cx">         if resourceInfo:
</span><span class="cx">             attrs[&quot;resourceInfo&quot;] = resourceInfo
</span><del>-    
</del><ins>+
</ins><span class="cx">         return attrs
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def shortNameForFullName(self, fullName):
</span><span class="cx">         return fullName.lower().replace(&quot; &quot;, &quot;&quot;)
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def guidForShortName(self, shortName, recordType=&quot;&quot;):
</span><span class="cx">         return uuidFromName(self.baseGUID, &quot;%s%s&quot; % (recordType, shortName))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def dummyRecords(self):
</span><span class="cx">         SIZE = 10
</span><span class="cx">         records = {
</span><span class="cx">             DirectoryService.recordType_users: [
</span><del>-                self.fakeRecord(&quot;User %02d&quot; % x, DirectoryService.recordType_users, multinames=(x&gt;5)) for x in range(1,SIZE+1)
</del><ins>+                self.fakeRecord(&quot;User %02d&quot; % x, DirectoryService.recordType_users, multinames=(x &gt; 5)) for x in range(1, SIZE + 1)
</ins><span class="cx">             ],
</span><span class="cx">             DirectoryService.recordType_groups: [
</span><del>-                self.fakeRecord(&quot;Group %02d&quot; % x, DirectoryService.recordType_groups) for x in range(1,SIZE+1)
</del><ins>+                self.fakeRecord(&quot;Group %02d&quot; % x, DirectoryService.recordType_groups) for x in range(1, SIZE + 1)
</ins><span class="cx">             ],
</span><span class="cx">             DirectoryService.recordType_resources: [
</span><del>-                self.fakeRecord(&quot;Resource %02d&quot; % x, DirectoryService.recordType_resources) for x in range(1,SIZE+1)
</del><ins>+                self.fakeRecord(&quot;Resource %02d&quot; % x, DirectoryService.recordType_resources) for x in range(1, SIZE + 1)
</ins><span class="cx">             ],
</span><span class="cx">             DirectoryService.recordType_locations: [
</span><del>-                self.fakeRecord(&quot;Location %02d&quot; % x, DirectoryService.recordType_locations) for x in range(1,SIZE+1)
</del><ins>+                self.fakeRecord(&quot;Location %02d&quot; % x, DirectoryService.recordType_locations) for x in range(1, SIZE + 1)
</ins><span class="cx">             ],
</span><span class="cx">         }
</span><span class="cx">         # Add duplicate shortnames
</span><span class="lines">@@ -165,14 +174,17 @@
</span><span class="cx"> 
</span><span class="cx">         self.loadRecords(records)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def verifyRecords(self, recordType, expectedGUIDs):
</span><del>-        
</del><ins>+
</ins><span class="cx">         records = self.service.listRecords(recordType)
</span><span class="cx">         recordGUIDs = set([record.guid for record in records])
</span><span class="cx">         self.assertEqual(recordGUIDs, expectedGUIDs)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class GUIDLookups(CachingDirectoryTest):
</span><del>-    
</del><ins>+
</ins><span class="cx">     def test_emptylist(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -180,7 +192,8 @@
</span><span class="cx">         self.verifyRecords(DirectoryService.recordType_groups, set())
</span><span class="cx">         self.verifyRecords(DirectoryService.recordType_resources, set())
</span><span class="cx">         self.verifyRecords(DirectoryService.recordType_locations, set())
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def test_cacheoneguid(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -200,7 +213,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Make sure guid is case-insensitive
</span><span class="cx">         self.assertTrue(self.service.recordWithGUID(self.guidForShortName(&quot;user01&quot;, recordType=DirectoryService.recordType_users).lower()) is not None)
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def test_cacheoneshortname(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -224,6 +238,7 @@
</span><span class="cx">         ) is not None)
</span><span class="cx">         self.assertFalse(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_cacheoneemail(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -245,6 +260,7 @@
</span><span class="cx">         ) is not None)
</span><span class="cx">         self.assertFalse(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_cacheonePrincipalsURLWithUIDS(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -267,6 +283,7 @@
</span><span class="cx">         ) is not None)
</span><span class="cx">         self.assertFalse(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_cacheonePrincipalsURLWithUsers(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -288,6 +305,7 @@
</span><span class="cx">         ) is not None)
</span><span class="cx">         self.assertFalse(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_cacheoneauthid(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -309,6 +327,7 @@
</span><span class="cx">         ) is not None)
</span><span class="cx">         self.assertFalse(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_negativeCaching(self):
</span><span class="cx">         self.dummyRecords()
</span><span class="cx"> 
</span><span class="lines">@@ -324,7 +343,6 @@
</span><span class="cx">         self.assertEquals(self.service.recordWithGUID(self.guidForShortName(&quot;missing&quot;)), None)
</span><span class="cx">         self.assertTrue(self.service.queried)
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         # However, if negativeCaching is on, a miss is recorded as such,
</span><span class="cx">         # preventing a similar queryDirectory( ) until cacheTimeout passes
</span><span class="cx">         self.service.negativeCaching = True
</span><span class="lines">@@ -345,6 +363,7 @@
</span><span class="cx">         self.assertEquals(self.service.recordWithGUID(self.guidForShortName(&quot;missing&quot;)), None)
</span><span class="cx">         self.assertTrue(self.service.queried)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_duplicateShortNames(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Verify that when looking up records having duplicate short-names, the record of the
</span><span class="lines">@@ -370,6 +389,7 @@
</span><span class="cx">             &quot;Duplicate&quot;)
</span><span class="cx">         self.assertEquals(record.recordType, DirectoryService.recordType_locations)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_generateMemcacheKey(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Verify keys are correctly generated based on the index type -- if index type is
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_digestpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx"> challengeResponse = ('digest',
</span><span class="cx">                      {'nonce': challengeNonce,
</span><span class="cx">                       'qop': 'auth', 'realm': 'test realm',
</span><del>-                      'algorithm': 'md5',})
</del><ins>+                      'algorithm': 'md5', })
</ins><span class="cx"> 
</span><span class="cx"> cnonce = &quot;29fc54aa1641c6fa0e151419361c8f23&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -116,6 +116,7 @@
</span><span class="cx">                                           self.namespace2
</span><span class="cx">                                       ))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getDigestResponse(self, challenge, ncount):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Calculate the response for the given challenge
</span><span class="lines">@@ -146,6 +147,7 @@
</span><span class="cx">                 )
</span><span class="cx">         return expected
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getDigestResponseComma(self, challenge, ncount):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Calculate the response for the given challenge
</span><span class="lines">@@ -176,6 +178,7 @@
</span><span class="cx">                 )
</span><span class="cx">         return expected
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def assertRaisesDeferred(self, exception, f, *args, **kwargs):
</span><span class="cx">         try:
</span><span class="lines">@@ -191,6 +194,7 @@
</span><span class="cx">             raise self.failureException('%s not raised (%r returned)'
</span><span class="cx">                                         % (exception.__name__, result))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_getChallenge(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -203,14 +207,15 @@
</span><span class="cx">         self.assertEquals(challenge['qop'], 'auth')
</span><span class="cx">         self.assertEquals(challenge['realm'], 'test realm')
</span><span class="cx">         self.assertEquals(challenge['algorithm'], 'md5')
</span><del>-        self.assertTrue(challenge.has_key(&quot;nonce&quot;))
</del><ins>+        self.assertTrue(&quot;nonce&quot; in challenge)
</ins><span class="cx"> 
</span><span class="cx">         challenge = (yield self.credentialFactories[1].getChallenge(clientAddress))
</span><del>-        self.assertFalse(challenge.has_key('qop'))
</del><ins>+        self.assertFalse('qop' in challenge)
</ins><span class="cx">         self.assertEquals(challenge['realm'], 'test realm')
</span><span class="cx">         self.assertEquals(challenge['algorithm'], 'md5')
</span><del>-        self.assertTrue(challenge.has_key(&quot;nonce&quot;))
</del><ins>+        self.assertTrue(&quot;nonce&quot; in challenge)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_response(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -219,15 +224,16 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><span class="cx">             self.failUnless(creds.checkPassword('password'))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_multiResponse(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -237,23 +243,24 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><span class="cx">             self.failUnless(creds.checkPassword('password'))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest2[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000002&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><span class="cx">             self.failUnless(creds.checkPassword('password'))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_failsWithDifferentMethod(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -263,16 +270,17 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse,
</span><span class="cx">                                                   SimpleRequest(None, 'POST', '/')))
</span><span class="cx">             self.failIf(creds.checkPassword('password'))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_noUsername(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -287,7 +295,7 @@
</span><span class="cx">                                   namelessAuthRequest,
</span><span class="cx">                                   _trivial_GET()))
</span><span class="cx">             self.assertEquals(str(e), &quot;Invalid response, no username given.&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             # Check for an empty username
</span><span class="cx">             e = (yield self.assertRaisesDeferred(error.LoginFailed,
</span><span class="cx">                                   factory.decode,
</span><span class="lines">@@ -295,6 +303,7 @@
</span><span class="cx">                                   _trivial_GET()))
</span><span class="cx">             self.assertEquals(str(e), &quot;Invalid response, no username given.&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_noNonce(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -308,6 +317,7 @@
</span><span class="cx">                                   _trivial_GET()))
</span><span class="cx">             self.assertEquals(str(e), &quot;Invalid response, no nonce given.&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_emptyAttribute(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -323,6 +333,7 @@
</span><span class="cx">                                   _trivial_GET()))
</span><span class="cx">             self.assertEquals(str(e), &quot;Invalid response, no username given.&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_checkHash(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -332,20 +343,21 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.failUnless(creds.checkHash(
</span><span class="cx">                     md5('username:test realm:password').hexdigest()))
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.failIf(creds.checkHash(
</span><span class="cx">                     md5('username:test realm:bogus').hexdigest()))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_invalidNonceCount(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -359,20 +371,20 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse1 = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse2 = authRequest2[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000002&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             yield factory.decode(clientResponse1, _trivial_GET())
</span><span class="cx">             yield factory.decode(clientResponse2, _trivial_GET())
</span><del>-    
</del><ins>+
</ins><span class="cx">             if challenge.get('qop') is not None:
</span><span class="cx">                 yield self.assertRaisesDeferred(
</span><span class="cx">                     error.LoginFailed,
</span><span class="lines">@@ -380,7 +392,7 @@
</span><span class="cx">                     clientResponse2,
</span><span class="cx">                     _trivial_GET()
</span><span class="cx">                 )
</span><del>-                
</del><ins>+
</ins><span class="cx">                 challenge = (yield factory.getChallenge(clientAddress))
</span><span class="cx"> 
</span><span class="cx">                 clientResponse1 = authRequest1[ctr] % (
</span><span class="lines">@@ -400,6 +412,7 @@
</span><span class="cx">                     _trivial_GET()
</span><span class="cx">                 )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_invalidNonce(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -415,12 +428,12 @@
</span><span class="cx">         for ctr, factory in enumerate(credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><span class="cx">             challenge['nonce'] = &quot;noNoncense&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             request = _trivial_GET()
</span><span class="cx">             yield self.assertRaisesDeferred(
</span><span class="cx">                 error.LoginFailed,
</span><span class="lines">@@ -431,11 +444,12 @@
</span><span class="cx"> 
</span><span class="cx">             factory._invalidate(FAKE_STATIC_NONCE)
</span><span class="cx">             response = (yield UnauthorizedResponse.makeResponse(
</span><del>-                {&quot;Digest&quot;:factory},
</del><ins>+                {&quot;Digest&quot;: factory},
</ins><span class="cx">                 request.remoteAddr
</span><span class="cx">             ))
</span><span class="cx">             response.headers.getHeader(&quot;www-authenticate&quot;)[0][1]
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_oldNonce(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -452,12 +466,12 @@
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><span class="cx">             nonce_count, timestamp = (yield factory.db.get(challenge['nonce']))
</span><span class="cx">             factory.db.set(challenge['nonce'], (nonce_count, timestamp - 2 * digest.DigestCredentialFactory.CHALLENGE_LIFETIME_SECS))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             request = _trivial_GET()
</span><span class="cx">             yield self.assertRaisesDeferred(
</span><span class="cx">                 error.LoginFailed,
</span><span class="lines">@@ -465,15 +479,16 @@
</span><span class="cx">                 clientResponse,
</span><span class="cx">                 request
</span><span class="cx">             )
</span><del>-            
</del><ins>+
</ins><span class="cx">             response = (yield UnauthorizedResponse.makeResponse(
</span><del>-                {&quot;Digest&quot;:factory},
</del><ins>+                {&quot;Digest&quot;: factory},
</ins><span class="cx">                 request.remoteAddr,
</span><span class="cx">             ))
</span><span class="cx">             wwwhdrs = response.headers.getHeader(&quot;www-authenticate&quot;)[0][1]
</span><span class="cx">             self.assertTrue('stale' in wwwhdrs, msg=&quot;No stale parameter in Digest WWW-Authenticate headers: %s&quot; % (wwwhdrs,))
</span><span class="cx">             self.assertEquals(wwwhdrs['stale'], 'true', msg=&quot;stale parameter not set to true in Digest WWW-Authenticate headers: %s&quot; % (wwwhdrs,))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_incompatibleCalcHA1Options(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Test that the appropriate error is raised when any of the
</span><span class="lines">@@ -500,6 +515,7 @@
</span><span class="cx">                 preHA1=preHA1
</span><span class="cx">                 )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_commaURI(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -508,15 +524,16 @@
</span><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequestComma[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponseComma(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><span class="cx">             self.failUnless(creds.checkPassword('password'))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_stale_response(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -526,20 +543,20 @@
</span><span class="cx">         class newtime(object):
</span><span class="cx">             def time(self):
</span><span class="cx">                 return theTime
</span><del>-        from twistedcaldav.directory import digest
-        self.patch(digest, &quot;time&quot;, newtime())
</del><ins>+        from twistedcaldav.directory import digest as ddigest
+        self.patch(ddigest, &quot;time&quot;, newtime())
</ins><span class="cx"> 
</span><span class="cx">         for ctr, factory in enumerate(self.credentialFactories):
</span><span class="cx">             challenge = (yield factory.getChallenge(clientAddress))
</span><del>-    
</del><ins>+
</ins><span class="cx">             clientResponse = authRequest1[ctr] % (
</span><span class="cx">                 challenge['nonce'],
</span><span class="cx">                 self.getDigestResponse(challenge, &quot;00000001&quot;),
</span><span class="cx">             )
</span><del>-    
</del><ins>+
</ins><span class="cx">             creds = (yield factory.decode(clientResponse, _trivial_GET()))
</span><span class="cx">             self.failUnless(creds.checkPassword('password'))
</span><del>-            
</del><ins>+
</ins><span class="cx">             theTime += DigestCredentialFactory.CHALLENGE_LIFETIME_SECS + 1
</span><span class="cx">             request = _trivial_GET()
</span><span class="cx">             try:
</span><span class="lines">@@ -555,8 +572,8 @@
</span><span class="cx">                 self.fail(&quot;Invalid exception from nonce timeout: %s&quot; % e)
</span><span class="cx">             challenge = (yield factory.getChallenge(request.remoteAddr))
</span><span class="cx">             self.assertTrue(challenge.get(&quot;stale&quot;) == &quot;true&quot;)
</span><del>-            
</del><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def _trivial_GET():
</span><span class="cx">     return SimpleRequest(None, 'GET', '/')
</span><del>-
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_directorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -121,7 +121,6 @@
</span><span class="cx">         self.count += 1
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     def test_expandedMembers(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Make sure expandedMembers( ) returns a complete, flattened set of
</span><span class="lines">@@ -889,7 +888,7 @@
</span><span class="cx">         }
</span><span class="cx">         members = pickle.loads(snapshotFile.getContent())
</span><span class="cx">         self.assertEquals(members, expected)
</span><del>-        
</del><ins>+
</ins><span class="cx">         # &quot;Corrupt&quot; the snapshot and verify it is regenerated properly
</span><span class="cx">         snapshotFile.setContent(&quot;xyzzy&quot;)
</span><span class="cx">         cache.delete(&quot;group-cacher-populated&quot;)
</span><span class="lines">@@ -900,8 +899,8 @@
</span><span class="cx">         self.assertTrue(snapshotFile.exists())
</span><span class="cx">         members = pickle.loads(snapshotFile.getContent())
</span><span class="cx">         self.assertEquals(members, expected)
</span><del>-        
</del><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_autoAcceptMembers(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         autoAcceptMembers( ) returns an empty list if no autoAcceptGroup is
</span><span class="lines">@@ -926,6 +925,7 @@
</span><span class="cx">             ])
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def testScheduling(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -934,6 +934,7 @@
</span><span class="cx"> 
</span><span class="cx">         groupCacher = StubGroupCacher()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">         def decorateTransaction(txn):
</span><span class="cx">             txn._groupCacher = groupCacher
</span><span class="cx"> 
</span><span class="lines">@@ -945,15 +946,19 @@
</span><span class="cx"> 
</span><span class="cx">     testScheduling.skip = &quot;Fix WorkProposal to track delayed calls and cancel them&quot;
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class StubGroupCacher(object):
</span><span class="cx">     def __init__(self):
</span><span class="cx">         self.called = False
</span><span class="cx">         self.updateSeconds = 99
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def updateCache(self):
</span><span class="cx">         self.called = True
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class RecordsMatchingTokensTests(TestCase):
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -1038,6 +1043,7 @@
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class GUIDTests(TestCase):
</span><span class="cx"> 
</span><span class="cx">     def setUp(self):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_guidchangepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">         newUID = &quot;38D8AC00-5490-4425-BE3A-05FFB9862444&quot;
</span><span class="cx"> 
</span><span class="cx">         homeResource = &quot;/calendars/users/cdaboo/&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         def privs1(result):
</span><span class="cx">             # Change GUID in record
</span><span class="cx">             self.xmlFile.setContent(
</span><span class="lines">@@ -65,10 +65,10 @@
</span><span class="cx"> 
</span><span class="cx">             # Now force the calendar home resource to be reset
</span><span class="cx">             self.resetCalendars()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Make sure new user cannot access old user's calendar home
</span><span class="cx">             return self._checkPrivileges(None, homeResource, davxml.HRef(&quot;/principals/__uids__/&quot; + newUID + &quot;/&quot;), davxml.Write, False)
</span><del>-            
</del><ins>+
</ins><span class="cx">         # Make sure current user has access to their calendar home
</span><span class="cx">         d = self._checkPrivileges(None, homeResource, davxml.HRef(&quot;/principals/__uids__/&quot; + oldUID + &quot;/&quot;), davxml.Write, True)
</span><span class="cx">         d.addCallback(privs1)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_livedirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -142,8 +142,6 @@
</span><span class="cx">             record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestcarlene&quot;)
</span><span class="cx">             self.assertTrue(record in records)
</span><span class="cx"> 
</span><del>-
-
</del><span class="cx">     if runLDAPTests:
</span><span class="cx"> 
</span><span class="cx">         from twistedcaldav.directory.ldapdirectory import LdapDirectoryService
</span><span class="lines">@@ -196,7 +194,6 @@
</span><span class="cx">                 }
</span><span class="cx">                 self.svc = LdapDirectoryService(params)
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     if runODTests:
</span><span class="cx"> 
</span><span class="cx">         from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_modifypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx">         augmentsFile = os.path.join(testRoot, &quot;augments.xml&quot;)
</span><span class="cx">         config.AugmentService.params.xmlFiles = (augmentsFile,)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_createRecord(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -75,6 +76,7 @@
</span><span class="cx">         record = directory.recordWithUID(&quot;location01&quot;)
</span><span class="cx">         self.assertNotEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_destroyRecord(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -95,6 +97,7 @@
</span><span class="cx">         record = directory.recordWithUID(&quot;location01&quot;)
</span><span class="cx">         self.assertNotEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_updateRecord(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -124,12 +127,14 @@
</span><span class="cx">         record = directory.recordWithUID(&quot;location01&quot;)
</span><span class="cx">         self.assertNotEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_createDuplicateRecord(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="cx">         directory.createRecord(&quot;resources&quot;, guid=&quot;resource01&quot;, shortNames=(&quot;resource01&quot;,), uid=&quot;resource01&quot;)
</span><span class="cx">         self.assertRaises(DirectoryError, directory.createRecord, &quot;resources&quot;, guid=&quot;resource01&quot;, shortNames=(&quot;resource01&quot;,), uid=&quot;resource01&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_missingShortNames(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -145,6 +150,7 @@
</span><span class="cx">         self.assertEquals(record.shortNames[0], &quot;resource01&quot;)
</span><span class="cx">         self.assertEquals(record.fullName, &quot;Resource #1&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_missingGUID(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_opendirectorybackerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -21,7 +21,20 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_multiplePhoneNumbersAndEmailAddresses(self):
</span><del>-        attributes={u'dsAttrTypeStandard:AppleMetaRecordName': ['uid=odtestamanda,cn=users,dc=dalek,dc=example,dc=com'], u'dsAttrTypeStandard:ModificationTimestamp': '20111017170937Z', u'dsAttrTypeStandard:PhoneNumber': ['408 555-1212', '415 555-1212'], u'dsAttrTypeStandard:RecordType': ['dsRecTypeStandard:Users'], u'dsAttrTypeStandard:AppleMetaNodeLocation': ['/LDAPv3/127.0.0.1'], u'dsAttrTypeStandard:RecordName': ['odtestamanda'], u'dsAttrTypeStandard:FirstName': 'Amanda', u'dsAttrTypeStandard:GeneratedUID': '9DC04A70-E6DD-11DF-9492-0800200C9A66', u'dsAttrTypeStandard:LastName': 'Test', u'dsAttrTypeStandard:CreationTimestamp': '20110927182945Z', u'dsAttrTypeStandard:EMailAddress': ['amanda@example.com', 'second@example.com'], u'dsAttrTypeStandard:RealName': 'Amanda Test'}
</del><ins>+        attributes = {
+            u'dsAttrTypeStandard:AppleMetaRecordName': ['uid=odtestamanda,cn=users,dc=dalek,dc=example,dc=com'],
+            u'dsAttrTypeStandard:ModificationTimestamp': '20111017170937Z',
+            u'dsAttrTypeStandard:PhoneNumber': ['408 555-1212', '415 555-1212'],
+            u'dsAttrTypeStandard:RecordType': ['dsRecTypeStandard:Users'],
+            u'dsAttrTypeStandard:AppleMetaNodeLocation': ['/LDAPv3/127.0.0.1'],
+            u'dsAttrTypeStandard:RecordName': ['odtestamanda'],
+            u'dsAttrTypeStandard:FirstName': 'Amanda',
+            u'dsAttrTypeStandard:GeneratedUID': '9DC04A70-E6DD-11DF-9492-0800200C9A66',
+            u'dsAttrTypeStandard:LastName': 'Test',
+            u'dsAttrTypeStandard:CreationTimestamp': '20110927182945Z',
+            u'dsAttrTypeStandard:EMailAddress': ['amanda@example.com', 'second@example.com'],
+            u'dsAttrTypeStandard:RealName': 'Amanda Test',
+        }
</ins><span class="cx">         vcardRecord = VCardRecord(StubService(), attributes)
</span><span class="cx">         vcard = vcardRecord.vCard()
</span><span class="cx">         properties = set([prop.value() for prop in vcard.properties(&quot;TEL&quot;)])
</span><span class="lines">@@ -30,6 +43,7 @@
</span><span class="cx">         self.assertEquals(properties, set([&quot;amanda@example.com&quot;, &quot;second@example.com&quot;]))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class StubService(object):
</span><span class="cx">     addDSAttrXProperties = False
</span><span class="cx">     directoryBackedAddressBook = None
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_proxyprincipaldbpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.directory import calendaruserproxy
</span><del>-from twistedcaldav.directory.calendaruserproxy import ProxySqliteDB,\
</del><ins>+from twistedcaldav.directory.calendaruserproxy import ProxySqliteDB, \
</ins><span class="cx">     ProxyPostgreSQLDB
</span><span class="cx"> from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="lines">@@ -28,21 +28,21 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Directory service provisioned principals.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     class old_ProxyDB(ProxySqliteDB):
</span><del>-        
</del><ins>+
</ins><span class="cx">         def _db_version(self):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             @return: the schema version assigned to this index.
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             return &quot;3&quot;
</span><del>-            
</del><ins>+
</ins><span class="cx">         def _db_init_data_tables(self):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             Initialise the underlying database tables.
</span><span class="cx">             @param q:           a database cursor to use.
</span><span class="cx">             &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">             #
</span><span class="cx">             # GROUPS table
</span><span class="cx">             #
</span><span class="lines">@@ -55,70 +55,77 @@
</span><span class="cx">                 &quot;&quot;&quot;
</span><span class="cx">             )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     class new_ProxyDB(ProxySqliteDB):
</span><del>-        
</del><ins>+
</ins><span class="cx">         def _db_version(self):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             @return: the schema version assigned to this index.
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             return &quot;11&quot;
</span><del>-            
</del><ins>+
+
</ins><span class="cx">     class newer_ProxyDB(ProxySqliteDB):
</span><del>-        
</del><ins>+
</ins><span class="cx">         def _db_version(self):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             @return: the schema version assigned to this index.
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             return &quot;51&quot;
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_normalDB(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = ProxySqliteDB(db_path)
</span><span class="cx">         yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><del>-        
</del><ins>+
</ins><span class="cx">         membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">         membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><del>-        
</del><ins>+
</ins><span class="cx">         self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">         self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_normalDBNonAscii(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = ProxySqliteDB(db_path)
</span><span class="cx">         principalID = &quot;Test \xe4\xbd\x90\xe8\x97\xa4&quot;
</span><span class="cx">         yield db.setGroupMembers(principalID, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><del>-        
</del><ins>+
</ins><span class="cx">         membersA = yield db.getMembers(principalID)
</span><span class="cx">         membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><del>-        
</del><ins>+
</ins><span class="cx">         self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">         self.assertEqual(membershipsB, set((principalID,)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_DBIndexed(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = ProxySqliteDB(db_path)
</span><span class="cx">         self.assertEqual(set([row[1] for row in (yield db.query(&quot;PRAGMA index_list(GROUPS)&quot;))]), set((&quot;GROUPNAMES&quot;, &quot;MEMBERS&quot;)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_OldDB(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = self.old_ProxyDB(db_path)
</span><span class="cx">         self.assertEqual(set([row[1] for row in (yield db.query(&quot;PRAGMA index_list(GROUPS)&quot;))]), set())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_DBUpgrade(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = self.old_ProxyDB(db_path)
</span><span class="lines">@@ -132,7 +139,7 @@
</span><span class="cx">         self.assertEqual(set([row[1] for row in (yield db.query(&quot;PRAGMA index_list(GROUPS)&quot;))]), set())
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><del>-        
</del><ins>+
</ins><span class="cx">         db = ProxySqliteDB(db_path)
</span><span class="cx"> 
</span><span class="cx">         membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="lines">@@ -144,9 +151,10 @@
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_DBUpgradeNewer(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = self.old_ProxyDB(db_path)
</span><span class="lines">@@ -160,7 +168,7 @@
</span><span class="cx">         self.assertEqual(set([row[1] for row in (yield db.query(&quot;PRAGMA index_list(GROUPS)&quot;))]), set())
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><del>-        
</del><ins>+
</ins><span class="cx">         db = self.new_ProxyDB(db_path)
</span><span class="cx"> 
</span><span class="cx">         membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="lines">@@ -172,9 +180,10 @@
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_DBNoUpgradeNewer(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         db_path = os.path.abspath(self.mktemp())
</span><span class="cx">         db = self.new_ProxyDB(db_path)
</span><span class="lines">@@ -188,7 +197,7 @@
</span><span class="cx">         self.assertEqual(set([row[1] for row in (yield db.query(&quot;PRAGMA index_list(GROUPS)&quot;))]), set((&quot;GROUPNAMES&quot;, &quot;MEMBERS&quot;)))
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><del>-        
</del><ins>+
</ins><span class="cx">         db = self.newer_ProxyDB(db_path)
</span><span class="cx"> 
</span><span class="cx">         membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="lines">@@ -200,40 +209,41 @@
</span><span class="cx">         db.close()
</span><span class="cx">         db = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBInsert(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             db_path = os.path.abspath(self.mktemp())
</span><span class="cx">             db = ProxySqliteDB(db_path)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><span class="cx">             membershipsE = yield db.getMemberships(&quot;E&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsE, set(()))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Change and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;E&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><span class="cx">             membershipsE = yield db.getMemberships(&quot;E&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;E&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;,)))
</span><span class="lines">@@ -242,41 +252,42 @@
</span><span class="cx"> 
</span><span class="cx">             yield db.clean()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemove(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             db_path = os.path.abspath(self.mktemp())
</span><span class="cx">             db = ProxySqliteDB(db_path)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield db.removeGroup(&quot;A&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set())
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set(&quot;X&quot;,))
</span><span class="lines">@@ -285,33 +296,34 @@
</span><span class="cx"> 
</span><span class="cx">             yield db.clean()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemoveSpecial(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             db_path = os.path.abspath(self.mktemp())
</span><span class="cx">             db = ProxySqliteDB(db_path)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield db.removeGroup(&quot;A&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set())
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set(&quot;X&quot;,))
</span><span class="lines">@@ -320,41 +332,42 @@
</span><span class="cx"> 
</span><span class="cx">             yield db.clean()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemovePrincipal(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             db_path = os.path.abspath(self.mktemp())
</span><span class="cx">             db = ProxySqliteDB(db_path)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield db.removePrincipal(&quot;B&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set())
</span><span class="lines">@@ -363,29 +376,30 @@
</span><span class="cx"> 
</span><span class="cx">             yield db.clean()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBInsertUncached(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             db_path = os.path.abspath(self.mktemp())
</span><span class="cx">             db = ProxySqliteDB(db_path)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result for the one we will remove
</span><span class="cx">             yield db.setGroupMembers(&quot;AA&quot;, (&quot;BB&quot;, &quot;CC&quot;, &quot;DD&quot;,))
</span><span class="cx">             yield db.getMemberships(&quot;DD&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             # Change and check the result
</span><span class="cx">             yield db.setGroupMembers(&quot;AA&quot;, (&quot;BB&quot;, &quot;CC&quot;, &quot;EE&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersAA = yield db.getMembers(&quot;AA&quot;)
</span><span class="cx">             membershipsBB = yield db.getMemberships(&quot;BB&quot;)
</span><span class="cx">             membershipsCC = yield db.getMemberships(&quot;CC&quot;)
</span><span class="cx">             membershipsDD = yield db.getMemberships(&quot;DD&quot;)
</span><span class="cx">             membershipsEE = yield db.getMemberships(&quot;EE&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersAA, set((&quot;BB&quot;, &quot;CC&quot;, &quot;EE&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsBB, set((&quot;AA&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsCC, set((&quot;AA&quot;,)))
</span><span class="lines">@@ -394,11 +408,13 @@
</span><span class="cx"> 
</span><span class="cx">             yield db.clean()
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class ProxyPrincipalDBPostgreSQL (twistedcaldav.test.util.TestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Directory service provisioned principals.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def setUp(self):
</span><span class="cx"> 
</span><span class="lines">@@ -406,209 +422,217 @@
</span><span class="cx">         self.db = ProxyPostgreSQLDB(host=&quot;localhost&quot;, database=&quot;proxies&quot;)
</span><span class="cx">         yield self.db.clean()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def tearDown(self):
</span><span class="cx">         yield self.db.close()
</span><span class="cx">         self.db = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_normalDB(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         yield self.db.clean()
</span><del>-        
</del><ins>+
</ins><span class="cx">         calendaruserproxy.ProxyDBService = self.db
</span><span class="cx">         loader = XMLCalendarUserProxyLoader(&quot;/Volumes/Data/Users/cyrusdaboo/Documents/Development/Apple/eclipse/CalendarServer-3/conf/auth/proxies-test.xml&quot;)
</span><span class="cx">         yield loader.updateProxyDB()
</span><span class="cx"> 
</span><span class="cx">         yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><del>-        
</del><ins>+
</ins><span class="cx">         membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">         membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><del>-        
</del><ins>+
</ins><span class="cx">         self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">         self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_DBIndexed(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         # Get the DB
</span><span class="cx">         yield self.db.clean()
</span><span class="cx">         self.assertTrue((yield self.db.queryOne(&quot;select hasindexes from pg_tables where tablename = 'groups'&quot;)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBInsert(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             yield self.db.clean()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><span class="cx">             membershipsE = yield self.db.getMemberships(&quot;E&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsE, set(()))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Change and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;E&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><span class="cx">             membershipsE = yield self.db.getMemberships(&quot;E&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;E&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set())
</span><span class="cx">             self.assertEqual(membershipsE, set((&quot;A&quot;,)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemove(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             yield self.db.clean()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield self.db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield self.db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield self.db.removeGroup(&quot;A&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield self.db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set())
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set(&quot;X&quot;,))
</span><span class="cx">             self.assertEqual(membershipsC, set(&quot;X&quot;,))
</span><span class="cx">             self.assertEqual(membershipsD, set())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemoveSpecial(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             yield self.db.clean()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield self.db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield self.db.removeGroup(&quot;A&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield self.db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set())
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set(&quot;X&quot;,))
</span><span class="cx">             self.assertEqual(membershipsC, set(&quot;X&quot;,))
</span><span class="cx">             self.assertEqual(membershipsD, set())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBRemovePrincipal(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             yield self.db.clean()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;A&quot;, (&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,))
</span><span class="cx">             yield self.db.setGroupMembers(&quot;X&quot;, (&quot;B&quot;, &quot;C&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield self.db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;B&quot;, &quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;B&quot;, &quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,)))
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Remove and check the result
</span><span class="cx">             yield self.db.removePrincipal(&quot;B&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersA = yield self.db.getMembers(&quot;A&quot;)
</span><span class="cx">             membersX = yield self.db.getMembers(&quot;X&quot;)
</span><span class="cx">             membershipsB = yield self.db.getMemberships(&quot;B&quot;)
</span><span class="cx">             membershipsC = yield self.db.getMemberships(&quot;C&quot;)
</span><span class="cx">             membershipsD = yield self.db.getMemberships(&quot;D&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersA, set((&quot;C&quot;, &quot;D&quot;,)))
</span><span class="cx">             self.assertEqual(membersX, set((&quot;C&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsB, set())
</span><span class="cx">             self.assertEqual(membershipsC, set((&quot;A&quot;, &quot;X&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsD, set((&quot;A&quot;,),))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_cachingDBInsertUncached(self):
</span><del>-    
</del><ins>+
</ins><span class="cx">         for processType in (&quot;Single&quot;, &quot;Combined&quot;,):
</span><span class="cx">             config.ProcessType = processType
</span><span class="cx"> 
</span><span class="cx">             # Get the DB
</span><span class="cx">             yield self.db.clean()
</span><del>-            
</del><ins>+
</ins><span class="cx">             # Do one insert and check the result for the one we will remove
</span><span class="cx">             yield self.db.setGroupMembers(&quot;AA&quot;, (&quot;BB&quot;, &quot;CC&quot;, &quot;DD&quot;,))
</span><span class="cx">             yield self.db.getMemberships(&quot;DD&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             # Change and check the result
</span><span class="cx">             yield self.db.setGroupMembers(&quot;AA&quot;, (&quot;BB&quot;, &quot;CC&quot;, &quot;EE&quot;,))
</span><del>-    
</del><ins>+
</ins><span class="cx">             membersAA = yield self.db.getMembers(&quot;AA&quot;)
</span><span class="cx">             membershipsBB = yield self.db.getMemberships(&quot;BB&quot;)
</span><span class="cx">             membershipsCC = yield self.db.getMemberships(&quot;CC&quot;)
</span><span class="cx">             membershipsDD = yield self.db.getMemberships(&quot;DD&quot;)
</span><span class="cx">             membershipsEE = yield self.db.getMemberships(&quot;EE&quot;)
</span><del>-    
</del><ins>+
</ins><span class="cx">             self.assertEqual(membersAA, set((&quot;BB&quot;, &quot;CC&quot;, &quot;EE&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsBB, set((&quot;AA&quot;,)))
</span><span class="cx">             self.assertEqual(membershipsCC, set((&quot;AA&quot;,)))
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_resourcespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #    def test_loadConfig(self):
</span><span class="cx"> #        directory = getDirectory()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordInPrimaryDirectory(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -48,6 +49,7 @@
</span><span class="cx">         record = directory.recordWithUID(&quot;user01&quot;)
</span><span class="cx">         self.assertNotEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordInSupplementalDirectory(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span><span class="lines">@@ -55,6 +57,7 @@
</span><span class="cx">         record = directory.recordWithUID(&quot;resource01&quot;)
</span><span class="cx">         self.assertNotEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_augments(self):
</span><span class="cx">         directory = getDirectory()
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_xmlfilepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -38,49 +38,50 @@
</span><span class="cx">     ))
</span><span class="cx"> 
</span><span class="cx">     users = {
</span><del>-        &quot;admin&quot;      : { &quot;password&quot;: &quot;nimda&quot;,      &quot;guid&quot;: &quot;D11F03A0-97EA-48AF-9A6C-FAC7F3975766&quot;, &quot;addresses&quot;: () },
-        &quot;wsanchez&quot;   : { &quot;password&quot;: &quot;zehcnasw&quot;,   &quot;guid&quot;: &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot;, &quot;addresses&quot;: (&quot;mailto:wsanchez@example.com&quot;,) },
-        &quot;cdaboo&quot;     : { &quot;password&quot;: &quot;oobadc&quot;,     &quot;guid&quot;: &quot;5A985493-EE2C-4665-94CF-4DFEA3A89500&quot;, &quot;addresses&quot;: (&quot;mailto:cdaboo@example.com&quot;,)   },
-        &quot;lecroy&quot;     : { &quot;password&quot;: &quot;yorcel&quot;,     &quot;guid&quot;: &quot;8B4288F6-CC82-491D-8EF9-642EF4F3E7D0&quot;, &quot;addresses&quot;: (&quot;mailto:lecroy@example.com&quot;,)   },
-        &quot;dreid&quot;      : { &quot;password&quot;: &quot;dierd&quot;,      &quot;guid&quot;: &quot;5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1&quot;, &quot;addresses&quot;: (&quot;mailto:dreid@example.com&quot;,)    },
-        &quot;nocalendar&quot; : { &quot;password&quot;: &quot;radnelacon&quot;, &quot;guid&quot;: &quot;543D28BA-F74F-4D5F-9243-B3E3A61171E5&quot;, &quot;addresses&quot;: () },
-        &quot;user01&quot;     : { &quot;password&quot;: &quot;01user&quot;,     &quot;guid&quot;: None                                  , &quot;addresses&quot;: (&quot;mailto:c4ca4238a0@example.com&quot;,) },
-        &quot;user02&quot;     : { &quot;password&quot;: &quot;02user&quot;,     &quot;guid&quot;: None                                  , &quot;addresses&quot;: (&quot;mailto:c81e728d9d@example.com&quot;,) },
-    }
</del><ins>+        &quot;admin&quot;      : {&quot;password&quot;: &quot;nimda&quot;, &quot;guid&quot;: &quot;D11F03A0-97EA-48AF-9A6C-FAC7F3975766&quot;, &quot;addresses&quot;: ()},
+        &quot;wsanchez&quot;   : {&quot;password&quot;: &quot;zehcnasw&quot;, &quot;guid&quot;: &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot;, &quot;addresses&quot;: (&quot;mailto:wsanchez@example.com&quot;,)},
+        &quot;cdaboo&quot;     : {&quot;password&quot;: &quot;oobadc&quot;, &quot;guid&quot;: &quot;5A985493-EE2C-4665-94CF-4DFEA3A89500&quot;, &quot;addresses&quot;: (&quot;mailto:cdaboo@example.com&quot;,)  },
+        &quot;lecroy&quot;     : {&quot;password&quot;: &quot;yorcel&quot;, &quot;guid&quot;: &quot;8B4288F6-CC82-491D-8EF9-642EF4F3E7D0&quot;, &quot;addresses&quot;: (&quot;mailto:lecroy@example.com&quot;,)  },
+        &quot;dreid&quot;      : {&quot;password&quot;: &quot;dierd&quot;, &quot;guid&quot;: &quot;5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1&quot;, &quot;addresses&quot;: (&quot;mailto:dreid@example.com&quot;,)   },
+        &quot;nocalendar&quot; : {&quot;password&quot;: &quot;radnelacon&quot;, &quot;guid&quot;: &quot;543D28BA-F74F-4D5F-9243-B3E3A61171E5&quot;, &quot;addresses&quot;: ()},
+        &quot;user01&quot;     : {&quot;password&quot;: &quot;01user&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:c4ca4238a0@example.com&quot;,)},
+        &quot;user02&quot;     : {&quot;password&quot;: &quot;02user&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:c81e728d9d@example.com&quot;,)},
+   }
</ins><span class="cx"> 
</span><span class="cx">     groups = {
</span><del>-        &quot;admin&quot;      : { &quot;password&quot;: &quot;admin&quot;,       &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;managers&quot;),)},
-        &quot;managers&quot;   : { &quot;password&quot;: &quot;managers&quot;,    &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;lecroy&quot;),)},
-        &quot;grunts&quot;     : { &quot;password&quot;: &quot;grunts&quot;,      &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;wsanchez&quot;),
</del><ins>+        &quot;admin&quot;      : {&quot;password&quot;: &quot;admin&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;managers&quot;),)},
+        &quot;managers&quot;   : {&quot;password&quot;: &quot;managers&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;lecroy&quot;),)},
+        &quot;grunts&quot;     : {&quot;password&quot;: &quot;grunts&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;wsanchez&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_users , &quot;cdaboo&quot;),
</span><span class="cx">                                                                                                (DirectoryService.recordType_users , &quot;dreid&quot;))},
</span><del>-        &quot;right_coast&quot;: { &quot;password&quot;: &quot;right_coast&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;cdaboo&quot;),)},
-        &quot;left_coast&quot; : { &quot;password&quot;: &quot;left_coast&quot;,  &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;wsanchez&quot;),
</del><ins>+        &quot;right_coast&quot;: {&quot;password&quot;: &quot;right_coast&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;cdaboo&quot;),)},
+        &quot;left_coast&quot; : {&quot;password&quot;: &quot;left_coast&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;wsanchez&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_users , &quot;dreid&quot;),
</span><span class="cx">                                                                                                (DirectoryService.recordType_users , &quot;lecroy&quot;))},
</span><del>-        &quot;both_coasts&quot;: { &quot;password&quot;: &quot;both_coasts&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;right_coast&quot;),
</del><ins>+        &quot;both_coasts&quot;: {&quot;password&quot;: &quot;both_coasts&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;right_coast&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_groups, &quot;left_coast&quot;))},
</span><del>-        &quot;recursive1_coasts&quot;:  { &quot;password&quot;: &quot;recursive1_coasts&quot;,  &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;recursive2_coasts&quot;),
</del><ins>+        &quot;recursive1_coasts&quot;: {&quot;password&quot;: &quot;recursive1_coasts&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;recursive2_coasts&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_users, &quot;wsanchez&quot;))},
</span><del>-        &quot;recursive2_coasts&quot;:  { &quot;password&quot;: &quot;recursive2_coasts&quot;,  &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;recursive1_coasts&quot;),
</del><ins>+        &quot;recursive2_coasts&quot;: {&quot;password&quot;: &quot;recursive2_coasts&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_groups, &quot;recursive1_coasts&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_users, &quot;cdaboo&quot;))},
</span><del>-        &quot;non_calendar_group&quot;: { &quot;password&quot;: &quot;non_calendar_group&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;cdaboo&quot;),
</del><ins>+        &quot;non_calendar_group&quot;: {&quot;password&quot;: &quot;non_calendar_group&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (), &quot;members&quot;: ((DirectoryService.recordType_users , &quot;cdaboo&quot;),
</ins><span class="cx">                                                                                                (DirectoryService.recordType_users , &quot;lecroy&quot;))},
</span><del>-    }
</del><ins>+   }
</ins><span class="cx"> 
</span><span class="cx">     locations = {
</span><del>-        &quot;mercury&quot;: { &quot;password&quot;: &quot;mercury&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:mercury@example.com&quot;,) },
-        &quot;gemini&quot; : { &quot;password&quot;: &quot;gemini&quot;,  &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:gemini@example.com&quot;,)  },
-        &quot;apollo&quot; : { &quot;password&quot;: &quot;apollo&quot;,  &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:apollo@example.com&quot;,)  },
-        &quot;orion&quot;  : { &quot;password&quot;: &quot;orion&quot;,   &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:orion@example.com&quot;,)   },
-    }
</del><ins>+        &quot;mercury&quot;: {&quot;password&quot;: &quot;mercury&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:mercury@example.com&quot;,)},
+        &quot;gemini&quot; : {&quot;password&quot;: &quot;gemini&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:gemini@example.com&quot;,)},
+        &quot;apollo&quot; : {&quot;password&quot;: &quot;apollo&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:apollo@example.com&quot;,)},
+        &quot;orion&quot;  : {&quot;password&quot;: &quot;orion&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:orion@example.com&quot;,)},
+   }
</ins><span class="cx"> 
</span><span class="cx">     resources = {
</span><del>-        &quot;transporter&quot;        : { &quot;password&quot;: &quot;transporter&quot;,        &quot;guid&quot;: None,                 &quot;addresses&quot;: (&quot;mailto:transporter@example.com&quot;,)        },
-        &quot;ftlcpu&quot;             : { &quot;password&quot;: &quot;ftlcpu&quot;,             &quot;guid&quot;: None,                 &quot;addresses&quot;: (&quot;mailto:ftlcpu@example.com&quot;,)             },
-        &quot;non_calendar_proxy&quot; : { &quot;password&quot;: &quot;non_calendar_proxy&quot;, &quot;guid&quot;: &quot;non_calendar_proxy&quot;, &quot;addresses&quot;: (&quot;mailto:non_calendar_proxy@example.com&quot;,) },
-    }
</del><ins>+        &quot;transporter&quot;        : {&quot;password&quot;: &quot;transporter&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:transporter@example.com&quot;,)       },
+        &quot;ftlcpu&quot;             : {&quot;password&quot;: &quot;ftlcpu&quot;, &quot;guid&quot;: None, &quot;addresses&quot;: (&quot;mailto:ftlcpu@example.com&quot;,)            },
+        &quot;non_calendar_proxy&quot; : {&quot;password&quot;: &quot;non_calendar_proxy&quot;, &quot;guid&quot;: &quot;non_calendar_proxy&quot;, &quot;addresses&quot;: (&quot;mailto:non_calendar_proxy@example.com&quot;,)},
+   }
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def xmlFile(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Create a L{FilePath} that points to a temporary file containing a copy
</span><span class="lines">@@ -155,10 +156,10 @@
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx">         )
</span><span class="cx">         for recordType, expectedRecords in (
</span><del>-            ( DirectoryService.recordType_users     , (&quot;admin&quot;,) ),
-            ( DirectoryService.recordType_groups    , ()         ),
-            ( DirectoryService.recordType_locations , ()         ),
-            ( DirectoryService.recordType_resources , ()         ),
</del><ins>+            (DirectoryService.recordType_users     , (&quot;admin&quot;,)),
+            (DirectoryService.recordType_groups    , ()),
+            (DirectoryService.recordType_locations , ()),
+            (DirectoryService.recordType_resources , ()),
</ins><span class="cx">         ):
</span><span class="cx">             # Fault records in
</span><span class="cx">             for name in expectedRecords:
</span><span class="lines">@@ -169,6 +170,7 @@
</span><span class="cx">                 set(expectedRecords)
</span><span class="cx">             )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_okAutoSchedule(self):
</span><span class="cx">         service = self.service()
</span><span class="cx"> 
</span><span class="lines">@@ -201,10 +203,10 @@
</span><span class="cx">         service.augmentService.refresh()
</span><span class="cx"> 
</span><span class="cx">         for recordType, expectedRecords in (
</span><del>-            ( DirectoryService.recordType_users     , ()             ),
-            ( DirectoryService.recordType_groups    , ()             ),
-            ( DirectoryService.recordType_locations , (&quot;my office&quot;,) ),
-            ( DirectoryService.recordType_resources , ()             ),
</del><ins>+            (DirectoryService.recordType_users     , ()),
+            (DirectoryService.recordType_groups    , ()),
+            (DirectoryService.recordType_locations , (&quot;my office&quot;,)),
+            (DirectoryService.recordType_resources , ()),
</ins><span class="cx">         ):
</span><span class="cx">             # Fault records in
</span><span class="cx">             for name in expectedRecords:
</span><span class="lines">@@ -239,12 +241,12 @@
</span><span class="cx"> &lt;/accounts&gt;
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx">         )
</span><del>-        
</del><ins>+
</ins><span class="cx">         for recordType, expectedRecords in (
</span><del>-            ( DirectoryService.recordType_users     , ()                       ),
-            ( DirectoryService.recordType_groups    , (&quot;enabled&quot;, &quot;disabled&quot;)  ),
-            ( DirectoryService.recordType_locations , ()                       ),
-            ( DirectoryService.recordType_resources , ()                       ),
</del><ins>+            (DirectoryService.recordType_users     , ()),
+            (DirectoryService.recordType_groups    , (&quot;enabled&quot;, &quot;disabled&quot;)),
+            (DirectoryService.recordType_locations , ()),
+            (DirectoryService.recordType_resources , ()),
</ins><span class="cx">         ):
</span><span class="cx">             # Fault records in
</span><span class="cx">             for name in expectedRecords:
</span><span class="lines">@@ -279,13 +281,14 @@
</span><span class="cx"> &lt;/accounts&gt;
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx">         )
</span><del>-        
</del><ins>+
</ins><span class="cx">         record = service.recordWithShortName(
</span><span class="cx">             DirectoryService.recordType_locations, &quot;my office&quot;)
</span><span class="cx">         self.assertEquals(record.guid, &quot;myoffice&quot;)
</span><span class="cx">         self.assertEquals(record.extras[&quot;comment&quot;], &quot;This is the comment&quot;)
</span><span class="cx">         self.assertEquals(record.extras[&quot;capacity&quot;], &quot;40&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_writeExtras(self):
</span><span class="cx">         service = self.service()
</span><span class="cx"> 
</span><span class="lines">@@ -302,7 +305,6 @@
</span><span class="cx">         self.assertEquals(record.extras[&quot;comment&quot;], &quot;Test comment&quot;)
</span><span class="cx">         self.assertEquals(record.extras[&quot;capacity&quot;], &quot;10&quot;)
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         service.updateRecord(DirectoryService.recordType_locations, &quot;newguid&quot;,
</span><span class="cx">             shortNames=(&quot;New office&quot;,),
</span><span class="cx">             fullName=&quot;My Newer Office&quot;,
</span><span class="lines">@@ -333,6 +335,7 @@
</span><span class="cx">         self.assertNotEquals(None, service._lookupInIndex(service.recordType_locations, service.INDEX_TYPE_SHORTNAME, &quot;orion&quot;))
</span><span class="cx">         self.assertEquals(None, service._lookupInIndex(service.recordType_users, service.INDEX_TYPE_CUA, &quot;mailto:nobody@example.com&quot;))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_repeat(self):
</span><span class="cx">         service = self.service()
</span><span class="cx">         record = service.recordWithShortName(
</span><span class="lines">@@ -342,6 +345,8 @@
</span><span class="cx">         self.assertEquals(record.lastName, &quot;c4ca4238a User 01&quot;)
</span><span class="cx">         self.assertEquals(record.emailAddresses, set(['c4ca4238a0@example.com']))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class XMLFileSubset (XMLFileBase, TestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Test the recordTypes subset feature of XMLFile service.
</span><span class="lines">@@ -351,6 +356,7 @@
</span><span class="cx">         DirectoryService.recordType_groups,
</span><span class="cx">     ))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordTypesSubset(self):
</span><span class="cx">         directory = XMLDirectoryService(
</span><span class="cx">             {
</span><span class="lines">@@ -366,4 +372,3 @@
</span><span class="cx">             alwaysStat=True
</span><span class="cx">         )
</span><span class="cx">         self.assertEquals(set((&quot;users&quot;, &quot;groups&quot;)), set(directory.recordTypes()))
</span><del>-    
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/util.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/util.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/directory/test/util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -54,12 +54,14 @@
</span><span class="cx">     # For aggregator subclasses
</span><span class="cx">     recordTypePrefixes = (&quot;&quot;,)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_realm(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.realm
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         self.failUnless(self.service().realmName)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordTypes(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.recordTypes()
</span><span class="lines">@@ -69,15 +71,16 @@
</span><span class="cx"> 
</span><span class="cx">         self.assertEquals(set(self.service().recordTypes()), self.recordTypes)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordWithShortName(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.recordWithShortName()
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         for recordType, data in (
</span><del>-            ( DirectoryService.recordType_users    , self.users     ),
-            ( DirectoryService.recordType_groups   , self.groups    ),
-            ( DirectoryService.recordType_locations, self.locations ),
-            ( DirectoryService.recordType_resources, self.resources ),
</del><ins>+            (DirectoryService.recordType_users    , self.users),
+            (DirectoryService.recordType_groups   , self.groups),
+            (DirectoryService.recordType_locations, self.locations),
+            (DirectoryService.recordType_resources, self.resources),
</ins><span class="cx">         ):
</span><span class="cx">             if not data:
</span><span class="cx">                 raise SkipTest(&quot;No %s&quot; % (recordType,))
</span><span class="lines">@@ -95,6 +98,7 @@
</span><span class="cx">                     continue
</span><span class="cx">                 self.assertEquals(record, None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordWithUID(self):
</span><span class="cx">         service = self.service()
</span><span class="cx">         record = None
</span><span class="lines">@@ -108,6 +112,7 @@
</span><span class="cx">         if record is None:
</span><span class="cx">             raise SkipTest(&quot;No GUIDs provided to test&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_recordWithCalendarUserAddress(self):
</span><span class="cx">         service = self.service()
</span><span class="cx">         record = None
</span><span class="lines">@@ -120,6 +125,7 @@
</span><span class="cx">         if record is None:
</span><span class="cx">             raise SkipTest(&quot;No calendar user addresses provided to test&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_groupMembers(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryRecord.members()
</span><span class="lines">@@ -138,6 +144,7 @@
</span><span class="cx">                 &quot;Wrong membership for group %r: %s != %s&quot; % (group, result, expected)
</span><span class="cx">             )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_groupMemberships(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryRecord.groups()
</span><span class="lines">@@ -148,8 +155,8 @@
</span><span class="cx">             raise SkipTest(&quot;No groups&quot;)
</span><span class="cx"> 
</span><span class="cx">         for recordType, data in (
</span><del>-            ( DirectoryService.recordType_users , self.users  ),
-            ( DirectoryService.recordType_groups, self.groups ),
</del><ins>+            (DirectoryService.recordType_users , self.users),
+            (DirectoryService.recordType_groups, self.groups),
</ins><span class="cx">         ):
</span><span class="cx">             service = self.service()
</span><span class="cx">             for shortName, info in data.iteritems():
</span><span class="lines">@@ -162,6 +169,7 @@
</span><span class="cx">                     &quot;Wrong groups for %s %r: %s != %s&quot; % (record.recordType, shortName, result, expected)
</span><span class="cx">                 )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def recordNames(self, recordType):
</span><span class="cx">         service = self.service()
</span><span class="cx">         names = set()
</span><span class="lines">@@ -176,16 +184,18 @@
</span><span class="cx"> 
</span><span class="cx">         return names
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def allEntries(self):
</span><span class="cx">         for data, _ignore_recordType in (
</span><del>-            (self.users,     DirectoryService.recordType_users    ),
-            (self.groups,    DirectoryService.recordType_groups   ),
</del><ins>+            (self.users, DirectoryService.recordType_users),
+            (self.groups, DirectoryService.recordType_groups),
</ins><span class="cx">             (self.locations, DirectoryService.recordType_locations),
</span><span class="cx">             (self.resources, DirectoryService.recordType_resources),
</span><span class="cx">         ):
</span><span class="cx">             for item in data.iteritems():
</span><span class="cx">                 yield item
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def compare(self, record, shortName, data):
</span><span class="cx">         def value(key):
</span><span class="cx">             if key in data:
</span><span class="lines">@@ -217,6 +227,7 @@
</span><span class="cx">         if value(&quot;name&quot;):
</span><span class="cx">             self.assertEquals(record.fullName, value(&quot;name&quot;))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def servicePrefix(self):
</span><span class="cx">         service = self.service()
</span><span class="cx">         if hasattr(service, &quot;recordTypePrefix&quot;):
</span><span class="lines">@@ -224,6 +235,8 @@
</span><span class="cx">         else:
</span><span class="cx">             return &quot;&quot;
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class NonCachingTestCase (DirectoryTestCase):
</span><span class="cx"> 
</span><span class="cx">     def test_listRecords_user(self):
</span><span class="lines">@@ -235,6 +248,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.assertEquals(self.recordNames(DirectoryService.recordType_users), set(self.users.keys()))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_listRecords_group(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.listRecords(DirectoryService.recordType_groups)
</span><span class="lines">@@ -244,6 +258,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.assertEquals(self.recordNames(DirectoryService.recordType_groups), set(self.groups.keys()))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_listRecords_locations(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.listRecords(&quot;locations&quot;)
</span><span class="lines">@@ -253,6 +268,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.assertEquals(self.recordNames(DirectoryService.recordType_locations), set(self.locations.keys()))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_listRecords_resources(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         IDirectoryService.listRecords(&quot;resources&quot;)
</span><span class="lines">@@ -263,6 +279,7 @@
</span><span class="cx">         self.assertEquals(self.recordNames(DirectoryService.recordType_resources), set(self.resources.keys()))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class BasicTestCase (DirectoryTestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Tests a directory implementation with basic auth.
</span><span class="lines">@@ -279,6 +296,8 @@
</span><span class="cx">             userRecord = service.recordWithShortName(DirectoryService.recordType_users, user)
</span><span class="cx">             self.failUnless(userRecord.verifyCredentials(UsernamePassword(user, self.users[user][&quot;password&quot;])))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> # authRequest = {
</span><span class="cx"> #    username=&quot;username&quot;,
</span><span class="cx"> #    realm=&quot;test realm&quot;,
</span><span class="lines">@@ -351,6 +370,8 @@
</span><span class="cx">                 else:
</span><span class="cx">                     self.failIf(userRecord.verifyCredentials(credentials))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def maybeCommit(req):
</span><span class="cx">     class JustForCleanup(object):
</span><span class="cx">         def newTransaction(self, *whatever):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdropboxpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/dropbox.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/dropbox.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/dropbox.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -44,12 +44,15 @@
</span><span class="cx">     def resourceType(self):
</span><span class="cx">         return davxml.ResourceType.dropboxhome #@UndefinedVariable
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return True
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def http_PUT(self, request):
</span><span class="cx">         return responsecode.FORBIDDEN
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def accessControlList(self, request, *args, **kwargs):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -57,7 +60,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         acl = (yield super(DropBoxHomeResource, self).accessControlList(request, *args, **kwargs))
</span><del>-        
</del><ins>+
</ins><span class="cx">         if config.EnableProxyPrincipals:
</span><span class="cx">             owner = (yield self.ownerPrincipal(request))
</span><span class="cx"> 
</span><span class="lines">@@ -75,10 +78,12 @@
</span><span class="cx">             )
</span><span class="cx"> 
</span><span class="cx">             returnValue(davxml.ACL(*newaces))
</span><del>-        
</del><ins>+
</ins><span class="cx">         else:
</span><span class="cx">             returnValue(acl)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class DropBoxCollectionResource (DAVResource):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Drop box resource.
</span><span class="lines">@@ -99,7 +104,7 @@
</span><span class="cx">         calendar collection have the same privileges unless explicitly overridden. The same applies
</span><span class="cx">         to drop box collections as we want all resources (attachments) to have the same privileges as
</span><span class="cx">         the drop box collection.
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param newaces: C{list} of L{ACE} for ACL being set.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # Add inheritable option to each ACE in the list
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavfreebusyurlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/freebusyurl.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/freebusyurl.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/freebusyurl.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -47,8 +47,8 @@
</span><span class="cx"> from txdav.caldav.datastore.scheduling.cuaddress import LocalCalendarUser
</span><span class="cx"> from txdav.caldav.datastore.scheduling.scheduler import Scheduler
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -189,15 +189,15 @@
</span><span class="cx">         # Start/end/duration must be valid iCalendar DATE-TIME UTC or DURATION values
</span><span class="cx">         try:
</span><span class="cx">             if self.start:
</span><del>-                self.start = PyCalendarDateTime.parseText(self.start)
</del><ins>+                self.start = DateTime.parseText(self.start)
</ins><span class="cx">                 if not self.start.utc():
</span><span class="cx">                     raise ValueError()
</span><span class="cx">             if self.end:
</span><del>-                self.end = PyCalendarDateTime.parseText(self.end)
</del><ins>+                self.end = DateTime.parseText(self.end)
</ins><span class="cx">                 if not self.end.utc():
</span><span class="cx">                     raise ValueError()
</span><span class="cx">             if self.duration:
</span><del>-                self.duration = PyCalendarDuration.parseText(self.duration)
</del><ins>+                self.duration = Duration.parseText(self.duration)
</ins><span class="cx">         except ValueError:
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.BAD_REQUEST,
</span><span class="lines">@@ -225,12 +225,12 @@
</span><span class="cx"> 
</span><span class="cx">         # Now fill in the missing pieces
</span><span class="cx">         if self.start is None:
</span><del>-            self.start = PyCalendarDateTime.getNowUTC()
</del><ins>+            self.start = DateTime.getNowUTC()
</ins><span class="cx">             self.start.setHHMMSS(0, 0, 0)
</span><span class="cx">         if self.duration:
</span><span class="cx">             self.end = self.start + self.duration
</span><span class="cx">         if self.end is None:
</span><del>-            self.end = self.start + PyCalendarDuration(days=config.FreeBusyURL.TimePeriod)
</del><ins>+            self.end = self.start + Duration(days=config.FreeBusyURL.TimePeriod)
</ins><span class="cx"> 
</span><span class="cx">         # End &gt; start
</span><span class="cx">         if self.end &lt;= self.start:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavicalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/ical.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/ical.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/ical.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -28,7 +28,6 @@
</span><span class="cx">     &quot;tzexpand&quot;,
</span><span class="cx"> ]
</span><span class="cx"> 
</span><del>-import cStringIO as StringIO
</del><span class="cx"> import codecs
</span><span class="cx"> from difflib import unified_diff
</span><span class="cx"> import heapq
</span><span class="lines">@@ -46,31 +45,34 @@
</span><span class="cx"> from txdav.caldav.datastore.scheduling.cuaddress import normalizeCUAddr
</span><span class="cx"> from twistedcaldav.timezones import hasTZ, TimezoneException
</span><span class="cx"> 
</span><del>-from pycalendar import definitions
-from pycalendar.attribute import PyCalendarAttribute
-from pycalendar.calendar import PyCalendar
-from pycalendar.componentbase import PyCalendarComponentBase
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.exceptions import PyCalendarError
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.property import PyCalendarProperty
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.utcoffsetvalue import PyCalendarUTCOffsetValue
</del><ins>+from pycalendar.icalendar import definitions
+from pycalendar.parameter import Parameter
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.icalendar.component import Component as PyComponent
+from pycalendar.componentbase import ComponentBase
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.exceptions import ErrorBase
+from pycalendar.period import Period
+from pycalendar.icalendar.property import Property as PyProperty
+from pycalendar.timezone import Timezone
+from pycalendar.utcoffsetvalue import UTCOffsetValue
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="cx"> iCalendarProductID = &quot;-//CALENDARSERVER.ORG//NONSGML Version 1//EN&quot;
</span><span class="cx"> 
</span><del>-allowedComponents = (
-    &quot;VEVENT&quot;,
-    &quot;VTODO&quot;,
-    &quot;VTIMEZONE&quot;,
-    # &quot;VJOURNAL&quot;,
-    &quot;VFREEBUSY&quot;,
-    # &quot;VAVAILABILITY&quot;,
-)
</del><ins>+allowedStoreComponents = (&quot;VEVENT&quot;, &quot;VTODO&quot;, &quot;VPOLL&quot;,)
+allowedSchedulingComponents = allowedStoreComponents + (&quot;VFREEBUSY&quot;,)
+allowedComponents = allowedSchedulingComponents + (&quot;VTIMEZONE&quot;,)
</ins><span class="cx"> 
</span><ins>+def _updateAllowedComponents(allowed):
+    global allowedStoreComponents, allowedSchedulingComponents, allowedComponents
+    allowedStoreComponents = allowed
+    allowedSchedulingComponents = allowedStoreComponents + (&quot;VFREEBUSY&quot;,)
+    allowedComponents = allowedSchedulingComponents + (&quot;VTIMEZONE&quot;,)
+
+
</ins><span class="cx"> # Additional per-user data components - see datafilters.peruserdata.py for details
</span><span class="cx"> PERUSER_COMPONENT = &quot;X-CALENDARSERVER-PERUSER&quot;
</span><span class="cx"> PERUSER_UID = &quot;X-CALENDARSERVER-PERUSER-UID&quot;
</span><span class="lines">@@ -134,19 +136,28 @@
</span><span class="cx">     &quot;LAST-MODIFIED&quot;: (None, {&quot;VALUE&quot;: &quot;DATE-TIME&quot;}),
</span><span class="cx">     &quot;SEQUENCE&quot;: (0, {&quot;VALUE&quot;: &quot;INTEGER&quot;}),
</span><span class="cx">     &quot;REQUEST-STATUS&quot;: (None, {&quot;VALUE&quot;: &quot;TEXT&quot;}),
</span><ins>+
+    &quot;VOTER&quot;: (None, {
+        &quot;VALUE&quot;: &quot;CAL-ADDRESS&quot;,
+        &quot;CUTYPE&quot;: &quot;INDIVIDUAL&quot;,
+        &quot;ROLE&quot;: &quot;REQ-PARTICIPANT&quot;,
+        &quot;RSVP&quot;: &quot;FALSE&quot;,
+        &quot;SCHEDULE-AGENT&quot;: &quot;SERVER&quot;,
+    }),
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> # transformations to apply to property values
</span><span class="cx"> normalizePropsValue = {
</span><span class="cx">     &quot;ATTENDEE&quot;: normalizeCUAddr,
</span><span class="cx">     &quot;ORGANIZER&quot;: normalizeCUAddr,
</span><ins>+    &quot;VOTER&quot;: normalizeCUAddr,
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ignoredComponents = (&quot;VTIMEZONE&quot;, PERUSER_COMPONENT,)
</span><span class="cx"> 
</span><span class="cx"> # Used for min/max time-range query limits
</span><del>-minDateTime = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-maxDateTime = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+minDateTime = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+maxDateTime = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx"> 
</span><span class="cx"> class InvalidICalendarDataError(ValueError):
</span><span class="cx">     pass
</span><span class="lines">@@ -170,16 +181,16 @@
</span><span class="cx"> 
</span><span class="cx">             pyobj = kwargs[&quot;pycalendar&quot;]
</span><span class="cx"> 
</span><del>-            if not isinstance(pyobj, PyCalendarProperty):
-                raise TypeError(&quot;Not a PyCalendarProperty: %r&quot; % (property,))
</del><ins>+            if not isinstance(pyobj, PyProperty):
+                raise TypeError(&quot;Not a Property: %r&quot; % (property,))
</ins><span class="cx"> 
</span><span class="cx">             self._pycalendar = pyobj
</span><span class="cx">         else:
</span><span class="cx">             # Convert params dictionary to list of lists format used by pycalendar
</span><span class="cx">             valuetype = kwargs.get(&quot;valuetype&quot;)
</span><del>-            self._pycalendar = PyCalendarProperty(name, value, valuetype=valuetype)
</del><ins>+            self._pycalendar = PyProperty(name, value, valuetype=valuetype)
</ins><span class="cx">             for attrname, attrvalue in params.items():
</span><del>-                self._pycalendar.addAttribute(PyCalendarAttribute(attrname, attrvalue))
</del><ins>+                self._pycalendar.addParameter(Parameter(attrname, attrvalue))
</ins><span class="cx"> 
</span><span class="cx">         self._parent = parent
</span><span class="cx"> 
</span><span class="lines">@@ -267,7 +278,7 @@
</span><span class="cx">         Returns a set containing parameter names for this property.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         result = set()
</span><del>-        for pyattrlist in self._pycalendar.getAttributes().values():
</del><ins>+        for pyattrlist in self._pycalendar.getParameters().values():
</ins><span class="cx">             for pyattr in pyattrlist:
</span><span class="cx">                 result.add(pyattr.getName())
</span><span class="cx">         return result
</span><span class="lines">@@ -279,27 +290,27 @@
</span><span class="cx">         InvalidICalendarDataError if the parameter has more than one value.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         try:
</span><del>-            return self._pycalendar.getAttributeValue(name)
</del><ins>+            return self._pycalendar.getParameterValue(name)
</ins><span class="cx">         except KeyError:
</span><span class="cx">             return default
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def hasParameter(self, paramname):
</span><del>-        return self._pycalendar.hasAttribute(paramname)
</del><ins>+        return self._pycalendar.hasParameter(paramname)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def setParameter(self, paramname, paramvalue):
</span><del>-        self._pycalendar.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
</del><ins>+        self._pycalendar.replaceParameter(Parameter(paramname, paramvalue))
</ins><span class="cx">         self._markAsDirty()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def removeParameter(self, paramname):
</span><del>-        self._pycalendar.removeAttributes(paramname)
</del><ins>+        self._pycalendar.removeParameters(paramname)
</ins><span class="cx">         self._markAsDirty()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def removeAllParameters(self):
</span><del>-        self._pycalendar.setAttributes({})
</del><ins>+        self._pycalendar.setParameters({})
</ins><span class="cx">         self._markAsDirty()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -308,11 +319,11 @@
</span><span class="cx">         paramname = paramname.upper()
</span><span class="cx">         for attrName in self.parameterNames():
</span><span class="cx">             if attrName.upper() == paramname:
</span><del>-                for attr in tuple(self._pycalendar.getAttributes()[attrName]):
</del><ins>+                for attr in tuple(self._pycalendar.getParameters()[attrName]):
</ins><span class="cx">                     for value in attr.getValues():
</span><span class="cx">                         if value == paramvalue:
</span><span class="cx">                             if not attr.removeValue(value):
</span><del>-                                self._pycalendar.removeAttributes(paramname)
</del><ins>+                                self._pycalendar.removeParameters(paramname)
</ins><span class="cx">         self._markAsDirty()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -322,8 +333,8 @@
</span><span class="cx">         start/end period.
</span><span class="cx">         The only properties allowed for this query are: COMPLETED, CREATED, DTSTAMP and
</span><span class="cx">         LAST-MODIFIED (caldav -09).
</span><del>-        @param start: a L{PyCalendarDateTime} specifying the beginning of the given time span.
-        @param end: a L{PyCalendarDateTime} specifying the end of the given time span.
</del><ins>+        @param start: a L{DateTime} specifying the beginning of the given time span.
+        @param end: a L{DateTime} specifying the end of the given time span.
</ins><span class="cx">             C{end} may be None, indicating that there is no end date.
</span><span class="cx">         @param defaulttz: the default L{PyTimezone} to use in datetime comparisons.
</span><span class="cx">         @return: True if the property's date/date-time value is within the given time range,
</span><span class="lines">@@ -337,7 +348,7 @@
</span><span class="cx"> 
</span><span class="cx">         # get date/date-time value
</span><span class="cx">         dt = self._pycalendar.getValue().getValue()
</span><del>-        assert isinstance(dt, PyCalendarDateTime), &quot;Not a date/date-time value: %r&quot; % (self,)
</del><ins>+        assert isinstance(dt, DateTime), &quot;Not a date/date-time value: %r&quot; % (self,)
</ins><span class="cx"> 
</span><span class="cx">         return timeRangesOverlap(dt, None, start, end, defaulttz)
</span><span class="cx"> 
</span><span class="lines">@@ -375,66 +386,95 @@
</span><span class="cx">     # Hidden instance.
</span><span class="cx">     HIDDEN_INSTANCE_PROPERTY = &quot;X-CALENDARSERVER-HIDDEN-INSTANCE&quot;
</span><span class="cx"> 
</span><ins>+    allowedTypesList = None
+
+
</ins><span class="cx">     @classmethod
</span><del>-    def allFromString(clazz, string):
</del><ins>+    def allowedTypes(cls):
+        if cls.allowedTypesList is None:
+            cls.allowedTypesList = [&quot;text/calendar&quot;]
+            if config.EnableJSONData:
+                cls.allowedTypesList.append(&quot;application/calendar+json&quot;)
+        return cls.allowedTypesList
+
+
+    @classmethod
+    def allFromString(clazz, string, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Just default to reading a single VCALENDAR
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        return clazz.fromString(string)
</del><ins>+        return clazz.fromString(string, format)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def allFromStream(clazz, stream):
</del><ins>+    def allFromStream(clazz, stream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Just default to reading a single VCALENDAR
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        return clazz.fromStream(stream)
</del><ins>+        return clazz.fromStream(stream, format)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def fromString(clazz, string):
</del><ins>+    def fromString(clazz, string, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a string.
</span><span class="cx">         @param string: a string containing iCalendar data.
</span><span class="cx">         @return: a L{Component} representing the first component described by
</span><span class="cx">             C{string}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if type(string) is unicode:
-            string = string.encode(&quot;utf-8&quot;)
-        else:
-            # Valid utf-8 please
-            string.decode(&quot;utf-8&quot;)
</del><ins>+        return clazz._fromData(string, False, format)
</ins><span class="cx"> 
</span><del>-        # No BOMs please
-        if string[:3] == codecs.BOM_UTF8:
-            string = string[3:]
</del><span class="cx"> 
</span><del>-        return clazz.fromStream(StringIO.StringIO(string))
</del><ins>+    @classmethod
+    def fromStream(clazz, stream, format=None):
+        &quot;&quot;&quot;
+        Construct a L{Component} from a stream.
+        @param stream: a C{read()}able stream containing iCalendar data.
+        @return: a L{Component} representing the first component described by
+            C{stream}.
+        &quot;&quot;&quot;
+        return clazz._fromData(stream, True, format)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def fromStream(clazz, stream):
</del><ins>+    def _fromData(clazz, data, isstream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a stream.
</span><span class="cx">         @param stream: a C{read()}able stream containing iCalendar data.
</span><ins>+        @param format: a C{str} indicating whether the data is iCalendar or jCal
</ins><span class="cx">         @return: a L{Component} representing the first component described by
</span><span class="cx">             C{stream}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        cal = PyCalendar()
</del><ins>+
+        if isstream:
+            pass
+        else:
+            if type(data) is unicode:
+                data = data.encode(&quot;utf-8&quot;)
+            else:
+                # Valid utf-8 please
+                data.decode(&quot;utf-8&quot;)
+
+            # No BOMs please
+            if data[:3] == codecs.BOM_UTF8:
+                data = data[3:]
+
</ins><span class="cx">         errmsg = &quot;Unknown&quot;
</span><span class="cx">         try:
</span><del>-            result = cal.parse(stream)
-        except PyCalendarError, e:
</del><ins>+            result = Calendar.parseData(data, format)
+        except ErrorBase, e:
</ins><span class="cx">             errmsg = &quot;%s: %s&quot; % (e.mReason, e.mData,)
</span><span class="cx">             result = None
</span><span class="cx">         if not result:
</span><del>-            stream.seek(0)
-            raise InvalidICalendarDataError(&quot;%s\n%s&quot; % (errmsg, stream.read(),))
-        return clazz(None, pycalendar=cal)
</del><ins>+            if isstream:
+                data.seek(0)
+                data = data.read()
+            raise InvalidICalendarDataError(&quot;%s\n%s&quot; % (errmsg, data,))
+        return clazz(None, pycalendar=result)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def fromIStream(clazz, stream):
</del><ins>+    def fromIStream(clazz, stream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a stream.
</span><span class="cx">         @param stream: an L{IStream} containing iCalendar data.
</span><span class="lines">@@ -448,7 +488,7 @@
</span><span class="cx">         #   request stream.
</span><span class="cx">         #
</span><span class="cx">         def parse(data):
</span><del>-            return clazz.fromString(data)
</del><ins>+            return clazz.fromString(data, format)
</ins><span class="cx">         return allDataFromStream(IStream(stream), parse)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -480,8 +520,8 @@
</span><span class="cx">                 pyobj = kwargs[&quot;pycalendar&quot;]
</span><span class="cx"> 
</span><span class="cx">                 if pyobj is not None:
</span><del>-                    if not isinstance(pyobj, PyCalendarComponentBase):
-                        raise TypeError(&quot;Not a PyCalendarComponentBase: %r&quot; % (pyobj,))
</del><ins>+                    if not isinstance(pyobj, ComponentBase):
+                        raise TypeError(&quot;Not a ComponentBase: %r&quot; % (pyobj,))
</ins><span class="cx"> 
</span><span class="cx">                 self._pycalendar = pyobj
</span><span class="cx">             else:
</span><span class="lines">@@ -499,7 +539,7 @@
</span><span class="cx">                 self._parent = None
</span><span class="cx">         else:
</span><span class="cx">             # FIXME: figure out creating an arbitrary component
</span><del>-            self._pycalendar = PyCalendar(add_defaults=False) if name == &quot;VCALENDAR&quot; else PyCalendar.makeComponent(name, None)
</del><ins>+            self._pycalendar = Calendar(add_defaults=False) if name == &quot;VCALENDAR&quot; else PyComponent.makeComponent(name, None)
</ins><span class="cx">             self._parent = None
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -542,13 +582,20 @@
</span><span class="cx">         return self._pycalendar == other._pycalendar
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def getTextWithTimezones(self, includeTimezones):
</del><ins>+    def getText(self, format=None):
+        return self.getTextWithTimezones(False, format)
+
+
+    def getTextWithTimezones(self, includeTimezones, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><del>-        Return text representation and include timezones if the option is on
</del><ins>+        Return text representation and include timezones if the option is on.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         assert self.name() == &quot;VCALENDAR&quot;, &quot;Must be a VCALENDAR: %r&quot; % (self,)
</span><span class="cx"> 
</span><del>-        return self._pycalendar.getText(includeTimezones=includeTimezones)
</del><ins>+        result = self._pycalendar.getText(includeTimezones=includeTimezones, format=format)
+        if result is None:
+            raise ValueError(&quot;Unknown format requested for calendar data.&quot;)
+        return result
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     # FIXME: Should this not be in __eq__?
</span><span class="lines">@@ -627,14 +674,14 @@
</span><span class="cx">         This also returns the matching master component if recurrence_id is C{None}.
</span><span class="cx"> 
</span><span class="cx">         @param recurrence_id: The RECURRENCE-ID property value to match.
</span><del>-        @type recurrence_id: L{PyCalendarDateTime}
</del><ins>+        @type recurrence_id: L{DateTime}
</ins><span class="cx">         @return: the L{Component} for the overridden component,
</span><span class="cx">             or C{None} if there isn't one.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         assert self.name() == &quot;VCALENDAR&quot;, &quot;Must be a VCALENDAR: %r&quot; % (self,)
</span><span class="cx"> 
</span><span class="cx">         if isinstance(recurrence_id, str):
</span><del>-            recurrence_id = PyCalendarDateTime.parseText(recurrence_id) if recurrence_id else None
</del><ins>+            recurrence_id = DateTime.parseText(recurrence_id) if recurrence_id else None
</ins><span class="cx"> 
</span><span class="cx">         for component in self.subcomponents():
</span><span class="cx">             if component.name() in ignoredComponents:
</span><span class="lines">@@ -760,7 +807,7 @@
</span><span class="cx">         Return the start date or date-time for the specified component
</span><span class="cx">         converted to UTC.
</span><span class="cx">         @param component: the Component whose start should be returned.
</span><del>-        @return: the L{PyCalendarDateTime} for the start.
</del><ins>+        @return: the L{DateTime} for the start.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         dtstart = self.propertyValue(&quot;DTSTART&quot;)
</span><span class="cx">         return dtstart.duplicateAsUTC() if dtstart is not None else None
</span><span class="lines">@@ -772,7 +819,7 @@
</span><span class="cx">         taking into account the presence or absence of DTEND/DURATION properties.
</span><span class="cx">         The returned date-time is converted to UTC.
</span><span class="cx">         @param component: the Component whose end should be returned.
</span><del>-        @return: the L{PyCalendarDateTime} for the end.
</del><ins>+        @return: the L{DateTime} for the end.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         dtend = self.propertyValue(&quot;DTEND&quot;)
</span><span class="cx">         if dtend is None:
</span><span class="lines">@@ -789,7 +836,7 @@
</span><span class="cx">         Return the due date or date-time for the specified component
</span><span class="cx">         converted to UTC. Use DTSTART/DURATION if no DUE property.
</span><span class="cx">         @param component: the Component whose start should be returned.
</span><del>-        @return: the L{PyCalendarDateTime} for the start.
</del><ins>+        @return: the L{DateTime} for the start.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         due = self.propertyValue(&quot;DUE&quot;)
</span><span class="cx">         if due is None:
</span><span class="lines">@@ -827,7 +874,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return the recurrence-id for the specified component.
</span><span class="cx">         @param component: the Component whose r-id should be returned.
</span><del>-        @return: the L{PyCalendarDateTime} for the r-id.
</del><ins>+        @return: the L{DateTime} for the r-id.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         rid = self.propertyValue(&quot;RECURRENCE-ID&quot;)
</span><span class="cx">         return rid.duplicateAsUTC() if rid is not None else None
</span><span class="lines">@@ -1086,7 +1133,7 @@
</span><span class="cx">         to match the new limit, remove RDATEs/EXDATEs and overridden components beyond the limit.
</span><span class="cx"> 
</span><span class="cx">         @param rid: the recurrence-id limit
</span><del>-        @type rid: L{PyCalendarDateTime}
</del><ins>+        @type rid: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if not self.isRecurring():
</span><span class="lines">@@ -1148,7 +1195,7 @@
</span><span class="cx">         match any RRULE pattern.
</span><span class="cx"> 
</span><span class="cx">         @param rid: the recurrence-id limit
</span><del>-        @type rid: L{PyCalendarDateTime}
</del><ins>+        @type rid: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if not self.isRecurring():
</span><span class="lines">@@ -1169,7 +1216,7 @@
</span><span class="cx">                     rrule_expanded = []
</span><span class="cx">                     rrule.expand(
</span><span class="cx">                         master.propertyValue(&quot;DTSTART&quot;),
</span><del>-                        PyCalendarPeriod(PyCalendarDateTime(1900, 1, 1), upperlimit),
</del><ins>+                        Period(DateTime(1900, 1, 1), upperlimit),
</ins><span class="cx">                         rrule_expanded,
</span><span class="cx">                     )
</span><span class="cx">                     for i in sorted(rrule_expanded):
</span><span class="lines">@@ -1244,14 +1291,14 @@
</span><span class="cx">         instance in the specified range. Date-times are converted to UTC. A
</span><span class="cx">         new calendar object is returned.
</span><span class="cx"> 
</span><del>-        @param start: the L{PyCalendarDateTime} for the start of the range.
-        @param end: the L{PyCalendarDateTime} for the end of the range.
-        @param timezone: the L{Component} or L{PyCalendarTimezone} of the VTIMEZONE to use for floating/all-day.
</del><ins>+        @param start: the L{DateTime} for the start of the range.
+        @param end: the L{DateTime} for the end of the range.
+        @param timezone: the L{Component} or L{Timezone} of the VTIMEZONE to use for floating/all-day.
</ins><span class="cx">         @return: the L{Component} for the new calendar with expanded instances.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if timezone is not None and isinstance(timezone, Component):
</span><del>-            pytz = PyCalendarTimezone(tzid=timezone.propertyValue(&quot;TZID&quot;))
</del><ins>+            pytz = Timezone(tzid=timezone.propertyValue(&quot;TZID&quot;))
</ins><span class="cx">         else:
</span><span class="cx">             pytz = timezone
</span><span class="cx"> 
</span><span class="lines">@@ -1297,7 +1344,7 @@
</span><span class="cx">         # Convert all datetime properties to UTC unless they are floating
</span><span class="cx">         for property in newcomp.properties():
</span><span class="cx">             value = property.value()
</span><del>-            if isinstance(value, PyCalendarDateTime) and value.local():
</del><ins>+            if isinstance(value, DateTime) and value.local():
</ins><span class="cx">                 property.removeParameter(&quot;TZID&quot;)
</span><span class="cx">                 property.setValue(value.duplicateAsUTC())
</span><span class="cx"> 
</span><span class="lines">@@ -1324,7 +1371,7 @@
</span><span class="cx">         breathing room to return results for future instances.
</span><span class="cx"> 
</span><span class="cx">         @param limit: the max datetime to cache up to.
</span><del>-        @type limit: L{PyCalendarDateTime}
</del><ins>+        @type limit: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Checked for cached values first
</span><span class="lines">@@ -1335,7 +1382,7 @@
</span><span class="cx">                 # so return cached instances
</span><span class="cx">                 return self.cachedInstances
</span><span class="cx"> 
</span><del>-        lookAheadLimit = limit + PyCalendarDuration(days=365)
</del><ins>+        lookAheadLimit = limit + Duration(days=365)
</ins><span class="cx">         self.cachedInstances = self.expandTimeRanges(
</span><span class="cx">             lookAheadLimit,
</span><span class="cx">             ignoreInvalidInstances=ignoreInvalidInstances
</span><span class="lines">@@ -1349,7 +1396,7 @@
</span><span class="cx">         contained within this VCALENDAR component. We will assume
</span><span class="cx">         that this component has already been validated as a CalDAV resource
</span><span class="cx">         (i.e. only one type of component, all with the same UID)
</span><del>-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
</del><ins>+        @param limit: L{DateTime} value representing the end of the expansion.
</ins><span class="cx">         @param ignoreInvalidInstances: C{bool} whether to ignore instance errors.
</span><span class="cx">         @return: a set of Instances for each recurrence in the set.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1368,14 +1415,14 @@
</span><span class="cx">         @param componentSet: the set of components that are to make up the
</span><span class="cx">                 recurrence set. These MUST all be components with the same UID
</span><span class="cx">                 and type, forming a proper recurring set.
</span><del>-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
</del><ins>+        @param limit: L{DateTime} value representing the end of the expansion.
</ins><span class="cx"> 
</span><span class="cx">         @param componentSet: the set of components that are to make up the recurrence set.
</span><span class="cx">             These MUST all be components with the same UID and type, forming a proper
</span><span class="cx">             recurring set.
</span><span class="cx">         @type componentSet: C{list}
</span><span class="cx">         @param limit: the end of the expansion
</span><del>-        @type limit: L{PyCalendarDateTime}
</del><ins>+        @type limit: L{DateTime}
</ins><span class="cx">         @param ignoreInvalidInstances: whether or not invalid recurrences raise an exception
</span><span class="cx">         @type ignoreInvalidInstances: C{bool}
</span><span class="cx">         @param normalizeFunction: a function used to normalize date/time values in instances
</span><span class="lines">@@ -1451,7 +1498,7 @@
</span><span class="cx">         There is always some new thing that will surprise you.
</span><span class="cx"> 
</span><span class="cx">         @param rid: recurrence-id value
</span><del>-        @type rid: L{PyCalendarDateTime} or C{str}
</del><ins>+        @type rid: L{DateTime} or C{str}
</ins><span class="cx">         @param allowCancelled: whether to allow a STATUS:CANCELLED override
</span><span class="cx">         @type allowCancelled: C{bool}
</span><span class="cx">         @param allowExcluded: whether to derive an instance for an existing EXDATE
</span><span class="lines">@@ -1469,7 +1516,7 @@
</span><span class="cx">             return None
</span><span class="cx"> 
</span><span class="cx">         if isinstance(rid, str):
</span><del>-            rid = PyCalendarDateTime.parseText(rid) if rid else None
</del><ins>+            rid = DateTime.parseText(rid) if rid else None
</ins><span class="cx"> 
</span><span class="cx">         # TODO: Check that the recurrence-id is a valid instance
</span><span class="cx">         # For now we just check that there is no matching EXDATE
</span><span class="lines">@@ -1586,7 +1633,7 @@
</span><span class="cx">             # Pre-cache instance expansion up to the highest rid
</span><span class="cx">             highest_rid = max(non_master_rids)
</span><span class="cx">             self.cacheExpandedTimeRanges(
</span><del>-                highest_rid + PyCalendarDuration(days=1),
</del><ins>+                highest_rid + Duration(days=1),
</ins><span class="cx">                 ignoreInvalidInstances=ignoreInvalidInstances
</span><span class="cx">             )
</span><span class="cx">         for rid in rids:
</span><span class="lines">@@ -1600,7 +1647,7 @@
</span><span class="cx">         Test whether the specified recurrence-id is a valid instance in this event.
</span><span class="cx"> 
</span><span class="cx">         @param rid: recurrence-id value
</span><del>-        @type rid: L{PyCalendarDateTime}
</del><ins>+        @type rid: L{DateTime}
</ins><span class="cx"> 
</span><span class="cx">         @return: C{bool}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1984,12 +2031,12 @@
</span><span class="cx"> 
</span><span class="cx">     def gettimezone(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        Get the PyCalendarTimezone for a Timezone component.
</del><ins>+        Get the Timezone for a Timezone component.
</ins><span class="cx"> 
</span><del>-        @return: L{PyCalendarTimezone} if this is a VTIMEZONE, otherwise None.
</del><ins>+        @return: L{Timezone} if this is a VTIMEZONE, otherwise None.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         if self.name() == &quot;VTIMEZONE&quot;:
</span><del>-            return PyCalendarTimezone(tzid=self._pycalendar.getID())
</del><ins>+            return Timezone(tzid=self._pycalendar.getID())
</ins><span class="cx">         elif self.name() == &quot;VCALENDAR&quot;:
</span><span class="cx">             for component in self.subcomponents():
</span><span class="cx">                 if component.name() == &quot;VTIMEZONE&quot;:
</span><span class="lines">@@ -2137,6 +2184,10 @@
</span><span class="cx">         return is_server
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def recipientPropertyName(self):
+        return &quot;VOTER&quot; if self.name() == &quot;VPOLL&quot; else &quot;ATTENDEE&quot;
+
+
</ins><span class="cx">     def getAttendees(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get the attendee value. Works on either a VCALENDAR or on a component.
</span><span class="lines">@@ -2152,7 +2203,7 @@
</span><span class="cx">                     return component.getAttendees()
</span><span class="cx">         else:
</span><span class="cx">             # Find the property values
</span><del>-            return [p.value() for p in self.properties(&quot;ATTENDEE&quot;)]
</del><ins>+            return [p.value() for p in self.properties(self.recipientPropertyName())]
</ins><span class="cx"> 
</span><span class="cx">         return None
</span><span class="cx"> 
</span><span class="lines">@@ -2179,7 +2230,7 @@
</span><span class="cx">             result = ()
</span><span class="cx">             attendees = set()
</span><span class="cx">             rid = self.getRecurrenceIDUTC()
</span><del>-            for attendee in tuple(self.properties(&quot;ATTENDEE&quot;)):
</del><ins>+            for attendee in tuple(self.properties(self.recipientPropertyName())):
</ins><span class="cx"> 
</span><span class="cx">                 if onlyScheduleAgentServer:
</span><span class="cx">                     if attendee.hasParameter(&quot;SCHEDULE-AGENT&quot;):
</span><span class="lines">@@ -2195,6 +2246,27 @@
</span><span class="cx">             return result
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def getVoterProperty(self, match):
+        &quot;&quot;&quot;
+        Get the voters matching a value.
+
+        @param match: a C{list} of calendar user address strings to try and match.
+        @return: the matching Voter property, or None
+        &quot;&quot;&quot;
+
+        # Need to normalize http/https cu addresses
+        test = set()
+        for item in match:
+            test.add(normalizeCUAddr(item))
+
+        # Find the primary subcomponent
+        for voter in self.properties(&quot;VOTER&quot;):
+            if normalizeCUAddr(voter.value()) in test:
+                return voter
+
+        return None
+
+
</ins><span class="cx">     def getAttendeeProperty(self, match):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get the attendees matching a value. Works on either a VCALENDAR or on a component.
</span><span class="lines">@@ -2217,7 +2289,7 @@
</span><span class="cx">                         return attendee
</span><span class="cx">         else:
</span><span class="cx">             # Find the primary subcomponent
</span><del>-            for attendee in self.properties(&quot;ATTENDEE&quot;):
</del><ins>+            for attendee in self.properties(self.recipientPropertyName()):
</ins><span class="cx">                 if normalizeCUAddr(attendee.value()) in test:
</span><span class="cx">                     return attendee
</span><span class="cx"> 
</span><span class="lines">@@ -2260,7 +2332,7 @@
</span><span class="cx">                         yield attendee
</span><span class="cx">         else:
</span><span class="cx">             # Find the primary subcomponent
</span><del>-            for attendee in self.properties(&quot;ATTENDEE&quot;):
</del><ins>+            for attendee in self.properties(self.recipientPropertyName()):
</ins><span class="cx">                 yield attendee
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2641,7 +2713,7 @@
</span><span class="cx">         for component in self.subcomponents():
</span><span class="cx">             if component.name() in ignoredComponents:
</span><span class="cx">                 continue
</span><del>-            [component.removeProperty(p) for p in tuple(component.properties(&quot;ATTENDEE&quot;)) if p.value().lower() != attendee.lower()]
</del><ins>+            [component.removeProperty(p) for p in tuple(component.properties(component.recipientPropertyName())) if p.value().lower() != attendee.lower()]
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def removeAllButTheseAttendees(self, attendees):
</span><span class="lines">@@ -2656,7 +2728,7 @@
</span><span class="cx">         for component in self.subcomponents():
</span><span class="cx">             if component.name() in ignoredComponents:
</span><span class="cx">                 continue
</span><del>-            [component.removeProperty(p) for p in tuple(component.properties(&quot;ATTENDEE&quot;)) if p.value().lower() not in attendees]
</del><ins>+            [component.removeProperty(p) for p in tuple(component.properties(component.recipientPropertyName())) if p.value().lower() not in attendees]
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def hasAlarm(self):
</span><span class="lines">@@ -2977,7 +3049,7 @@
</span><span class="cx">             # Bump all components
</span><span class="cx">             self.replacePropertyInAllComponents(Property(&quot;SEQUENCE&quot;, newseq))
</span><span class="cx"> 
</span><del>-        self.replacePropertyInAllComponents(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+        self.replacePropertyInAllComponents(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def sequenceInSync(self, oldcalendar):
</span><span class="lines">@@ -3059,7 +3131,7 @@
</span><span class="cx">             dtend = self.getProperty(&quot;DTEND&quot;)
</span><span class="cx">             duration = self.getProperty(&quot;DURATION&quot;)
</span><span class="cx"> 
</span><del>-            timeRange = PyCalendarPeriod(
</del><ins>+            timeRange = Period(
</ins><span class="cx">                 start=dtstart.value(),
</span><span class="cx">                 end=dtend.value()    if dtend is not None else None,
</span><span class="cx">                 duration=duration.value() if duration is not None else None,
</span><span class="lines">@@ -3163,7 +3235,8 @@
</span><span class="cx">                 continue
</span><span class="cx">             for prop in itertools.chain(
</span><span class="cx">                 component.properties(&quot;ORGANIZER&quot;),
</span><del>-                component.properties(&quot;ATTENDEE&quot;)
</del><ins>+                component.properties(&quot;ATTENDEE&quot;),
+                component.properties(&quot;VOTER&quot;)
</ins><span class="cx">             ):
</span><span class="cx"> 
</span><span class="cx">                 # Check that we can lookup this calendar user address - if not
</span><span class="lines">@@ -3261,7 +3334,11 @@
</span><span class="cx">                     else:
</span><span class="cx">                         prop.removeParameter(&quot;EMAIL&quot;)
</span><span class="cx"> 
</span><ins>+            # For VPOLL also do immediate children
+            if component.name() == &quot;VPOLL&quot;:
+                component.normalizeCalendarUserAddresses(lookupFunction, principalFunction, toUUID)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def allPerUserUIDs(self):
</span><span class="cx"> 
</span><span class="cx">         results = set()
</span><span class="lines">@@ -3311,7 +3388,7 @@
</span><span class="cx">         Determine whether an event exists completely prior to a given moment.
</span><span class="cx"> 
</span><span class="cx">         @param limit: the moment to compare against.
</span><del>-        @type limit: L{PyCalendarDateTime}
</del><ins>+        @type limit: L{DateTime}
</ins><span class="cx"> 
</span><span class="cx">         @return: a C{bool}, True if the event has any instances occurring after
</span><span class="cx">         limit, False otherwise.
</span><span class="lines">@@ -3369,13 +3446,13 @@
</span><span class="cx">     start.setDateOnly(False)
</span><span class="cx">     if tzexpanded:
</span><span class="cx">         if start != tzexpanded[0][0]:
</span><del>-            results.append((str(start), PyCalendarUTCOffsetValue(tzexpanded[0][1]).getText(),))
</del><ins>+            results.append((str(start), UTCOffsetValue(tzexpanded[0][1]).getText(),))
</ins><span class="cx">     else:
</span><del>-        results.append((str(start), PyCalendarUTCOffsetValue(tzcomp._pycalendar.getTimezoneOffsetSeconds(start)).getText(),))
</del><ins>+        results.append((str(start), UTCOffsetValue(tzcomp._pycalendar.getTimezoneOffsetSeconds(start)).getText(),))
</ins><span class="cx">     for tzstart, _ignore_tzoffsetfrom, tzoffsetto in tzexpanded:
</span><span class="cx">         results.append((
</span><span class="cx">             tzstart.getText(),
</span><del>-            PyCalendarUTCOffsetValue(tzoffsetto).getText(),
</del><ins>+            UTCOffsetValue(tzoffsetto).getText(),
</ins><span class="cx">         ))
</span><span class="cx"> 
</span><span class="cx">     return results
</span><span class="lines">@@ -3388,7 +3465,7 @@
</span><span class="cx">     time range.
</span><span class="cx"> 
</span><span class="cx">     @param tzdata: the iCalendar data containing a VTIMEZONE.
</span><del>-    @type tzdata: L{PyCalendar}
</del><ins>+    @type tzdata: L{Calendar}
</ins><span class="cx">     @param start: date for the start of the expansion.
</span><span class="cx">     @type start: C{date}
</span><span class="cx">     @param end: date for the end of the expansion.
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavicaldavpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/icaldav.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/icaldav.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/icaldav.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -29,14 +29,14 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalDAV resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    def isCalendarCollection():
</del><ins>+    def isCalendarCollection(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         (CalDAV-access-10, Section 4.2)
</span><span class="cx">         @return: True if this resource is a calendar collection, False
</span><span class="cx">             otherwise.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def isSpecialCollection(collectiontype):
</del><ins>+    def isSpecialCollection(collectiontype): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         (CalDAV-access-10, Section 4.2)
</span><span class="cx">         @param collectiontype: L{WebDAVElement} for the collection type to test for.
</span><span class="lines">@@ -44,30 +44,30 @@
</span><span class="cx">             False otherwise.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def isPseudoCalendarCollection():
</del><ins>+    def isPseudoCalendarCollection(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: True if this resource is a calendar collection like (e.g.
</span><span class="cx">             a regular calendar collection or schedule inbox/outbox), False
</span><span class="cx">             otherwise.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def findCalendarCollections(depth):
</del><ins>+    def findCalendarCollections(depth): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Returns an iterable of child calendar collection resources for the given
</span><span class="cx">         depth.
</span><del>-        Because resources do not know their request URIs, chidren are returned
</del><ins>+        Because resources do not know their request URIs, children are returned
</ins><span class="cx">         as tuples C{(resource, uri)}, where C{resource} is the child resource
</span><span class="cx">         and C{uri} is a URL path relative to this resource.
</span><span class="cx">         @param depth: the search depth (one of &quot;0&quot;, &quot;1&quot;, or &quot;infinity&quot;)
</span><span class="cx">         @return: an iterable of tuples C{(resource, uri)}.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def createCalendar(request):
</del><ins>+    def createCalendar(request): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Create a calendar collection for this resource.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def iCalendar():
</del><ins>+    def iCalendar(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Instantiate an iCalendar component object representing this resource or
</span><span class="cx">         its child with the given name.
</span><span class="lines">@@ -78,52 +78,42 @@
</span><span class="cx">         @return: a L{twistedcaldav.ical.Component} of type C{&quot;VCALENDAR&quot;}.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def iCalendarText():
-        &quot;&quot;&quot;
-        Obtains the iCalendar text representing this resource or its child with
-        the given name.
-        The behavior of this method is not specified if it is called on a
-        resource that is not a calendar collection or a calendar resource within
-        a calendar collection.
</del><span class="cx"> 
</span><del>-        @return: a string containing iCalendar text with a top-level component
-            of type C{&quot;VCALENDAR&quot;}.
-        &quot;&quot;&quot;
</del><span class="cx"> 
</span><span class="cx"> class ICalendarPrincipalResource(IDAVResource):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalDAV principle resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    def principalUID():
</del><ins>+    def principalUID(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the user id for this principal.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def calendarHomeURLs():
</del><ins>+    def calendarHomeURLs(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: a list of calendar home URLs for this principal's calendar user.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def calendarUserAddresses():
</del><ins>+    def calendarUserAddresses(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: a list of calendar user addresses for this principal's calendar
</span><span class="cx">             user.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def calendarFreeBusyURIs(self, request):
</del><ins>+    def calendarFreeBusyURIs(request): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @param request: the request being processed.
</span><span class="cx">         @return: a L{Deferred} list of URIs for calendars that contribute to
</span><span class="cx">             free-busy for this principal's calendar user.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def scheduleInboxURL():
</del><ins>+    def scheduleInboxURL(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get the schedule INBOX URL for this principal's calendar user.
</span><span class="cx">         @return: a string containing the URL from the schedule-inbox-URL property.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    def scheduleOutboxURL():
</del><ins>+    def scheduleOutboxURL(): #@NoSelf
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get the schedule OUTBOX URL for this principal's calendar user.
</span><span class="cx">         @return: a string containing the URL from the schedule-outbox-URL property.
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavinstancepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/instance.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/instance.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/instance.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -21,10 +21,10 @@
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.dateops import normalizeForIndex, differenceDateTime
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.period import Period
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> class TooManyInstancesError(Exception):
</span><span class="cx"> 
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">             (trigger, related, repeat, duration) = alarm.getTriggerDetails()
</span><span class="cx"> 
</span><span class="cx">             # Handle relative vs absolute triggers
</span><del>-            if isinstance(trigger, PyCalendarDateTime):
</del><ins>+            if isinstance(trigger, DateTime):
</ins><span class="cx">                 # Absolute trigger
</span><span class="cx">                 start = trigger
</span><span class="cx">             else:
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">         @param componentSet: the set of components that are to make up the
</span><span class="cx">                 recurrence set. These MUST all be components with the same UID
</span><span class="cx">                 and type, forming a proper recurring set.
</span><del>-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
</del><ins>+        @param limit: L{DateTime} value representing the end of the expansion.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Look at each component type
</span><span class="lines">@@ -232,10 +232,10 @@
</span><span class="cx">         if end is None:
</span><span class="cx">             if not start.isDateOnly():
</span><span class="cx">                 # Timed event with zero duration
</span><del>-                duration = PyCalendarDuration(days=0)
</del><ins>+                duration = Duration(days=0)
</ins><span class="cx">             else:
</span><span class="cx">                 # All day event default duration is one day
</span><del>-                duration = PyCalendarDuration(days=1)
</del><ins>+                duration = Duration(days=1)
</ins><span class="cx">             end = start + duration
</span><span class="cx">         else:
</span><span class="cx">             duration = differenceDateTime(start, end)
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx">         Add the specified master VEVENT Component to the instance list, expanding it
</span><span class="cx">         within the supplied time range.
</span><span class="cx">         @param component: the Component to expand
</span><del>-        @param limit: the end L{PyCalendarDateTime} for expansion
</del><ins>+        @param limit: the end L{DateTime} for expansion
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         details = self._getMasterEventDetails(component)
</span><span class="lines">@@ -330,7 +330,7 @@
</span><span class="cx">         Add the specified master VTODO Component to the instance list, expanding it
</span><span class="cx">         within the supplied time range.
</span><span class="cx">         @param component: the Component to expand
</span><del>-        @param limit: the end L{PyCalendarDateTime} for expansion
</del><ins>+        @param limit: the end L{DateTime} for expansion
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         details = self._getMasterToDoDetails(component)
</span><span class="cx">         if details is None:
</span><span class="lines">@@ -370,7 +370,7 @@
</span><span class="cx">             # than the master DTSTART, and if we exclude those, the associated
</span><span class="cx">             # overridden instances will cause an InvalidOverriddenInstance.
</span><span class="cx">             limited = rrules.expand(rulestart,
</span><del>-                PyCalendarPeriod(PyCalendarDateTime(1900, 1, 1), upperlimit), expanded)
</del><ins>+                Period(DateTime(1900, 1, 1), upperlimit), expanded)
</ins><span class="cx">             for startDate in expanded:
</span><span class="cx">                 startDate = self.normalizeFunction(startDate)
</span><span class="cx">                 endDate = startDate + duration
</span><span class="lines">@@ -478,7 +478,7 @@
</span><span class="cx">         Add the specified master VFREEBUSY Component to the instance list, expanding it
</span><span class="cx">         within the supplied time range.
</span><span class="cx">         @param component: the Component to expand
</span><del>-        @param limit: the end L{PyCalendarDateTime} for expansion
</del><ins>+        @param limit: the end L{DateTime} for expansion
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         start = component.getStartDateUTC()
</span><span class="lines">@@ -519,7 +519,7 @@
</span><span class="cx">         depending on the presence of the properties. If unbounded at one or both ends, we will
</span><span class="cx">         set the time to 1/1/1900 in the past and 1/1/3000 in the future.
</span><span class="cx">         @param component: the Component to expand
</span><del>-        @param limit: the end L{PyCalendarDateTime} for expansion
</del><ins>+        @param limit: the end L{DateTime} for expansion
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         start = component.getStartDateUTC()
</span><span class="lines">@@ -531,7 +531,7 @@
</span><span class="cx">             # If the availability is beyond the end of the range we want, ignore it
</span><span class="cx">             return
</span><span class="cx">         if start is None:
</span><del>-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         start = self.normalizeFunction(start)
</span><span class="cx"> 
</span><span class="cx">         end = component.getEndDateUTC()
</span><span class="lines">@@ -539,7 +539,7 @@
</span><span class="cx">             # If the availability is before the start of the range we want, ignore it
</span><span class="cx">             return
</span><span class="cx">         if end is None:
</span><del>-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         end = self.normalizeFunction(end)
</span><span class="cx"> 
</span><span class="cx">         self.addInstance(Instance(component, start, end))
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavlinkresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/linkresource.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/linkresource.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/linkresource.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -47,16 +47,17 @@
</span><span class="cx">     case of a missing underlying resource (broken link) as indicated by self._linkedResource being None.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     log = Logger()
</span><del>-    
</del><ins>+
</ins><span class="cx">     def __init__(self, parent, link_url):
</span><span class="cx">         self.parent = parent
</span><span class="cx">         self.linkURL = link_url
</span><span class="cx">         self.loopDetect = set()
</span><span class="cx">         super(LinkResource, self).__init__(self.parent.principalCollections())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def linkedResource(self, request):
</span><del>-        
</del><ins>+
</ins><span class="cx">         if not hasattr(self, &quot;_linkedResource&quot;):
</span><span class="cx">             if self.linkURL in self.loopDetect:
</span><span class="cx">                 raise HTTPError(StatusResponse(responsecode.LOOP_DETECTED, &quot;Recursive link target: %s&quot; % (self.linkURL,)))
</span><span class="lines">@@ -67,17 +68,20 @@
</span><span class="cx"> 
</span><span class="cx">         if self._linkedResource is None:
</span><span class="cx">             raise HTTPError(StatusResponse(responsecode.NOT_FOUND, &quot;Missing link target: %s&quot; % (self.linkURL,)))
</span><del>-            
</del><ins>+
</ins><span class="cx">         returnValue(self._linkedResource)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return True if hasattr(self, &quot;_linkedResource&quot;) else False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceType(self):
</span><span class="cx">         return self._linkedResource.resourceType() if hasattr(self, &quot;_linkedResource&quot;) else davxml.ResourceType.link
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def locateChild(self, request, segments):
</span><del>-        
</del><ins>+
</ins><span class="cx">         def _defer(result):
</span><span class="cx">             if result is None:
</span><span class="cx">                 return (self, server.StopTraversal)
</span><span class="lines">@@ -87,6 +91,7 @@
</span><span class="cx">         d.addCallback(_defer)
</span><span class="cx">         return d
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def renderHTTP(self, request):
</span><span class="cx">         linked_to = (yield self.linkedResource(request))
</span><span class="lines">@@ -95,27 +100,33 @@
</span><span class="cx">         else:
</span><span class="cx">             returnValue(http.StatusResponse(responsecode.OK, &quot;Link resource with missing target: %s&quot; % (self.linkURL,)))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getChild(self, name):
</span><span class="cx">         return self._linkedResource.getChild(name) if hasattr(self, &quot;_linkedResource&quot;) else None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def hasProperty(self, property, request):
</span><span class="cx">         hosted = (yield self.linkedResource(request))
</span><span class="cx">         result = (yield hosted.hasProperty(property, request)) if hosted else False
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def readProperty(self, property, request):
</span><span class="cx">         hosted = (yield self.linkedResource(request))
</span><span class="cx">         result = (yield hosted.readProperty(property, request)) if hosted else None
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def writeProperty(self, property, request):
</span><span class="cx">         hosted = (yield self.linkedResource(request))
</span><span class="cx">         result = (yield hosted.writeProperty(property, request)) if hosted else None
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class LinkFollowerMixIn(object):
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -128,6 +139,5 @@
</span><span class="cx">             if linked_to is None:
</span><span class="cx">                 break
</span><span class="cx">             resource = linked_to
</span><del>-        
</del><ins>+
</ins><span class="cx">         returnValue((resource, path))
</span><del>-        
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavlocalizationpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/localization.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/localization.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/localization.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> from locale import normalize
</span><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><del>-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.duration import Duration
</ins><span class="cx"> 
</span><span class="cx"> try:
</span><span class="cx">     from Foundation import (
</span><span class="lines">@@ -89,12 +89,12 @@
</span><span class="cx"> helper methods for date formatting:
</span><span class="cx"> 
</span><span class="cx">     with translationTo('en') as trans:
</span><del>-        print(trans.dtDate(PyCalendarDateTime.getToday()))
</del><ins>+        print(trans.dtDate(DateTime.getToday()))
</ins><span class="cx"> 
</span><span class="cx">     ... Thursday, October 23, 2008
</span><span class="cx"> 
</span><span class="cx">     with translationTo('fr') as trans:
</span><del>-        print(trans.dtDate(PyCalendarDateTime.getToday()))
</del><ins>+        print(trans.dtDate(DateTime.getToday()))
</ins><span class="cx"> 
</span><span class="cx">     ... Jeudi, Octobre 23, 2008
</span><span class="cx"> 
</span><span class="lines">@@ -124,12 +124,13 @@
</span><span class="cx">                 localedir=localeDir, languages=[lang, 'en'], fallback=True)
</span><span class="cx">             self.translations[key] = self.translation
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def __enter__(self):
</span><span class="cx">         # Get the caller's globals so we can rebind their '_' to our translator
</span><span class="cx">         caller_globals = inspect.stack()[1][0].f_globals
</span><span class="cx"> 
</span><span class="cx">         # Store whatever '_' is already bound to so we can restore it later
</span><del>-        if caller_globals.has_key('_'):
</del><ins>+        if '_' in caller_globals:
</ins><span class="cx">             self.prev = caller_globals['_']
</span><span class="cx"> 
</span><span class="cx">         # Rebind '_' to our translator
</span><span class="lines">@@ -138,6 +139,7 @@
</span><span class="cx">         # What we return here is accessible to the caller via the 'as' clause
</span><span class="cx">         return self
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def __exit__(self, type, value, traceback):
</span><span class="cx">         # Restore '_' if it previously had a value
</span><span class="cx">         if hasattr(self, 'prev'):
</span><span class="lines">@@ -146,13 +148,16 @@
</span><span class="cx">         # Don't swallow exceptions
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def monthAbbreviation(self, monthNumber):
</span><span class="cx">         return self.translation.ugettext(monthsAbbrev[monthNumber])
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def date(self, component):
</span><span class="cx">         dtStart = component.propertyValue(&quot;DTSTART&quot;)
</span><span class="cx">         return self.dtDate(dtStart)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def time(self, component):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Examples:
</span><span class="lines">@@ -191,9 +196,9 @@
</span><span class="cx">             else:
</span><span class="cx">                 if dtStart.isDateOnly():
</span><span class="cx">                     dtEnd = None
</span><del>-                    duration = PyCalendarDuration(days=1)
</del><ins>+                    duration = Duration(days=1)
</ins><span class="cx">                 else:
</span><del>-                    dtEnd = dtStart + PyCalendarDuration(days=1)
</del><ins>+                    dtEnd = dtStart + Duration(days=1)
</ins><span class="cx">                     dtEnd.setHHMMSS(0, 0, 0)
</span><span class="cx">                     duration = dtEnd - dtStart
</span><span class="cx"> 
</span><span class="lines">@@ -225,6 +230,7 @@
</span><span class="cx">             }
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def dtTime(self, val, includeTimezone=True):
</span><span class="cx">         if val.isDateOnly():
</span><span class="cx">             return &quot;&quot;
</span><span class="lines">@@ -252,6 +258,7 @@
</span><span class="cx"> 
</span><span class="cx">         return result
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def dtDuration(self, val):
</span><span class="cx"> 
</span><span class="cx">         # Bind to '_' so pygettext.py will pick this up for translation
</span><span class="lines">@@ -265,7 +272,7 @@
</span><span class="cx">             parts.append(_(&quot;1 day&quot;))
</span><span class="cx">         elif days &gt; 1:
</span><span class="cx">             parts.append(_(&quot;%(dayCount)d days&quot;) %
</span><del>-                { 'dayCount' : days })
</del><ins>+                {'dayCount' : days})
</ins><span class="cx"> 
</span><span class="cx">         hours = divmod(total / 3600, 24)[1]
</span><span class="cx">         minutes = divmod(total / 60, 60)[1]
</span><span class="lines">@@ -275,19 +282,19 @@
</span><span class="cx">             parts.append(_(&quot;1 hour&quot;))
</span><span class="cx">         elif hours &gt; 1:
</span><span class="cx">             parts.append(_(&quot;%(hourCount)d hours&quot;) %
</span><del>-                { 'hourCount' : hours })
</del><ins>+                {'hourCount' : hours})
</ins><span class="cx"> 
</span><span class="cx">         if minutes == 1:
</span><span class="cx">             parts.append(_(&quot;1 minute&quot;))
</span><span class="cx">         elif minutes &gt; 1:
</span><span class="cx">             parts.append(_(&quot;%(minuteCount)d minutes&quot;) %
</span><del>-                { 'minuteCount' : minutes })
</del><ins>+                {'minuteCount' : minutes})
</ins><span class="cx"> 
</span><span class="cx">         if seconds == 1:
</span><span class="cx">             parts.append(_(&quot;1 second&quot;))
</span><span class="cx">         elif seconds &gt; 1:
</span><span class="cx">             parts.append(_(&quot;%(secondCount)d seconds&quot;) %
</span><del>-                { 'secondCount' : seconds })
</del><ins>+                {'secondCount' : seconds})
</ins><span class="cx"> 
</span><span class="cx">         return &quot; &quot;.join(parts)
</span><span class="cx"> 
</span><span class="lines">@@ -398,12 +405,14 @@
</span><span class="cx">                     else:
</span><span class="cx">                         log.info(&quot;%s is up to date&quot; % (moFile,))
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class ParseError(Exception):
</span><span class="cx">     pass
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def convertStringsFile(src, dest):
</span><del>-    strings = { }
</del><span class="cx"> 
</span><span class="cx">     dir = os.path.dirname(dest)
</span><span class="cx"> 
</span><span class="lines">@@ -458,13 +467,13 @@
</span><span class="cx"> 
</span><span class="cx">     result = struct.pack(
</span><span class="cx">         &quot;Iiiiiii&quot;,
</span><del>-        0x950412DEL,         # magic number
-        0,                   # file format revision
-        len(originals),      # number of strings
-        28,                  # offset of table with original strings
-        28+len(originals)*8, # offset of table with translation strings
-        0,                   # size of hashing table
-        0                    # offset of hashing table
</del><ins>+        0x950412DEL,           # magic number
+        0,                     # file format revision
+        len(originals),        # number of strings
+        28,                    # offset of table with original strings
+        28 + len(originals) * 8, # offset of table with translation strings
+        0,                     # size of hashing table
+        0                      # offset of hashing table
</ins><span class="cx">     )
</span><span class="cx">     result += array.array(&quot;i&quot;, keyDescriptors).tostring()
</span><span class="cx">     result += array.array(&quot;i&quot;, valueDescriptors).tostring()
</span><span class="lines">@@ -475,6 +484,7 @@
</span><span class="cx">         outFile.write(result)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def getLanguage(config):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     If the language has been specified explicitly in the config, return it.  Otherwise
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmemcachelockpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/memcachelock.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/memcachelock.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/memcachelock.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -15,7 +15,7 @@
</span><span class="cx"> ##
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.memcacher import Memcacher
</span><del>-from twisted.internet.defer import inlineCallbacks, Deferred, returnValue,\
</del><ins>+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue, \
</ins><span class="cx">     succeed
</span><span class="cx"> from twisted.internet import reactor
</span><span class="cx"> import time
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param namespace: a unique namespace for this lock's tokens
</span><span class="cx">         @type namespace: C{str}
</span><span class="cx">         @param locktoken: the name of the locktoken
</span><span class="lines">@@ -44,31 +44,33 @@
</span><span class="cx">         self._expire_time = expire_time
</span><span class="cx">         self._hasLock = False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _getMemcacheProtocol(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         result = super(MemcacheLock, self)._getMemcacheProtocol()
</span><span class="cx"> 
</span><span class="cx">         if isinstance(result, Memcacher.nullCacher):
</span><span class="cx">             raise AssertionError(&quot;No implementation of shared locking without memcached&quot;)
</span><del>-        
</del><ins>+
</ins><span class="cx">         return result
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def acquire(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         assert not self._hasLock, &quot;Lock already acquired.&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">         timeout_at = time.time() + self._timeout
</span><span class="cx">         waiting = False
</span><span class="cx">         while True:
</span><del>-            
</del><ins>+
</ins><span class="cx">             result = (yield self.add(self._locktoken, &quot;1&quot;, expireTime=self._expire_time))
</span><span class="cx">             if result:
</span><span class="cx">                 self._hasLock = True
</span><span class="cx">                 if waiting:
</span><span class="cx">                     self.log.debug(&quot;Got lock after waiting on %s&quot; % (self._locktoken,))
</span><span class="cx">                 break
</span><del>-            
</del><ins>+
</ins><span class="cx">             if self._timeout and time.time() &lt; timeout_at:
</span><span class="cx">                 waiting = True
</span><span class="cx">                 self.log.debug(&quot;Waiting for lock on %s&quot; % (self._locktoken,))
</span><span class="lines">@@ -80,13 +82,14 @@
</span><span class="cx">             else:
</span><span class="cx">                 self.log.debug(&quot;Timed out lock after waiting on %s&quot; % (self._locktoken,))
</span><span class="cx">                 raise MemcacheLockTimeoutError()
</span><del>-        
</del><ins>+
</ins><span class="cx">         returnValue(True)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def release(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         assert self._hasLock, &quot;Lock not acquired.&quot;
</span><del>-    
</del><ins>+
</ins><span class="cx">         def _done(result):
</span><span class="cx">             self._hasLock = False
</span><span class="cx">             return result
</span><span class="lines">@@ -95,18 +98,20 @@
</span><span class="cx">         d.addCallback(_done)
</span><span class="cx">         return d
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def clean(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         if self._hasLock:
</span><span class="cx">             return self.release()
</span><span class="cx">         else:
</span><span class="cx">             return succeed(True)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def locked(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Test if the lock is currently being held.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         def _gotit(value):
</span><span class="cx">             return value is not None
</span><span class="cx"> 
</span><span class="lines">@@ -114,5 +119,7 @@
</span><span class="cx">         d.addCallback(_gotit)
</span><span class="cx">         return d
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class MemcacheLockTimeoutError(Exception):
</span><span class="cx">     pass
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmemcachepoolpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/memcachepool.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/memcachepool.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/memcachepool.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -99,6 +99,7 @@
</span><span class="cx">             connector,
</span><span class="cx">             reason)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def buildProtocol(self, addr):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Attach the C{self.connectionPool} to the protocol so it can tell it,
</span><span class="lines">@@ -167,6 +168,7 @@
</span><span class="cx">         self._pendingConnects = 0
</span><span class="cx">         self._commands = []
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _isIdle(self):
</span><span class="cx">         return (
</span><span class="cx">             len(self._busyClients) == 0 and
</span><span class="lines">@@ -174,6 +176,7 @@
</span><span class="cx">             self._pendingConnects == 0
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _shutdownCallback(self):
</span><span class="cx">         self.shutdown_requested = True
</span><span class="cx">         if self._isIdle():
</span><span class="lines">@@ -181,13 +184,14 @@
</span><span class="cx">         self.shutdown_deferred = Deferred()
</span><span class="cx">         return self.shutdown_deferred
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _newClientConnection(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Create a new client connection.
</span><span class="cx"> 
</span><span class="cx">         @return: A L{Deferred} that fires with the L{IProtocol} instance.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        self.log.debug(&quot;Initating new client connection to: %r&quot; % (
</del><ins>+        self.log.debug(&quot;Initiating new client connection to: %r&quot; % (
</ins><span class="cx">                 self._endpoint,))
</span><span class="cx">         self._logClientStats()
</span><span class="cx"> 
</span><span class="lines">@@ -219,7 +223,7 @@
</span><span class="cx"> 
</span><span class="cx">         @param command: A C{str} representing an attribute of
</span><span class="cx">             L{MemCacheProtocol}.
</span><del>-        @parma args: Any positional arguments that should be passed to
</del><ins>+        @param args: Any positional arguments that should be passed to
</ins><span class="cx">             C{command}.
</span><span class="cx">         @param kwargs: Any keyword arguments that should be passed to
</span><span class="cx">             C{command}.
</span><span class="lines">@@ -258,7 +262,7 @@
</span><span class="cx"> 
</span><span class="cx">         @param command: A C{str} representing an attribute of
</span><span class="cx">             L{MemCacheProtocol}.
</span><del>-        @parma args: Any positional arguments that should be passed to
</del><ins>+        @param args: Any positional arguments that should be passed to
</ins><span class="cx">             C{command}.
</span><span class="cx">         @param kwargs: Any keyword arguments that should be passed to
</span><span class="cx">             C{command}.
</span><span class="lines">@@ -371,24 +375,31 @@
</span><span class="cx">     def get(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('get', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def set(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('set', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def checkAndSet(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('checkAndSet', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def delete(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('delete', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def add(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('add', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def incr(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('increment', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def decr(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('decrement', *args, **kwargs)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def flushAll(self, *args, **kwargs):
</span><span class="cx">         return self.performRequest('flushAll', *args, **kwargs)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodgetpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/get.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/get.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/method/get.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> from txdav.xml import element as davxml
</span><span class="cx"> from twext.web2.dav.http import ErrorResponse
</span><span class="cx"> from twext.web2.dav.util import parentForURL
</span><del>-from twext.web2.http import HTTPError
</del><ins>+from twext.web2.http import HTTPError, StatusResponse
</ins><span class="cx"> from twext.web2.http import Response
</span><span class="cx"> from twext.web2.http_headers import MimeType
</span><span class="cx"> from twext.web2.stream import MemoryStream
</span><span class="lines">@@ -34,8 +34,10 @@
</span><span class="cx"> from twistedcaldav.customxml import calendarserver_namespace
</span><span class="cx"> from twistedcaldav.datafilters.hiddeninstance import HiddenInstanceFilter
</span><span class="cx"> from twistedcaldav.datafilters.privateevents import PrivateEventFilter
</span><ins>+from twistedcaldav.ical import Component
</ins><span class="cx"> from twistedcaldav.resource import isPseudoCalendarCollectionResource, \
</span><span class="cx">     CalDAVResource
</span><ins>+from twistedcaldav.util import bestAcceptType
</ins><span class="cx"> 
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def http_GET(self, request):
</span><span class="lines">@@ -70,6 +72,8 @@
</span><span class="cx">                 returnValue(response)
</span><span class="cx"> 
</span><span class="cx">         else:
</span><ins>+            # FIXME: this should be implemented in storebridge.CalendarObject.render
+
</ins><span class="cx">             # Look for calendar access restriction on existing resource.
</span><span class="cx">             parentURL = parentForURL(request.uri)
</span><span class="cx">             parent = (yield request.locateResource(parentURL))
</span><span class="lines">@@ -78,6 +82,11 @@
</span><span class="cx">                 # Check authorization first
</span><span class="cx">                 yield self.authorize(request, (davxml.Read(),))
</span><span class="cx"> 
</span><ins>+                # Accept header handling
+                accepted_type = bestAcceptType(request.headers.getHeader(&quot;accept&quot;), Component.allowedTypes())
+                if accepted_type is None:
+                    raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, &quot;Cannot generate requested data type&quot;))
+
</ins><span class="cx">                 caldata = (yield self.iCalendarForUser(request))
</span><span class="cx"> 
</span><span class="cx">                 # Filter any attendee hidden instances
</span><span class="lines">@@ -92,8 +101,8 @@
</span><span class="cx">                     caldata = PrivateEventFilter(self.accessMode, isowner).filter(caldata)
</span><span class="cx"> 
</span><span class="cx">                 response = Response()
</span><del>-                response.stream = MemoryStream(caldata.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference))
-                response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;text/calendar; charset=utf-8&quot;))
</del><ins>+                response.stream = MemoryStream(caldata.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference, format=accepted_type))
+                response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;%s; charset=utf-8&quot; % (accepted_type,)))
</ins><span class="cx"> 
</span><span class="cx">                 # Add Schedule-Tag header if property is present
</span><span class="cx">                 if self.scheduleTag:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodpropfindpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/propfind.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/propfind.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/method/propfind.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -98,7 +98,7 @@
</span><span class="cx">             search_properties = &quot;names&quot;
</span><span class="cx">         elif isinstance(container, davxml.PropertyContainer):
</span><span class="cx">             properties = container.children
</span><del>-            search_properties = [(p.namespace, p.name) for p in properties]
</del><ins>+            search_properties = properties
</ins><span class="cx">         else:
</span><span class="cx">             raise AssertionError(&quot;Unexpected element type in %s: %s&quot;
</span><span class="cx">                                  % (davxml.PropertyFind.sname(), container))
</span><span class="lines">@@ -245,7 +245,11 @@
</span><span class="cx"> # Utilities
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-def propertyName(name):
</del><ins>+def propertyName(prop):
+    if type(prop) is tuple:
+        name = prop
+    else:
+        name = prop.qname()
</ins><span class="cx">     property_namespace, property_name = name
</span><span class="cx">     pname = davxml.WebDAVUnknownElement()
</span><span class="cx">     pname.namespace = property_namespace
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodreport_calendar_querypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -32,7 +32,8 @@
</span><span class="cx"> from twext.web2.http import HTTPError, StatusResponse
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav import caldavxml
</span><del>-from twistedcaldav.caldavxml import caldav_namespace, MaxInstances
</del><ins>+from twistedcaldav.caldavxml import caldav_namespace, MaxInstances, \
+    CalendarTimeZone
</ins><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from txdav.common.icommondatastore import IndexedSearchException, \
</span><span class="cx">     ConcurrentModification
</span><span class="lines">@@ -171,10 +172,10 @@
</span><span class="cx">         if calresource.isPseudoCalendarCollection():
</span><span class="cx">             # Get the timezone property from the collection if one was not set in the query,
</span><span class="cx">             # and store in the query filter for later use
</span><del>-            has_prop = (yield calresource.hasProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+            has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
</ins><span class="cx">             timezone = query_timezone
</span><span class="cx">             if query_tz is None and has_prop:
</span><del>-                tz = (yield calresource.readProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+                tz = (yield calresource.readProperty(CalendarTimeZone(), request))
</ins><span class="cx">                 filter.settimezone(tz)
</span><span class="cx">                 timezone = tuple(tz.calendar().subcomponents())[0]
</span><span class="cx"> 
</span><span class="lines">@@ -233,9 +234,9 @@
</span><span class="cx">                 parent = (yield calresource.locateParent(request, uri))
</span><span class="cx">                 assert parent is not None and parent.isPseudoCalendarCollection()
</span><span class="cx"> 
</span><del>-                has_prop = (yield parent.hasProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+                has_prop = (yield parent.hasProperty(CalendarTimeZone(), request))
</ins><span class="cx">                 if has_prop:
</span><del>-                    tz = (yield parent.readProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+                    tz = (yield parent.readProperty(CalendarTimeZone(), request))
</ins><span class="cx">                     filter.settimezone(tz)
</span><span class="cx">                     timezone = tuple(tz.calendar().subcomponents())[0]
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodreport_commonpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/report_common.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/report_common.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/method/report_common.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav import caldavxml
</span><span class="cx"> from twistedcaldav import carddavxml
</span><del>-from twistedcaldav.caldavxml import caldav_namespace, CalendarData, TimeRange
</del><ins>+from twistedcaldav.caldavxml import CalendarData, CalendarTimeZone, TimeRange
</ins><span class="cx"> from twistedcaldav.carddavxml import AddressData
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.datafilters.calendardata import CalendarDataFilter
</span><span class="lines">@@ -69,10 +69,10 @@
</span><span class="cx"> 
</span><span class="cx"> from txdav.common.icommondatastore import IndexedSearchException
</span><span class="cx"> 
</span><del>-from pycalendar.duration import PyCalendarDuration
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.period import PyCalendarPeriod
</del><ins>+from pycalendar.duration import Duration
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
+from pycalendar.period import Period
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -299,7 +299,7 @@
</span><span class="cx">     generate_calendar_data = False
</span><span class="cx">     for property in prop.children:
</span><span class="cx">         if isinstance(property, caldavxml.CalendarData):
</span><del>-            if not property.verifyTypeVersion([(&quot;text/calendar&quot;, &quot;2.0&quot;)]):
</del><ins>+            if not property.verifyTypeVersion():
</ins><span class="cx">                 result = False
</span><span class="cx">                 message = &quot;Calendar-data element type/version not supported: content-type: %s, version: %s&quot; % (property.content_type, property.version)
</span><span class="cx">             generate_calendar_data = True
</span><span class="lines">@@ -324,7 +324,7 @@
</span><span class="cx">     generate_address_data = False
</span><span class="cx">     for property in prop.children:
</span><span class="cx">         if isinstance(property, carddavxml.AddressData):
</span><del>-            if not property.verifyTypeVersion([(&quot;text/vcard&quot;, &quot;3.0&quot;)]):
</del><ins>+            if not property.verifyTypeVersion():
</ins><span class="cx">                 result = False
</span><span class="cx">                 message = &quot;Address-data element type/version not supported: content-type: %s, version: %s&quot; % (property.content_type, property.version)
</span><span class="cx">             generate_address_data = True
</span><span class="lines">@@ -371,7 +371,7 @@
</span><span class="cx">             filtered = HiddenInstanceFilter().filter(calendar)
</span><span class="cx">             filtered = PrivateEventFilter(resource.accessMode, isowner).filter(filtered)
</span><span class="cx">             filtered = CalendarDataFilter(property, timezone).filter(filtered)
</span><del>-            propvalue = CalendarData().fromCalendar(filtered)
</del><ins>+            propvalue = CalendarData.fromCalendar(filtered, format=property.content_type)
</ins><span class="cx">             properties_by_status[responsecode.OK].append(propvalue)
</span><span class="cx">             continue
</span><span class="cx"> 
</span><span class="lines">@@ -379,7 +379,7 @@
</span><span class="cx">             if vcard is None:
</span><span class="cx">                 vcard = (yield resource.vCard())
</span><span class="cx">             filtered = AddressDataFilter(property).filter(vcard)
</span><del>-            propvalue = AddressData().fromAddress(filtered)
</del><ins>+            propvalue = AddressData.fromAddress(filtered, format=property.content_type)
</ins><span class="cx">             properties_by_status[responsecode.OK].append(propvalue)
</span><span class="cx">             continue
</span><span class="cx"> 
</span><span class="lines">@@ -392,7 +392,7 @@
</span><span class="cx"> 
</span><span class="cx">         if has:
</span><span class="cx">             try:
</span><del>-                prop = (yield resource.readProperty(qname, request))
</del><ins>+                prop = (yield resource.readProperty(property, request))
</ins><span class="cx">                 if prop is not None:
</span><span class="cx">                     properties_by_status[responsecode.OK].append(prop)
</span><span class="cx">                 elif not returnMinimal:
</span><span class="lines">@@ -436,8 +436,8 @@
</span><span class="cx">         if entry:
</span><span class="cx"> 
</span><span class="cx">             # Offset one day at either end to account for floating
</span><del>-            cached_start = entry.timerange.start + PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
-            cached_end = entry.timerange.end - PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
</del><ins>+            cached_start = entry.timerange.start + Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_end = entry.timerange.end - Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
</ins><span class="cx"> 
</span><span class="cx">             # Verify that the requested timerange lies within the cache timerange
</span><span class="cx">             if compareDateTime(timerange.end, cached_end) &lt;= 0 and compareDateTime(timerange.start, cached_start) &gt;= 0:
</span><span class="lines">@@ -515,9 +515,9 @@
</span><span class="cx">         useruid = &quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     # Get the timezone property from the collection.
</span><del>-    has_prop = (yield calresource.hasProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+    has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
</ins><span class="cx">     if has_prop:
</span><del>-        tz = (yield calresource.readProperty((caldav_namespace, &quot;calendar-timezone&quot;), request))
</del><ins>+        tz = (yield calresource.readProperty(CalendarTimeZone(), request))
</ins><span class="cx">     else:
</span><span class="cx">         tz = None
</span><span class="cx"> 
</span><span class="lines">@@ -559,8 +559,8 @@
</span><span class="cx">             request.extendedLogItems[&quot;fb-uncached&quot;] = request.extendedLogItems.get(&quot;fb-uncached&quot;, 0) + 1
</span><span class="cx"> 
</span><span class="cx">             # We want to cache a large range of time based on the current date
</span><del>-            cache_start = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=0 - config.FreeBusyCacheDaysBack))
-            cache_end = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=config.FreeBusyCacheDaysForward))
</del><ins>+            cache_start = normalizeToUTC(DateTime.getToday() + Duration(days=0 - config.FreeBusyCacheDaysBack))
+            cache_end = normalizeToUTC(DateTime.getToday() + Duration(days=config.FreeBusyCacheDaysForward))
</ins><span class="cx"> 
</span><span class="cx">             # If the requested timerange would fit in our allowed cache range, trigger the cache creation
</span><span class="cx">             if compareDateTime(timerange.start, cache_start) &gt;= 0 and compareDateTime(timerange.end, cache_end) &lt;= 0:
</span><span class="lines">@@ -602,7 +602,7 @@
</span><span class="cx">         request.extendedLogItems[&quot;fb-cached&quot;] = request.extendedLogItems.get(&quot;fb-cached&quot;, 0) + 1
</span><span class="cx"> 
</span><span class="cx">         # Determine appropriate timezone (UTC is the default)
</span><del>-        tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
</del><ins>+        tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
</ins><span class="cx"> 
</span><span class="cx">     # We care about separate instances for VEVENTs only
</span><span class="cx">     aggregated_resources = {}
</span><span class="lines">@@ -645,15 +645,15 @@
</span><span class="cx">                 if float == 'Y':
</span><span class="cx">                     fbstart.setTimezone(tzinfo)
</span><span class="cx">                 else:
</span><del>-                    fbstart.setTimezone(PyCalendarTimezone(utc=True))
</del><ins>+                    fbstart.setTimezone(Timezone(utc=True))
</ins><span class="cx">                 fbend = parseSQLTimestampToPyCalendar(end)
</span><span class="cx">                 if float == 'Y':
</span><span class="cx">                     fbend.setTimezone(tzinfo)
</span><span class="cx">                 else:
</span><del>-                    fbend.setTimezone(PyCalendarTimezone(utc=True))
</del><ins>+                    fbend.setTimezone(Timezone(utc=True))
</ins><span class="cx"> 
</span><span class="cx">                 # Clip instance to time range
</span><del>-                clipped = clipPeriod(PyCalendarPeriod(fbstart, duration=fbend - fbstart), PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                clipped = clipPeriod(Period(fbstart, duration=fbend - fbstart), Period(timerange.start, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">                 # Double check for overlap
</span><span class="cx">                 if clipped:
</span><span class="lines">@@ -735,7 +735,7 @@
</span><span class="cx">     @param timerange: the time-range in which to expand
</span><span class="cx">     @type timerange: L{TimeRange}
</span><span class="cx">     @param tzinfo: timezone for floating time calculations
</span><del>-    @type tzinfo: L{PyCalendarTimezone}
</del><ins>+    @type tzinfo: L{Timezone}
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     # First expand the component
</span><span class="lines">@@ -775,7 +775,7 @@
</span><span class="cx">     @param calendar: the L{Component} that is the VCALENDAR containing the VEVENT's.
</span><span class="cx">     @param fbinfo: the tuple used to store the three types of fb data.
</span><span class="cx">     @param timerange: the time range to restrict free busy data to.
</span><del>-    @param tzinfo: the L{PyCalendarTimezone} for the timezone to use for floating/all-day events.
</del><ins>+    @param tzinfo: the L{Timezone} for the timezone to use for floating/all-day events.
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     # Expand out the set of instances for the event with in the required range
</span><span class="lines">@@ -820,10 +820,10 @@
</span><span class="cx">         # Clip period for this instance - use duration for period end if that
</span><span class="cx">         # is what original component used
</span><span class="cx">         if instance.component.hasProperty(&quot;DURATION&quot;):
</span><del>-            period = PyCalendarPeriod(fbstart, duration=fbend - fbstart)
</del><ins>+            period = Period(fbstart, duration=fbend - fbstart)
</ins><span class="cx">         else:
</span><del>-            period = PyCalendarPeriod(fbstart, fbend)
-        clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+            period = Period(fbstart, fbend)
+        clipped = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">         # Double check for overlap
</span><span class="cx">         if clipped:
</span><span class="lines">@@ -861,7 +861,7 @@
</span><span class="cx">             assert isinstance(fb.value(), list), &quot;FREEBUSY property does not contain a list of values: %r&quot; % (fb,)
</span><span class="cx">             for period in fb.value():
</span><span class="cx">                 # Clip period for this instance
</span><del>-                clipped = clipPeriod(period.getValue(), PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                clipped = clipPeriod(period.getValue(), Period(timerange.start, timerange.end))
</ins><span class="cx">                 if clipped:
</span><span class="cx">                     fbinfo[fbtype_mapper.get(fbtype, 0)].append(clipped)
</span><span class="cx"> 
</span><span class="lines">@@ -880,12 +880,12 @@
</span><span class="cx">         # Get overall start/end
</span><span class="cx">         start = vav.getStartDateUTC()
</span><span class="cx">         if start is None:
</span><del>-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         end = vav.getEndDateUTC()
</span><span class="cx">         if end is None:
</span><del>-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        period = PyCalendarPeriod(start, end)
-        overall = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        period = Period(start, end)
+        overall = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx">         if overall is None:
</span><span class="cx">             continue
</span><span class="cx"> 
</span><span class="lines">@@ -897,10 +897,10 @@
</span><span class="cx">         last_end = timerange.start
</span><span class="cx">         for period in periods:
</span><span class="cx">             if last_end &lt; period.getStart():
</span><del>-                busyperiods.append(PyCalendarPeriod(last_end, period.getStart()))
</del><ins>+                busyperiods.append(Period(last_end, period.getStart()))
</ins><span class="cx">             last_end = period.getEnd()
</span><span class="cx">         if last_end &lt; timerange.end:
</span><del>-            busyperiods.append(PyCalendarPeriod(last_end, timerange.end))
</del><ins>+            busyperiods.append(Period(last_end, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">         # Add to actual results mapped by busy type
</span><span class="cx">         fbtype = vav.propertyValue(&quot;BUSYTYPE&quot;)
</span><span class="lines">@@ -947,10 +947,10 @@
</span><span class="cx">             # Clip period for this instance - use duration for period end if that
</span><span class="cx">             # is what original component used
</span><span class="cx">             if instance.component.hasProperty(&quot;DURATION&quot;):
</span><del>-                period = PyCalendarPeriod(start, duration=end - start)
</del><ins>+                period = Period(start, duration=end - start)
</ins><span class="cx">             else:
</span><del>-                period = PyCalendarPeriod(start, end)
-            clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                period = Period(start, end)
+            clipped = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx">             if clipped:
</span><span class="cx">                 periods.append(clipped)
</span><span class="cx"> 
</span><span class="lines">@@ -993,7 +993,7 @@
</span><span class="cx">         fb.addProperty(attendee)
</span><span class="cx">     fb.addProperty(Property(&quot;DTSTART&quot;, timerange.start))
</span><span class="cx">     fb.addProperty(Property(&quot;DTEND&quot;, timerange.end))
</span><del>-    fb.addProperty(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+    fb.addProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx">     if len(fbinfo[0]) != 0:
</span><span class="cx">         fb.addProperty(Property(&quot;FREEBUSY&quot;, fbinfo[0], {&quot;FBTYPE&quot;: &quot;BUSY&quot;}))
</span><span class="cx">     if len(fbinfo[1]) != 0:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodreport_freebusypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/report_freebusy.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/report_freebusy.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/method/report_freebusy.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -31,7 +31,9 @@
</span><span class="cx"> from twext.web2.stream import MemoryStream
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav import caldavxml
</span><ins>+from twistedcaldav.ical import Component
</ins><span class="cx"> from twistedcaldav.method import report_common
</span><ins>+from twistedcaldav.util import bestAcceptType
</ins><span class="cx"> 
</span><span class="cx"> from txdav.caldav.icalendarstore import TimeRangeLowerLimit, TimeRangeUpperLimit
</span><span class="cx"> from txdav.xml import element as davxml
</span><span class="lines">@@ -60,6 +62,11 @@
</span><span class="cx"> 
</span><span class="cx">     matchcount = [0]
</span><span class="cx"> 
</span><ins>+    accepted_type = bestAcceptType(request.headers.getHeader(&quot;accept&quot;), Component.allowedTypes())
+    if accepted_type is None:
+        raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, &quot;Cannot generate requested data type&quot;))
+
+
</ins><span class="cx">     def generateFreeBusyInfo(calresource, uri): #@UnusedVariable
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Run a free busy report on the specified calendar collection
</span><span class="lines">@@ -104,7 +111,7 @@
</span><span class="cx">     fbcalendar = report_common.buildFreeBusyResult(fbinfo, timerange)
</span><span class="cx"> 
</span><span class="cx">     response = Response()
</span><del>-    response.stream = MemoryStream(str(fbcalendar))
-    response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;text/calendar; charset=utf-8&quot;))
</del><ins>+    response.stream = MemoryStream(fbcalendar.getText(accepted_type))
+    response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;%s; charset=utf-8&quot; % (accepted_type,)))
</ins><span class="cx"> 
</span><span class="cx">     returnValue(response)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmkcolxmlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/mkcolxml.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/mkcolxml.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/mkcolxml.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -45,11 +45,12 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;mkcol&quot;
</span><span class="cx"> 
</span><del>-    allowed_children = { (davxml.dav_namespace, &quot;set&quot;): (0, 1) }
</del><ins>+    allowed_children = {(davxml.dav_namespace, &quot;set&quot;): (0, 1)}
</ins><span class="cx"> 
</span><del>-    child_types = { &quot;WebDAVUnknownElement&quot;: (0, None) }
</del><ins>+    child_types = {&quot;WebDAVUnknownElement&quot;: (0, None)}
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class MakeCollectionResponse (davxml.WebDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -58,4 +59,4 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     name = &quot;mkcol-response&quot;
</span><span class="cx"> 
</span><del>-    allowed_children = { davxml.WebDAVElement: (0, None) }
</del><ins>+    allowed_children = {davxml.WebDAVElement: (0, None)}
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavnotificationspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/notifications.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/notifications.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/notifications.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -48,43 +48,53 @@
</span><span class="cx">         self._parent = parent
</span><span class="cx">         CalDAVResource.__init__(self)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def principalCollections(self):
</span><span class="cx">         return self._parent.principalCollections()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceName(self):
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def http_PUT(self, request):
</span><span class="cx">         return responsecode.FORBIDDEN
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def http_DELETE(self, request):
</span><del>-        
</del><ins>+
</ins><span class="cx">         response = (yield super(NotificationResource, self).http_DELETE(request))
</span><span class="cx">         if response == responsecode.NO_CONTENT:
</span><span class="cx">             yield self._parent.removedNotifictionMessage(request, self.resourceName())
</span><span class="cx">         returnValue(response)
</span><del>-    
</del><ins>+
+
+
</ins><span class="cx"> class NotificationCollectionResource(ReadOnlyNoCopyResourceMixIn, CalDAVResource):
</span><span class="cx"> 
</span><span class="cx">     def notificationsDB(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         if not hasattr(self, &quot;_notificationsDB&quot;):
</span><span class="cx">             self._notificationsDB = NotificationsDatabase(self)
</span><span class="cx">         return self._notificationsDB
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return True
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceType(self):
</span><span class="cx">         return davxml.ResourceType.notification
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def addNotification(self, request, uid, xmltype, xmldata):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # Write data to file
</span><span class="cx">         rname = uid + &quot;.xml&quot;
</span><span class="cx">         yield self._writeNotification(request, uid, rname, xmltype, xmldata)
</span><span class="lines">@@ -103,7 +113,7 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def deleteNotifictionMessageByUID(self, request, uid):
</span><del>-        
</del><ins>+
</ins><span class="cx">         # See if it exists and delete the resource
</span><span class="cx">         record = yield self.notificationsDB().recordForUID(uid)
</span><span class="cx">         if record:
</span><span class="lines">@@ -117,7 +127,7 @@
</span><span class="cx">         record = yield self.notificationsDB().recordForName(rname)
</span><span class="cx">         if record:
</span><span class="cx">             yield self.deleteNotification(request, record)
</span><del>-        
</del><ins>+
</ins><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -131,13 +141,16 @@
</span><span class="cx">         return maybeDeferred(self.notificationsDB().removeRecordForName, rname)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class NotificationRecord(object):
</span><del>-    
</del><ins>+
</ins><span class="cx">     def __init__(self, uid, name, xmltype):
</span><span class="cx">         self.uid = uid
</span><span class="cx">         self.name = name
</span><span class="cx">         self.xmltype = xmltype
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class NotificationsDatabase(AbstractSQLDatabase):
</span><span class="cx">     log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -154,35 +167,40 @@
</span><span class="cx">         db_filename = os.path.join(self.resource.fp.path, NotificationsDatabase.db_basename)
</span><span class="cx">         super(NotificationsDatabase, self).__init__(db_filename, True, autocommit=True)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def allRecords(self):
</span><del>-        
</del><ins>+
</ins><span class="cx">         records = self._db_execute(&quot;select * from NOTIFICATIONS&quot;)
</span><span class="cx">         return [self._makeRecord(row) for row in (records if records is not None else ())]
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def recordForUID(self, uid):
</span><del>-        
</del><ins>+
</ins><span class="cx">         row = self._db_execute(&quot;select * from NOTIFICATIONS where UID = :1&quot;, uid)
</span><span class="cx">         return self._makeRecord(row[0]) if row else None
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def addOrUpdateRecord(self, record):
</span><span class="cx"> 
</span><span class="cx">         self._db_execute(&quot;&quot;&quot;insert or replace into NOTIFICATIONS (UID, NAME, TYPE)
</span><span class="cx">             values (:1, :2, :3)
</span><span class="cx">             &quot;&quot;&quot;, record.uid, record.name, record.xmltype,
</span><span class="cx">         )
</span><del>-            
</del><ins>+
</ins><span class="cx">         self._db_execute(
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             insert or replace into REVISIONS (NAME, REVISION, DELETED)
</span><span class="cx">             values (:1, :2, :3)
</span><span class="cx">             &quot;&quot;&quot;, record.name, self.bumpRevision(fast=True), 'N',
</span><span class="cx">         )
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def removeRecordForUID(self, uid):
</span><span class="cx"> 
</span><span class="cx">         record = self.recordForUID(uid)
</span><span class="cx">         self.removeRecordForName(record.name)
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def removeRecordForName(self, rname):
</span><span class="cx"> 
</span><span class="cx">         self._db_execute(&quot;delete from NOTIFICATIONS where NAME = :1&quot;, rname)
</span><span class="lines">@@ -192,12 +210,13 @@
</span><span class="cx">             where NAME = :3
</span><span class="cx">             &quot;&quot;&quot;, self.bumpRevision(fast=True), 'Y', rname
</span><span class="cx">         )
</span><del>-    
</del><ins>+
+
</ins><span class="cx">     def whatchanged(self, revision):
</span><span class="cx"> 
</span><span class="cx">         results = [(name.encode(&quot;utf-8&quot;), deleted) for name, deleted in self._db_execute(&quot;select NAME, DELETED from REVISIONS where REVISION &gt; :1&quot;, revision)]
</span><del>-        results.sort(key=lambda x:x[1])
-        
</del><ins>+        results.sort(key=lambda x: x[1])
+
</ins><span class="cx">         changed = []
</span><span class="cx">         deleted = []
</span><span class="cx">         for name, wasdeleted in results:
</span><span class="lines">@@ -209,14 +228,16 @@
</span><span class="cx">                     changed.append(name)
</span><span class="cx">             else:
</span><span class="cx">                 raise SyncTokenValidException
</span><del>-        
</del><ins>+
</ins><span class="cx">         return changed, deleted,
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def lastRevision(self):
</span><span class="cx">         return self._db_value_for_sql(
</span><span class="cx">             &quot;select REVISION from REVISION_SEQUENCE&quot;
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def bumpRevision(self, fast=False):
</span><span class="cx">         self._db_execute(
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="lines">@@ -230,18 +251,21 @@
</span><span class="cx">             &quot;&quot;&quot;,
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_version(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the schema version assigned to this index.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return NotificationsDatabase.schema_version
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_type(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the collection type assigned to this index.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return NotificationsDatabase.db_type
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_init_data_tables(self, q):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Initialise the underlying database tables.
</span><span class="lines">@@ -302,6 +326,7 @@
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_upgrade_data_tables(self, q, old_version):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the data from an older version of the DB.
</span><span class="lines">@@ -310,7 +335,7 @@
</span><span class="cx">         # Nothing to do as we have not changed the schema
</span><span class="cx">         pass
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _makeRecord(self, row):
</span><del>-        
</del><ins>+
</ins><span class="cx">         return NotificationRecord(*[str(item) if type(item) == types.UnicodeType else item for item in row])
</span><del>-
</del></span></pre></div>
<a id="CalendarServertrunktwistedcaldavquerycalendarqueryfilterpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -28,8 +28,8 @@
</span><span class="cx"> from twistedcaldav.dateops import timeRangesOverlap
</span><span class="cx"> from twistedcaldav.ical import Component, Property
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">                     instances = None
</span><span class="cx">                 else:
</span><span class="cx">                     # Expand the instances up to infinity
</span><del>-                    instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), ignoreInvalidInstances=True)
</del><ins>+                    instances = component.expandTimeRanges(DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)), ignoreInvalidInstances=True)
</ins><span class="cx">             else:
</span><span class="cx">                 instances = component.expandTimeRanges(maxend, ignoreInvalidInstances=True)
</span><span class="cx">         else:
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx">         Set the default timezone to use with this query.
</span><span class="cx">         @param calendar: a L{Component} for the VCALENDAR containing the one
</span><span class="cx">             VTIMEZONE that we want
</span><del>-        @return: the L{PyCalendarTimezone} derived from the VTIMEZONE or utc.
</del><ins>+        @return: the L{Timezone} derived from the VTIMEZONE or utc.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if tzelement is None:
</span><span class="lines">@@ -127,7 +127,7 @@
</span><span class="cx">         elif isinstance(tzelement, Component):
</span><span class="cx">             tz = tzelement.gettimezone()
</span><span class="cx">         if tz is None:
</span><del>-            tz = PyCalendarTimezone(utc=True)
</del><ins>+            tz = Timezone(utc=True)
</ins><span class="cx">         self.child.settzinfo(tz)
</span><span class="cx">         return tz
</span><span class="cx"> 
</span><span class="lines">@@ -357,7 +357,7 @@
</span><span class="cx">     def settzinfo(self, tzinfo):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Set the default timezone to use with this query.
</span><del>-        @param tzinfo: a L{PyCalendarTimezone} to use.
</del><ins>+        @param tzinfo: a L{Timezone} to use.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Give tzinfo to any TimeRange we have
</span><span class="lines">@@ -374,7 +374,7 @@
</span><span class="cx">         Get the date farthest into the future in any time-range elements
</span><span class="cx"> 
</span><span class="cx">         @param currentMaximum: current future value to compare with
</span><del>-        @type currentMaximum: L{PyCalendarDateTime}
</del><ins>+        @type currentMaximum: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Give tzinfo to any TimeRange we have
</span><span class="lines">@@ -471,7 +471,7 @@
</span><span class="cx">     def settzinfo(self, tzinfo):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Set the default timezone to use with this query.
</span><del>-        @param tzinfo: a L{PyCalendarTimezone} to use.
</del><ins>+        @param tzinfo: a L{Timezone} to use.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Give tzinfo to any TimeRange we have
</span><span class="lines">@@ -484,7 +484,7 @@
</span><span class="cx">         Get the date farthest into the future in any time-range elements
</span><span class="cx"> 
</span><span class="cx">         @param currentMaximum: current future value to compare with
</span><del>-        @type currentMaximum: L{PyCalendarDateTime}
</del><ins>+        @type currentMaximum: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Give tzinfo to any TimeRange we have
</span><span class="lines">@@ -652,15 +652,15 @@
</span><span class="cx">         if &quot;start&quot; not in xml_element.attributes and &quot;end&quot; not in xml_element.attributes:
</span><span class="cx">             raise ValueError(&quot;One of 'start' or 'end' must be present in CALDAV:time-range&quot;)
</span><span class="cx"> 
</span><del>-        self.start = PyCalendarDateTime.parseText(xml_element.attributes[&quot;start&quot;]) if &quot;start&quot; in xml_element.attributes else None
-        self.end = PyCalendarDateTime.parseText(xml_element.attributes[&quot;end&quot;]) if &quot;end&quot; in xml_element.attributes else None
</del><ins>+        self.start = DateTime.parseText(xml_element.attributes[&quot;start&quot;]) if &quot;start&quot; in xml_element.attributes else None
+        self.end = DateTime.parseText(xml_element.attributes[&quot;end&quot;]) if &quot;end&quot; in xml_element.attributes else None
</ins><span class="cx">         self.tzinfo = None
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def settzinfo(self, tzinfo):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Set the default timezone to use with this query.
</span><del>-        @param tzinfo: a L{PyCalendarTimezone} to use.
</del><ins>+        @param tzinfo: a L{Timezone} to use.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Give tzinfo to any TimeRange we have
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavquerytesttest_calendarquerypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx"> from twistedcaldav import caldavxml
</span><span class="cx"> from twistedcaldav.query import calendarqueryfilter
</span><span class="cx"> import twistedcaldav.test.util
</span><del>-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.timezone import Timezone
</ins><span class="cx"> from twistedcaldav.query.calendarquery import sqlcalendarquery
</span><span class="cx"> 
</span><span class="cx"> class Tests(twistedcaldav.test.util.TestCase):
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx">             )
</span><span class="cx">         )
</span><span class="cx">         filter = calendarqueryfilter.Filter(filter)
</span><del>-        filter.child.settzinfo(PyCalendarTimezone(tzid=&quot;America/New_York&quot;))
</del><ins>+        filter.child.settzinfo(Timezone(tzid=&quot;America/New_York&quot;))
</ins><span class="cx"> 
</span><span class="cx">         sql, args = sqlcalendarquery(filter)
</span><span class="cx">         self.assertTrue(sql.find(&quot;RESOURCE&quot;) != -1)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">             )
</span><span class="cx">         )
</span><span class="cx">         filter = calendarqueryfilter.Filter(filter)
</span><del>-        filter.child.settzinfo(PyCalendarTimezone(tzid=&quot;America/New_York&quot;))
</del><ins>+        filter.child.settzinfo(Timezone(tzid=&quot;America/New_York&quot;))
</ins><span class="cx"> 
</span><span class="cx">         sql, args = sqlcalendarquery(filter)
</span><span class="cx">         self.assertTrue(sql.find(&quot;RESOURCE&quot;) != -1)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">             )
</span><span class="cx">         )
</span><span class="cx">         filter = calendarqueryfilter.Filter(filter)
</span><del>-        filter.child.settzinfo(PyCalendarTimezone(tzid=&quot;America/New_York&quot;))
</del><ins>+        filter.child.settzinfo(Timezone(tzid=&quot;America/New_York&quot;))
</ins><span class="cx"> 
</span><span class="cx">         sql, args = sqlcalendarquery(filter)
</span><span class="cx">         self.assertTrue(sql.find(&quot;RESOURCE&quot;) != -1)
</span><span class="lines">@@ -119,7 +119,7 @@
</span><span class="cx">             )
</span><span class="cx">         )
</span><span class="cx">         filter = calendarqueryfilter.Filter(filter)
</span><del>-        filter.child.settzinfo(PyCalendarTimezone(tzid=&quot;America/New_York&quot;))
</del><ins>+        filter.child.settzinfo(Timezone(tzid=&quot;America/New_York&quot;))
</ins><span class="cx"> 
</span><span class="cx">         sql, args = sqlcalendarquery(filter)
</span><span class="cx">         self.assertTrue(sql.find(&quot;RESOURCE&quot;) != -1)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavquerytesttest_queryfilterpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> from twistedcaldav.query import calendarqueryfilter
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="cx"> from twistedcaldav.caldavxml import TimeZone
</span><del>-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> class Tests(twistedcaldav.test.util.TestCase):
</span><span class="cx"> 
</span><span class="lines">@@ -227,4 +227,4 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;))
</span><span class="cx"> 
</span><del>-        self.assertTrue(isinstance(tz, PyCalendarTimezone))
</del><ins>+        self.assertTrue(isinstance(tz, Timezone))
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/resource.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/resource.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/resource.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> from twistedcaldav.directory.internal import InternalDirectoryRecord
</span><span class="cx"> from twistedcaldav.extensions import DAVResource, DAVPrincipalResource, \
</span><span class="cx">     DAVResourceWithChildrenMixin
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.icaldav import ICalDAVResource, ICalendarPrincipalResource
</span><span class="lines">@@ -257,10 +258,11 @@
</span><span class="cx">                 # Redirect to include trailing '/' in URI
</span><span class="cx">                 return RedirectResponse(request.unparseURL(path=urllib.quote(urllib.unquote(request.path), safe=':/') + '/'))
</span><span class="cx"> 
</span><del>-            def _defer(data):
</del><ins>+            def _defer(result):
+                data, accepted_type = result
</ins><span class="cx">                 response = Response()
</span><del>-                response.stream = MemoryStream(str(data))
-                response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;text/calendar&quot;))
</del><ins>+                response.stream = MemoryStream(data.getText(accepted_type))
+                response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;%s; charset=utf-8&quot; % (accepted_type,)))
</ins><span class="cx">                 return response
</span><span class="cx"> 
</span><span class="cx">             d = self.iCalendarRolledup(request)
</span><span class="lines">@@ -375,7 +377,7 @@
</span><span class="cx">                                   (self,))
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def storeStream(self, stream):
</del><ins>+    def storeStream(self, stream, format):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Store the content of the stream in this resource, as it would via a PUT.
</span><span class="cx"> 
</span><span class="lines">@@ -385,8 +387,7 @@
</span><span class="cx">         @return: a L{Deferred} which fires with an HTTP response.
</span><span class="cx">         @rtype: L{Deferred}
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        raise NotImplementedError(&quot;%s does not implement storeStream&quot; %
-                                  (self,))
</del><ins>+        raise NotImplementedError(&quot;%s does not implement storeStream&quot; % (self,))
</ins><span class="cx"> 
</span><span class="cx">     # End transitional new-store interface
</span><span class="cx"> 
</span><span class="lines">@@ -605,12 +606,21 @@
</span><span class="cx">             returnValue(self.getSupportedComponentSet())
</span><span class="cx"> 
</span><span class="cx">         elif qname == caldavxml.SupportedCalendarData.qname() and self.isPseudoCalendarCollection():
</span><del>-            returnValue(caldavxml.SupportedCalendarData(
</del><ins>+            dataTypes = []
+            dataTypes.append(
</ins><span class="cx">                 caldavxml.CalendarData(**{
</span><span class="cx">                     &quot;content-type&quot;: &quot;text/calendar&quot;,
</span><span class="cx">                     &quot;version&quot;     : &quot;2.0&quot;,
</span><span class="cx">                 }),
</span><del>-            ))
</del><ins>+            )
+            if config.EnableJSONData:
+                dataTypes.append(
+                    caldavxml.CalendarData(**{
+                        &quot;content-type&quot;: &quot;application/calendar+json&quot;,
+                        &quot;version&quot;     : &quot;2.0&quot;,
+                    }),
+                )
+            returnValue(caldavxml.SupportedCalendarData(*dataTypes))
</ins><span class="cx"> 
</span><span class="cx">         elif qname == caldavxml.MaxResourceSize.qname() and self.isPseudoCalendarCollection():
</span><span class="cx">             if config.MaxResourceSize:
</span><span class="lines">@@ -642,12 +652,21 @@
</span><span class="cx"> 
</span><span class="cx">         elif qname == carddavxml.SupportedAddressData.qname() and self.isAddressBookCollection():
</span><span class="cx">             # CardDAV, section 6.2.2
</span><del>-            returnValue(carddavxml.SupportedAddressData(
</del><ins>+            dataTypes = []
+            dataTypes.append(
</ins><span class="cx">                 carddavxml.AddressDataType(**{
</span><span class="cx">                     &quot;content-type&quot;: &quot;text/vcard&quot;,
</span><span class="cx">                     &quot;version&quot;     : &quot;3.0&quot;,
</span><span class="cx">                 }),
</span><del>-            ))
</del><ins>+            )
+            if config.EnableJSONData:
+                dataTypes.append(
+                    carddavxml.AddressDataType(**{
+                        &quot;content-type&quot;: &quot;application/vcard+json&quot;,
+                        &quot;version&quot;     : &quot;3.0&quot;,
+                    }),
+                )
+            returnValue(carddavxml.SupportedAddressData(*dataTypes))
</ins><span class="cx"> 
</span><span class="cx">         elif qname == carddavxml.MaxResourceSize.qname() and self.isAddressBookCollection() and not self.isDirectoryBackedAddressBookCollection():
</span><span class="cx">             # CardDAV, section 6.2.3
</span><span class="lines">@@ -1446,11 +1465,6 @@
</span><span class="cx">         returnValue(caldata)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def iCalendarText(self):
-        # storebridge handles this method
-        raise NotImplementedError()
-
-
</del><span class="cx">     def iCalendar(self):
</span><span class="cx">         # storebridge handles this method
</span><span class="cx">         raise NotImplementedError()
</span><span class="lines">@@ -2446,18 +2460,13 @@
</span><span class="cx"> 
</span><span class="cx">         if qname == caldavxml.SupportedCalendarComponentSets.qname():
</span><span class="cx">             if config.RestrictCalendarsToOneComponentType:
</span><del>-                prop = caldavxml.SupportedCalendarComponentSets(
</del><ins>+                prop = caldavxml.SupportedCalendarComponentSets(*[
</ins><span class="cx">                     caldavxml.SupportedCalendarComponentSet(
</span><span class="cx">                         caldavxml.CalendarComponent(
</span><del>-                            name=&quot;VEVENT&quot;,
</del><ins>+                            name=name,
</ins><span class="cx">                         ),
</span><del>-                    ),
-                    caldavxml.SupportedCalendarComponentSet(
-                        caldavxml.CalendarComponent(
-                            name=&quot;VTODO&quot;,
-                        ),
-                    ),
-                )
</del><ins>+                    ) for name in ical.allowedStoreComponents
+                ])
</ins><span class="cx">             else:
</span><span class="cx">                 prop = caldavxml.SupportedCalendarComponentSets()
</span><span class="cx">             returnValue(prop)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavscheduling_storecaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> from twistedcaldav import caldavxml, customxml
</span><span class="cx"> from twistedcaldav.caldavxml import caldav_namespace, CalendarFreeBusySet
</span><span class="cx"> from twistedcaldav.customxml import calendarserver_namespace
</span><del>-from twistedcaldav.ical import allowedComponents, Component
</del><ins>+from twistedcaldav.ical import Component, allowedSchedulingComponents
</ins><span class="cx"> from twistedcaldav.resource import CalDAVResource
</span><span class="cx"> from twistedcaldav.resource import isCalendarCollectionResource
</span><span class="cx"> 
</span><span class="lines">@@ -300,8 +300,14 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Write either the default VEVENT or VTODO calendar property, validating and canonicalizing the value
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        tasks = property.qname() == customxml.ScheduleDefaultTasksURL
-        error_element = (calendarserver_namespace, &quot;valid-schedule-default-tasks-URL&quot;) if tasks else (caldav_namespace, &quot;valid-schedule-default-calendar-URL&quot;)
</del><ins>+        if property.qname() == caldavxml.ScheduleDefaultCalendarURL.qname():
+            ctype = &quot;VEVENT&quot;
+            error_element = (caldav_namespace, &quot;valid-schedule-default-calendar-URL&quot;)
+        elif property.qname() == customxml.ScheduleDefaultTasksURL.qname():
+            ctype = &quot;VTODO&quot;
+            error_element = (calendarserver_namespace, &quot;valid-schedule-default-tasks-URL&quot;)
+        else:
+            returnValue(None)
</ins><span class="cx"> 
</span><span class="cx">         # Verify that the calendar added in the PROPPATCH is valid.
</span><span class="cx">         property.children = [davxml.HRef(normalizeURL(str(href))) for href in property.children]
</span><span class="lines">@@ -325,7 +331,7 @@
</span><span class="cx"> 
</span><span class="cx">         try:
</span><span class="cx">             # Now set it on the new store object
</span><del>-            yield self.parent._newStoreHome.setDefaultCalendar(cal._newStoreObject, tasks)
</del><ins>+            yield self.parent._newStoreHome.setDefaultCalendar(cal._newStoreObject, ctype)
</ins><span class="cx">         except InvalidDefaultCalendar as e:
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.CONFLICT,
</span><span class="lines">@@ -390,7 +396,7 @@
</span><span class="cx"> 
</span><span class="cx">     def getSupportedComponentSet(self):
</span><span class="cx">         return caldavxml.SupportedCalendarComponentSet(
</span><del>-            *[caldavxml.CalendarComponent(name=item) for item in allowedComponents]
</del><ins>+            *[caldavxml.CalendarComponent(name=item) for item in allowedSchedulingComponents]
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -407,7 +413,7 @@
</span><span class="cx">         # Check authentication and access controls
</span><span class="cx">         yield self.authorize(request, (caldavxml.ScheduleSend(),))
</span><span class="cx"> 
</span><del>-        calendar = (yield self.loadCalendarFromRequest(request))
</del><ins>+        calendar, format = (yield self.loadCalendarFromRequest(request))
</ins><span class="cx">         originator = (yield self.loadOriginatorFromRequestDetails(request))
</span><span class="cx">         recipients = self.loadRecipientsFromCalendarData(calendar)
</span><span class="cx"> 
</span><span class="lines">@@ -431,14 +437,25 @@
</span><span class="cx"> 
</span><span class="cx">         # Do the POST processing treating
</span><span class="cx">         result = (yield scheduler.doSchedulingViaPOST(originator, recipients, calendar))
</span><del>-        returnValue(result.response())
</del><ins>+        returnValue(result.response(format=format))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def determineType(self, content_type):
+        &quot;&quot;&quot;
+        Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+        &quot;&quot;&quot;
+        format = None
+        if content_type is not None:
+            format = &quot;%s/%s&quot; % (content_type.mediaType, content_type.mediaSubtype,)
+        return format if format in Component.allowedTypes() else None
+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def loadCalendarFromRequest(self, request):
</span><span class="cx">         # Must be content-type text/calendar
</span><span class="cx">         contentType = request.headers.getHeader(&quot;content-type&quot;)
</span><del>-        if contentType is not None and (contentType.mediaType, contentType.mediaSubtype) != (&quot;text&quot;, &quot;calendar&quot;):
</del><ins>+        format = self.determineType(contentType)
+        if format is None:
</ins><span class="cx">             self.log.error(&quot;MIME type %s not allowed in calendar collection&quot; % (contentType,))
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.FORBIDDEN,
</span><span class="lines">@@ -448,7 +465,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Parse the calendar object from the HTTP request stream
</span><span class="cx">         try:
</span><del>-            calendar = (yield Component.fromIStream(request.stream))
</del><ins>+            calendar = (yield Component.fromIStream(request.stream, format=format))
</ins><span class="cx">         except:
</span><span class="cx">             # FIXME: Bare except
</span><span class="cx">             self.log.error(&quot;Error while handling POST: %s&quot; % (Failure(),))
</span><span class="lines">@@ -458,7 +475,7 @@
</span><span class="cx">                 description=&quot;Can't parse calendar data&quot;
</span><span class="cx">             ))
</span><span class="cx"> 
</span><del>-        returnValue(calendar)
</del><ins>+        returnValue((calendar, format,))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavsharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/sharing.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/sharing.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/sharing.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
</span><span class="cx"> from twistedcaldav.linkresource import LinkFollowerMixIn
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> # FIXME: Get rid of these imports
</span><span class="lines">@@ -740,7 +740,7 @@
</span><span class="cx">         typeAttr = {'shared-type': self.sharedResourceType()}
</span><span class="cx">         xmltype = customxml.InviteNotification(**typeAttr)
</span><span class="cx">         xmldata = customxml.Notification(
</span><del>-            customxml.DTStamp.fromString(PyCalendarDateTime.getNowUTC().getText()),
</del><ins>+            customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
</ins><span class="cx">             customxml.InviteNotification(
</span><span class="cx">                 customxml.UID.fromString(invitation.uid()),
</span><span class="cx">                 element.HRef.fromString(userid),
</span><span class="lines">@@ -1362,7 +1362,7 @@
</span><span class="cx">         record = shareePrincipal.record
</span><span class="cx"> 
</span><span class="cx">         xmldata = customxml.Notification(
</span><del>-            customxml.DTStamp.fromString(PyCalendarDateTime.getNowUTC().getText()),
</del><ins>+            customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
</ins><span class="cx">             customxml.InviteReply(
</span><span class="cx">                 *(
</span><span class="cx">                     (
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavsqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/sql.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/sql.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/sql.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> Generic SQL database access object.
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-__all__ = [ 
</del><ins>+__all__ = [
</ins><span class="cx">     &quot;db_prefix&quot;,
</span><span class="cx">     &quot;DatabaseError&quot;,
</span><span class="cx">     &quot;AbstractSQLDatabase&quot;,
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, dbpath, persistent, autocommit=False):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         @param dbpath: the path where the db file is stored.
</span><span class="cx">         @type dbpath: str
</span><span class="cx">         @param persistent: C{True} if the data in the DB must be perserved during upgrades,
</span><span class="lines">@@ -63,21 +63,25 @@
</span><span class="cx">         self.persistent = persistent
</span><span class="cx">         self.autocommit = autocommit
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def __repr__(self):
</span><span class="cx">         return &quot;&lt;%s %r&gt;&quot; % (self.__class__.__name__, self.dbpath)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_version(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the schema version assigned to this index.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _db_type(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the collection type assigned to this index.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><del>-        
</del><ins>+
+
</ins><span class="cx">     def _db(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Access the underlying database.
</span><span class="lines">@@ -108,7 +112,7 @@
</span><span class="cx">                 # Create CALDAV table if needed
</span><span class="cx"> 
</span><span class="cx">                 if self._test_schema_table(q):
</span><del>-                    
</del><ins>+
</ins><span class="cx">                     version, dbtype = self._get_schema_version(q)
</span><span class="cx"> 
</span><span class="cx">                     if (version != self._db_version()) or (dbtype != self._db_type()):
</span><span class="lines">@@ -130,7 +134,7 @@
</span><span class="cx">                         if version != self._db_version():
</span><span class="cx">                             log.error(&quot;Database %s has different schema (v.%s vs. v.%s)&quot;
</span><span class="cx">                                       % (db_filename, version, self._db_version()))
</span><del>-                            
</del><ins>+
</ins><span class="cx">                             # Upgrade the DB
</span><span class="cx">                             return self._db_upgrade(version)
</span><span class="cx"> 
</span><span class="lines">@@ -139,9 +143,11 @@
</span><span class="cx"> 
</span><span class="cx">                 self._db_connection.commit()
</span><span class="cx">             finally:
</span><del>-                if q is not None: q.close()
</del><ins>+                if q is not None:
+                    q.close()
</ins><span class="cx">         return self._db_connection
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _test_schema_table(self, q):
</span><span class="cx">         q.execute(&quot;&quot;&quot;
</span><span class="cx">         select (1) from SQLITE_MASTER
</span><span class="lines">@@ -149,6 +155,7 @@
</span><span class="cx">         &quot;&quot;&quot;)
</span><span class="cx">         return q.fetchone()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _get_schema_version(self, q):
</span><span class="cx">         q.execute(
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="lines">@@ -157,7 +164,8 @@
</span><span class="cx">             &quot;&quot;&quot;)
</span><span class="cx">         version = q.fetchone()
</span><span class="cx"> 
</span><del>-        if version is not None: version = version[0]
</del><ins>+        if version is not None:
+            version = version[0]
</ins><span class="cx"> 
</span><span class="cx">         q.execute(
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="lines">@@ -166,10 +174,12 @@
</span><span class="cx">             &quot;&quot;&quot;)
</span><span class="cx">         dbtype = q.fetchone()
</span><span class="cx"> 
</span><del>-        if dbtype is not None: dbtype = dbtype[0]
</del><ins>+        if dbtype is not None:
+            dbtype = dbtype[0]
</ins><span class="cx"> 
</span><span class="cx">         return version, dbtype
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_init(self, db_filename, q):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Initialise the underlying database tables.
</span><span class="lines">@@ -183,7 +193,7 @@
</span><span class="cx">         old_isolation = self._db_connection.isolation_level
</span><span class="cx">         self._db_connection.isolation_level = None
</span><span class="cx">         q.execute(&quot;begin exclusive transaction&quot;)
</span><del>-        
</del><ins>+
</ins><span class="cx">         # We re-check whether the schema table is present again AFTER we've got an exclusive
</span><span class="cx">         # lock as some other server process may have snuck in and already created it
</span><span class="cx">         # before we got the lock, or whilst we were waiting for it.
</span><span class="lines">@@ -199,6 +209,7 @@
</span><span class="cx"> 
</span><span class="cx">         self._db_connection.isolation_level = old_isolation
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_init_schema_table(self, q):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Initialise the underlying database tables.
</span><span class="lines">@@ -229,6 +240,7 @@
</span><span class="cx">             &quot;&quot;&quot;, [self._db_type()]
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_init_data_tables(self, q):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Initialise the underlying database tables.
</span><span class="lines">@@ -237,6 +249,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         raise NotImplementedError
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_recreate(self, do_commit=True):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Recreate the database tables.
</span><span class="lines">@@ -246,15 +259,17 @@
</span><span class="cx">         if do_commit:
</span><span class="cx">             self._db_commit()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_can_upgrade(self, old_version):
</span><del>-        
</del><ins>+
</ins><span class="cx">         return self.persistent
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_upgrade(self, old_version):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the database tables.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if self._db_can_upgrade(old_version):
</span><span class="cx">             self._db_connection = sqlite.connect(self.dbpath, isolation_level=None)
</span><span class="cx">             q = self._db_connection.cursor()
</span><span class="lines">@@ -278,6 +293,7 @@
</span><span class="cx"> 
</span><span class="cx">         return self._db()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_upgrade_data_tables(self, q, old_version):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the data from an older version of the DB.
</span><span class="lines">@@ -286,6 +302,7 @@
</span><span class="cx">         # cannot be thrown away.
</span><span class="cx">         raise NotImplementedError(&quot;Persistent databases MUST support an upgrade method.&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_upgrade_schema(self, q):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Upgrade the stored schema version to the current one.
</span><span class="lines">@@ -297,11 +314,13 @@
</span><span class="cx">             &quot;&quot;&quot;, [self._db_version()]
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_close(self):
</span><span class="cx">         if hasattr(self, &quot;_db_connection&quot;):
</span><span class="cx">             self._db_connection.close()
</span><span class="cx">             del self._db_connection
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_values_for_sql(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute an SQL query and obtain the resulting values.
</span><span class="lines">@@ -313,6 +332,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return (row[0] for row in self._db_execute(sql, *query_params))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_value_for_sql(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute an SQL query and obtain a single value.
</span><span class="lines">@@ -328,6 +348,7 @@
</span><span class="cx">             value = row
</span><span class="cx">         return value
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _db_execute(self, sql, *query_params):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute an SQL query and obtain the resulting values.
</span><span class="lines">@@ -347,5 +368,10 @@
</span><span class="cx">         finally:
</span><span class="cx">             q.close()
</span><span class="cx"> 
</span><del>-    def _db_commit  (self): self._db_connection.commit()
-    def _db_rollback(self): self._db_connection.rollback()
</del><ins>+
+    def _db_commit(self):
+        self._db_connection.commit()
+
+
+    def _db_rollback(self):
+        self._db_connection.rollback()
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/stdconfig.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> from twistedcaldav.util import computeProcessCount
</span><span class="cx"> 
</span><span class="cx"> from calendarserver.push.util import getAPNTopicFromCertificate
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -545,6 +546,11 @@
</span><span class="cx">     &quot;EnableManagedAttachments&quot;    : False, # Support Managed Attachments
</span><span class="cx"> 
</span><span class="cx">     #
</span><ins>+    # Generic CalDAV/CardDAV extensions
+    #
+    &quot;EnableJSONData&quot;          : True, # Allow clients to send/receive JSON jCal and jCard format data
+
+    #
</ins><span class="cx">     # Non-standard CalDAV extensions
</span><span class="cx">     #
</span><span class="cx">     &quot;EnableDropBox&quot;           : False, # Calendar Drop Box
</span><span class="lines">@@ -594,6 +600,12 @@
</span><span class="cx">                                                    # If on, it will also cause new accounts to provision with separate
</span><span class="cx">                                                    # calendars for events and tasks.
</span><span class="cx"> 
</span><ins>+    &quot;SupportedComponents&quot; : [                      # Set of supported iCalendar components
+        &quot;VEVENT&quot;,
+        &quot;VTODO&quot;,
+        #&quot;VPOLL&quot;,
+    ],
+
</ins><span class="cx">     &quot;ParallelUpgrades&quot; : False, # Perform upgrades - currently only the
</span><span class="cx">                                    # database -&gt; filesystem migration - but in
</span><span class="cx">                                    # the future, hopefully all relevant
</span><span class="lines">@@ -1502,6 +1514,14 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+def _updateICalendar(configDict, reloading=False):
+    &quot;&quot;&quot;
+    Updated support iCalendar components.
+    &quot;&quot;&quot;
+    ical._updateAllowedComponents(tuple(configDict.SupportedComponents))
+
+
+
</ins><span class="cx"> def _updateScheduling(configDict, reloading=False):
</span><span class="cx">     #
</span><span class="cx">     # Scheduling
</span><span class="lines">@@ -1612,6 +1632,7 @@
</span><span class="cx">     _updateRejectClients,
</span><span class="cx">     _updateLogLevels,
</span><span class="cx">     _updateNotifications,
</span><ins>+    _updateICalendar,
</ins><span class="cx">     _updateScheduling,
</span><span class="cx">     _updateServers,
</span><span class="cx">     _updateCompliance,
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstorebridgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/storebridge.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/storebridge.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -15,7 +15,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> from twext.web2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
</span><span class="lines">@@ -36,14 +36,14 @@
</span><span class="cx"> from twisted.python.hashlib import md5
</span><span class="cx"> from twisted.python.util import FancyEqMixin
</span><span class="cx"> 
</span><del>-from twistedcaldav import customxml, carddavxml, caldavxml
</del><ins>+from twistedcaldav import customxml, carddavxml, caldavxml, ical
</ins><span class="cx"> from twistedcaldav.caldavxml import caldav_namespace, MaxAttendeesPerInstance, \
</span><span class="cx">     MaxInstances, NoUIDConflict
</span><span class="cx"> from twistedcaldav.carddavxml import carddav_namespace, NoUIDConflict as NovCardUIDConflict
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
</span><span class="cx"> from twistedcaldav.ical import Component as VCalendar, Property as VProperty, \
</span><del>-    InvalidICalendarDataError, iCalendarProductID, allowedComponents, Component
</del><ins>+    InvalidICalendarDataError, iCalendarProductID, Component
</ins><span class="cx"> from twistedcaldav.memcachelock import MemcacheLockTimeoutError
</span><span class="cx"> from twistedcaldav.notifications import NotificationCollectionResource, NotificationResource
</span><span class="cx"> from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource, \
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx"> from twistedcaldav.customxml import calendarserver_namespace
</span><span class="cx"> from twistedcaldav.instance import InvalidOverriddenInstanceError, \
</span><span class="cx">     TooManyInstancesError
</span><ins>+from twistedcaldav.util import bestAcceptType
</ins><span class="cx"> import collections
</span><span class="cx"> 
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="lines">@@ -626,14 +627,17 @@
</span><span class="cx">         # Read in all data
</span><span class="cx">         data = (yield allDataFromStream(request.stream))
</span><span class="cx"> 
</span><del>-        components = self.componentsFromData(data)
</del><ins>+        format = request.headers.getHeader(&quot;content-type&quot;)
+        if format:
+            format = &quot;%s/%s&quot; % (format.mediaType, format.mediaSubtype,)
+        components = self.componentsFromData(data, format)
</ins><span class="cx">         if components is None:
</span><span class="cx">             raise HTTPError(StatusResponse(BAD_REQUEST, &quot;Could not parse valid data from request body&quot;))
</span><span class="cx"> 
</span><span class="cx">         # Build response
</span><span class="cx">         xmlresponses = [None] * len(components)
</span><span class="cx">         indexedComponents = [idxComponent for idxComponent in enumerate(components)]
</span><del>-        yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
</del><ins>+        yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses, format)
</ins><span class="cx"> 
</span><span class="cx">         result = MultiStatusResponse(xmlresponses)
</span><span class="cx"> 
</span><span class="lines">@@ -650,7 +654,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
</del><ins>+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses, format):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Do create from simpleBatchPOST or crudCreate()
</span><span class="cx">         Subclasses may override
</span><span class="lines">@@ -664,7 +668,7 @@
</span><span class="cx">                 # Get a resource for the new item
</span><span class="cx">                 newchildURL = joinURL(request.path, name)
</span><span class="cx">                 newchild = (yield request.locateResource(newchildURL))
</span><del>-                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
</del><ins>+                changedComponent = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
</ins><span class="cx"> 
</span><span class="cx">             except HTTPError, e:
</span><span class="cx">                 # Extract the pre-condition
</span><span class="lines">@@ -674,30 +678,30 @@
</span><span class="cx">                     error = (error.namespace, error.name,)
</span><span class="cx"> 
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx">             except Exception:
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, BAD_REQUEST, None, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx">             else:
</span><span class="cx">                 if not return_changed:
</span><del>-                    changedData = None
</del><ins>+                    changedComponent = None
</ins><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def bulkCreateResponse(self, component, newchildURL, newchild, changedData, code, error):
</del><ins>+    def bulkCreateResponse(self, component, newchildURL, newchild, changedComponent, code, error, format):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         generate one xmlresponse for bulk create
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         if code is None:
</span><span class="cx">             etag = (yield newchild.etag())
</span><del>-            if changedData is None:
</del><ins>+            if changedComponent is None:
</ins><span class="cx">                 returnValue(
</span><span class="cx">                     davxml.PropertyStatusResponse(
</span><span class="cx">                         davxml.HRef.fromString(newchildURL),
</span><span class="lines">@@ -717,7 +721,7 @@
</span><span class="cx">                         davxml.PropertyStatus(
</span><span class="cx">                             davxml.PropertyContainer(
</span><span class="cx">                                 davxml.GETETag.fromString(etag.generate()),
</span><del>-                                self.xmlDataElementType().fromTextData(changedData),
</del><ins>+                                self.xmlDataElementType().fromComponent(changedComponent, format),
</ins><span class="cx">                             ),
</span><span class="cx">                             davxml.Status.fromResponseCode(OK),
</span><span class="cx">                         )
</span><span class="lines">@@ -822,6 +826,7 @@
</span><span class="cx">             for index, xmldata in crudCreateInfo:
</span><span class="cx"> 
</span><span class="cx">                 component = xmldata.generateComponent()
</span><ins>+                format = xmldata.content_type
</ins><span class="cx"> 
</span><span class="cx">                 if hasPrivilege is not True:
</span><span class="cx">                     e = hasPrivilege # use same code pattern as exception
</span><span class="lines">@@ -830,13 +835,13 @@
</span><span class="cx">                         error = e.response.error
</span><span class="cx">                         error = (error.namespace, error.name,)
</span><span class="cx"> 
</span><del>-                    xmlresponse = yield self.bulkCreateResponse(component, None, None, None, code, error)
</del><ins>+                    xmlresponse = yield self.bulkCreateResponse(component, None, None, None, code, error, format)
</ins><span class="cx">                     xmlresponses[index] = xmlresponse
</span><span class="cx"> 
</span><span class="cx">                 else:
</span><span class="cx">                     indexedComponents.append((index, component,))
</span><span class="cx"> 
</span><del>-            yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
</del><ins>+            yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses, format)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -847,8 +852,8 @@
</span><span class="cx">             code = None
</span><span class="cx">             error = None
</span><span class="cx">             try:
</span><del>-                componentdata = xmldata.textData()
</del><span class="cx">                 component = xmldata.generateComponent()
</span><ins>+                format = xmldata.content_type
</ins><span class="cx"> 
</span><span class="cx">                 updateResource = (yield request.locateResource(href))
</span><span class="cx">                 if not updateResource.exists():
</span><span class="lines">@@ -862,7 +867,7 @@
</span><span class="cx">                 if ifmatch and ifmatch != etag.generate():
</span><span class="cx">                     raise HTTPError(PRECONDITION_FAILED)
</span><span class="cx"> 
</span><del>-                changedData = yield self.storeResourceData(updateResource, component, componentdata)
</del><ins>+                changedComponent = yield self.storeResourceData(updateResource, component, returnChangedData=return_changed)
</ins><span class="cx"> 
</span><span class="cx">             except HTTPError, e:
</span><span class="cx">                 # Extract the pre-condition
</span><span class="lines">@@ -875,7 +880,7 @@
</span><span class="cx">                 code = BAD_REQUEST
</span><span class="cx"> 
</span><span class="cx">             if code is None:
</span><del>-                if not return_changed or changedData is None:
</del><ins>+                if changedComponent is None:
</ins><span class="cx">                     xmlresponses[index] = davxml.PropertyStatusResponse(
</span><span class="cx">                         davxml.HRef.fromString(href),
</span><span class="cx">                         davxml.PropertyStatus(
</span><span class="lines">@@ -891,7 +896,7 @@
</span><span class="cx">                         davxml.PropertyStatus(
</span><span class="cx">                             davxml.PropertyContainer(
</span><span class="cx">                                 davxml.GETETag.fromString(etag.generate()),
</span><del>-                                self.xmlDataElementType().fromTextData(changedData),
</del><ins>+                                self.xmlDataElementType().fromComponentData(changedComponent, format),
</ins><span class="cx">                             ),
</span><span class="cx">                             davxml.Status.fromResponseCode(OK),
</span><span class="cx">                         )
</span><span class="lines">@@ -989,7 +994,7 @@
</span><span class="cx">         if comps:
</span><span class="cx">             comps = comps.split(&quot;,&quot;)
</span><span class="cx">         else:
</span><del>-            comps = allowedComponents
</del><ins>+            comps = ical.allowedStoreComponents
</ins><span class="cx">         return caldavxml.SupportedCalendarComponentSet(
</span><span class="cx">             *[caldavxml.CalendarComponent(name=item) for item in comps]
</span><span class="cx">         )
</span><span class="lines">@@ -1016,7 +1021,7 @@
</span><span class="cx">         if comps:
</span><span class="cx">             comps = comps.split(&quot;,&quot;)
</span><span class="cx">         else:
</span><del>-            comps = allowedComponents
</del><ins>+            comps = ical.allowedStoreComponents
</ins><span class="cx">         return comps
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1053,6 +1058,8 @@
</span><span class="cx"> 
</span><span class="cx">         if config.EnableBatchUpload:
</span><span class="cx">             self._postHandlers[(&quot;text&quot;, &quot;calendar&quot;)] = _CommonHomeChildCollectionMixin.simpleBatchPOST
</span><ins>+            if config.EnableJSONData:
+                self._postHandlers[(&quot;application&quot;, &quot;calendar+json&quot;)] = _CommonHomeChildCollectionMixin.simpleBatchPOST
</ins><span class="cx">             self.xmlDocHandlers[customxml.Multiput] = _CommonHomeChildCollectionMixin.crudBatchPOST
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1088,6 +1095,11 @@
</span><span class="cx">     def iCalendarRolledup(self, request):
</span><span class="cx">         # FIXME: uncached: implement cache in the storage layer
</span><span class="cx"> 
</span><ins>+        # Accept header handling
+        accepted_type = bestAcceptType(request.headers.getHeader(&quot;accept&quot;), Component.allowedTypes())
+        if accepted_type is None:
+            raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, &quot;Cannot generate requested data type&quot;))
+
</ins><span class="cx">         # Generate a monolithic calendar
</span><span class="cx">         calendar = VCalendar(&quot;VCALENDAR&quot;)
</span><span class="cx">         calendar.addProperty(VProperty(&quot;VERSION&quot;, &quot;2.0&quot;))
</span><span class="lines">@@ -1138,17 +1150,13 @@
</span><span class="cx"> 
</span><span class="cx">                     calendar.addComponent(component)
</span><span class="cx"> 
</span><del>-        # Cache the data
-        data = str(calendar)
-        data = (yield self.getInternalSyncToken()) + &quot;\r\n&quot; + data
</del><ins>+        returnValue((calendar, accepted_type,))
</ins><span class="cx"> 
</span><del>-        returnValue(calendar)
-
</del><span class="cx">     createCalendarCollection = _CommonHomeChildCollectionMixin.createCollection
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def componentsFromData(cls, data):
</del><ins>+    def componentsFromData(cls, data, format):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Need to split a single VCALENDAR into separate ones based on UID with the
</span><span class="cx">         appropriate VTIEMZONES included.
</span><span class="lines">@@ -1158,7 +1166,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Split into components by UID and TZID
</span><span class="cx">         try:
</span><del>-            vcal = VCalendar.fromString(data)
</del><ins>+            vcal = VCalendar.fromString(data, format)
</ins><span class="cx">         except InvalidICalendarDataError:
</span><span class="cx">             return None
</span><span class="cx"> 
</span><span class="lines">@@ -1242,7 +1250,8 @@
</span><span class="cx"> 
</span><span class="cx">         elif qname == caldavxml.CalendarTimeZone.qname():
</span><span class="cx">             timezone = self._newStoreObject.getTimezone()
</span><del>-            returnValue(caldavxml.CalendarTimeZone.fromString(str(timezone)) if timezone else None)
</del><ins>+            format = property.content_type if isinstance(property, caldavxml.CalendarTimeZone) else None
+            returnValue(caldavxml.CalendarTimeZone.fromCalendar(timezone, format=format) if timezone else None)
</ins><span class="cx"> 
</span><span class="cx">         result = (yield super(CalendarCollectionResource, self).readProperty(property, request))
</span><span class="cx">         returnValue(result)
</span><span class="lines">@@ -1288,7 +1297,7 @@
</span><span class="cx">         yield newchild.storeComponent(component)
</span><span class="cx">         if returnChangedData and newchild._newStoreObject._componentChanged:
</span><span class="cx">             result = (yield newchild.componentForUser())
</span><del>-            returnValue(str(result))
</del><ins>+            returnValue(result)
</ins><span class="cx">         else:
</span><span class="cx">             returnValue(None)
</span><span class="cx"> 
</span><span class="lines">@@ -2210,16 +2219,38 @@
</span><span class="cx">         return self._newStoreObject.component()
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def allowedTypes(self):
+        &quot;&quot;&quot;
+        Return a dict of allowed MIME types for storing, mapped to equivalent PyCalendar types.
+        &quot;&quot;&quot;
+        raise NotImplementedError
+
+
+    def determineType(self, content_type):
+        &quot;&quot;&quot;
+        Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+        &quot;&quot;&quot;
+        format = None
+        if content_type is not None:
+            format = &quot;%s/%s&quot; % (content_type.mediaType, content_type.mediaSubtype,)
+        return format if format in self.allowedTypes() else None
+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def render(self, request):
</span><span class="cx">         if not self.exists():
</span><span class="cx">             log.debug(&quot;Resource not found: %s&quot; % (self,))
</span><span class="cx">             raise HTTPError(NOT_FOUND)
</span><span class="cx"> 
</span><ins>+        # Accept header handling
+        accepted_type = bestAcceptType(request.headers.getHeader(&quot;accept&quot;), self.allowedTypes())
+        if accepted_type is None:
+            raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, &quot;Cannot generate requested data type&quot;))
+
</ins><span class="cx">         output = yield self.component()
</span><span class="cx"> 
</span><del>-        response = Response(OK, {}, str(output))
-        response.headers.setHeader(&quot;content-type&quot;, self.contentType())
</del><ins>+        response = Response(OK, {}, output.getText(accepted_type))
+        response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;%s; charset=utf-8&quot; % (accepted_type,)))
</ins><span class="cx">         returnValue(response)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2379,10 +2410,10 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def storeStream(self, stream):
</del><ins>+    def storeStream(self, stream, format):
</ins><span class="cx"> 
</span><span class="cx">         # FIXME: direct tests
</span><del>-        component = self._componentFromStream((yield allDataFromStream(stream)))
</del><ins>+        component = self._componentFromStream((yield allDataFromStream(stream)), format)
</ins><span class="cx">         result = (yield self.storeComponent(component))
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><span class="lines">@@ -2514,6 +2545,13 @@
</span><span class="cx"> 
</span><span class="cx">     _componentFromStream = VCalendar.fromString
</span><span class="cx"> 
</span><ins>+    def allowedTypes(self):
+        &quot;&quot;&quot;
+        Return a tuple of allowed MIME types for storing.
+        &quot;&quot;&quot;
+        return Component.allowedTypes()
+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def inNewTransaction(self, request, label=&quot;&quot;):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2541,12 +2579,6 @@
</span><span class="cx">         self._initializeWithObject(newObject, newParent)
</span><span class="cx">         returnValue(txn)
</span><span class="cx"> 
</span><del>-
-    @inlineCallbacks
-    def iCalendarText(self):
-        data = yield self.iCalendar()
-        returnValue(str(data))
-
</del><span class="cx">     iCalendar = _CommonObjectResource.component
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2710,7 +2742,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Content-type check
</span><span class="cx">         content_type = request.headers.getHeader(&quot;content-type&quot;)
</span><del>-        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != (&quot;text&quot;, &quot;calendar&quot;):
</del><ins>+        format = self.determineType(content_type)
+        if format is None:
</ins><span class="cx">             log.error(&quot;MIME type %s not allowed in calendar collection&quot; % (content_type,))
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.FORBIDDEN,
</span><span class="lines">@@ -2745,13 +2778,13 @@
</span><span class="cx">                 ))
</span><span class="cx"> 
</span><span class="cx">             try:
</span><del>-                component = Component.fromString(calendardata)
</del><ins>+                component = Component.fromString(calendardata, format)
</ins><span class="cx">             except ValueError, e:
</span><span class="cx">                 log.error(str(e))
</span><span class="cx">                 raise HTTPError(ErrorResponse(
</span><span class="cx">                     responsecode.FORBIDDEN,
</span><span class="cx">                     (caldav_namespace, &quot;valid-calendar-data&quot;),
</span><del>-                    &quot;Can't parse calendar data&quot;
</del><ins>+                    &quot;Can't parse calendar data: %s&quot; % (str(e),)
</ins><span class="cx">                 ))
</span><span class="cx"> 
</span><span class="cx">             # storeComponent needs to know who the auth'd user is for access control
</span><span class="lines">@@ -2864,7 +2897,7 @@
</span><span class="cx">             if rids is not None:
</span><span class="cx">                 rids = rids[0].split(&quot;,&quot;)
</span><span class="cx">                 try:
</span><del>-                    rids = [PyCalendarDateTime.parseText(rid) if rid != &quot;M&quot; else None for rid in rids]
</del><ins>+                    rids = [DateTime.parseText(rid) if rid != &quot;M&quot; else None for rid in rids]
</ins><span class="cx">                 except ValueError:
</span><span class="cx">                     raise HTTPError(ErrorResponse(
</span><span class="cx">                         FORBIDDEN,
</span><span class="lines">@@ -3001,6 +3034,8 @@
</span><span class="cx"> 
</span><span class="cx">         if config.EnableBatchUpload:
</span><span class="cx">             self._postHandlers[(&quot;text&quot;, &quot;vcard&quot;)] = AddressBookCollectionResource.simpleBatchPOST
</span><ins>+            if config.EnableJSONData:
+                self._postHandlers[(&quot;application&quot;, &quot;vcard+json&quot;)] = _CommonHomeChildCollectionMixin.simpleBatchPOST
</ins><span class="cx">             self.xmlDocHandlers[customxml.Multiput] = AddressBookCollectionResource.crudBatchPOST
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -3032,9 +3067,9 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><del>-    def componentsFromData(cls, data):
</del><ins>+    def componentsFromData(cls, data, format):
</ins><span class="cx">         try:
</span><del>-            return VCard.allFromString(data)
</del><ins>+            return VCard.allFromString(data, format)
</ins><span class="cx">         except InvalidVCardDataError:
</span><span class="cx">             return None
</span><span class="cx"> 
</span><span class="lines">@@ -3055,7 +3090,7 @@
</span><span class="cx">         yield newchild.storeComponent(component)
</span><span class="cx">         if returnChangedData and newchild._newStoreObject._componentChanged:
</span><span class="cx">             result = (yield newchild.component())
</span><del>-            returnValue(str(result))
</del><ins>+            returnValue(result)
</ins><span class="cx">         else:
</span><span class="cx">             returnValue(None)
</span><span class="cx"> 
</span><span class="lines">@@ -3096,7 +3131,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
</del><ins>+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses, format):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         bulk create allowing groups to contain member UIDs added during the same bulk create
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -3111,7 +3146,7 @@
</span><span class="cx">                 # Get a resource for the new item
</span><span class="cx">                 newchildURL = joinURL(request.path, name)
</span><span class="cx">                 newchild = (yield request.locateResource(newchildURL))
</span><del>-                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
</del><ins>+                changedComponent = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
</ins><span class="cx"> 
</span><span class="cx">             except GroupWithUnsharedAddressNotAllowedError, e:
</span><span class="cx">                 # save off info and try again below
</span><span class="lines">@@ -3126,20 +3161,20 @@
</span><span class="cx">                     error = (error.namespace, error.name,)
</span><span class="cx"> 
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx">             except Exception:
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, BAD_REQUEST, None, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx">             else:
</span><span class="cx">                 if not return_changed:
</span><del>-                    changedData = None
</del><ins>+                    changedComponent = None
</ins><span class="cx">                 coaddedUIDs |= set([component.resourceUID()])
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx">         if groupRetries:
</span><span class="lines">@@ -3157,7 +3192,7 @@
</span><span class="cx">                 # give FORBIDDEN response
</span><span class="cx">                 index, component, newchildURL, newchild, missingUIDs = groupRetry
</span><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData=None, code=FORBIDDEN, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, FORBIDDEN, None, format)
</ins><span class="cx">                 )
</span><span class="cx">                 coaddedUIDs -= set([component.resourceUID()]) # group uid not added
</span><span class="cx">                 groupRetries.remove(groupRetry) # remove this retry
</span><span class="lines">@@ -3167,11 +3202,11 @@
</span><span class="cx">                 newchild._metadata[&quot;coaddedUIDs&quot;] = coaddedUIDs
</span><span class="cx"> 
</span><span class="cx">                 # don't catch errors, abort the whole transaction
</span><del>-                changedData = yield self.storeResourceData(newchild, component, returnChangedData=return_changed)
</del><ins>+                changedComponent = yield self.storeResourceData(newchild, component, returnChangedData=return_changed)
</ins><span class="cx">                 if not return_changed:
</span><del>-                    changedData = None
</del><ins>+                    changedComponent = None
</ins><span class="cx">                 xmlresponses[index] = (
</span><del>-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
</del><ins>+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
</ins><span class="cx">                 )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -3266,6 +3301,13 @@
</span><span class="cx"> 
</span><span class="cx">     _componentFromStream = VCard.fromString
</span><span class="cx"> 
</span><ins>+    def allowedTypes(self):
+        &quot;&quot;&quot;
+        Return a tuple of allowed MIME types for storing.
+        &quot;&quot;&quot;
+        return VCard.allowedTypes()
+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def vCardText(self):
</span><span class="cx">         data = yield self.vCard()
</span><span class="lines">@@ -3340,7 +3382,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Content-type check
</span><span class="cx">         content_type = request.headers.getHeader(&quot;content-type&quot;)
</span><del>-        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != (&quot;text&quot;, &quot;vcard&quot;):
</del><ins>+        format = self.determineType(content_type)
+        if format is None:
</ins><span class="cx">             log.error(&quot;MIME type %s not allowed in vcard collection&quot; % (content_type,))
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.FORBIDDEN,
</span><span class="lines">@@ -3365,7 +3408,7 @@
</span><span class="cx">                 ))
</span><span class="cx"> 
</span><span class="cx">             try:
</span><del>-                component = VCard.fromString(vcarddata)
</del><ins>+                component = VCard.fromString(vcarddata, format)
</ins><span class="cx">             except ValueError, e:
</span><span class="cx">                 log.error(str(e))
</span><span class="cx">                 raise HTTPError(ErrorResponse(
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_addressbookmultigetpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -19,17 +19,19 @@
</span><span class="cx"> from twext.web2 import responsecode
</span><span class="cx"> from twext.web2.iweb import IResponse
</span><span class="cx"> from twext.web2.stream import MemoryStream
</span><del>-from txdav.xml import element as davxml
</del><span class="cx"> from twext.web2.dav.util import davXMLFromStream, joinURL
</span><ins>+from twext.web2.http_headers import Headers, MimeType
</ins><span class="cx"> 
</span><span class="cx"> from twistedcaldav import carddavxml
</span><span class="cx"> from twistedcaldav import vcard
</span><del>-
</del><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
</span><ins>+
</ins><span class="cx"> from twisted.python.filepath import FilePath
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx"> 
</span><ins>+from txdav.xml import element as davxml
+
</ins><span class="cx"> class AddressBookMultiget (StoreTestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     addressbook-multiget REPORT
</span><span class="lines">@@ -214,7 +216,13 @@
</span><span class="cx">             '''
</span><span class="cx">             if data:
</span><span class="cx">                 for filename, icaldata in data.iteritems():
</span><del>-                    request = SimpleStoreRequest(self, &quot;PUT&quot;, joinURL(addressbook_uri, filename + &quot;.vcf&quot;), authid=&quot;wsanchez&quot;)
</del><ins>+                    request = SimpleStoreRequest(
+                        self,
+                        &quot;PUT&quot;,
+                        joinURL(addressbook_uri, filename + &quot;.vcf&quot;),
+                        headers=Headers({&quot;content-type&quot;: MimeType.fromString(&quot;text/vcard&quot;)}),
+                        authid=&quot;wsanchez&quot;
+                    )
</ins><span class="cx">                     request.stream = MemoryStream(icaldata)
</span><span class="cx">                     yield self.send(request)
</span><span class="cx">             else:
</span><span class="lines">@@ -222,7 +230,13 @@
</span><span class="cx">                 for child in FilePath(self.vcards_dir).children():
</span><span class="cx">                     if os.path.splitext(child.basename())[1] != &quot;.vcf&quot;:
</span><span class="cx">                         continue
</span><del>-                    request = SimpleStoreRequest(self, &quot;PUT&quot;, joinURL(addressbook_uri, child.basename()), authid=&quot;wsanchez&quot;)
</del><ins>+                    request = SimpleStoreRequest(
+                        self,
+                        &quot;PUT&quot;,
+                        joinURL(addressbook_uri, child.basename()),
+                        headers=Headers({&quot;content-type&quot;: MimeType.fromString(&quot;text/vcard&quot;)}),
+                        authid=&quot;wsanchez&quot;
+                    )
</ins><span class="cx">                     request.stream = MemoryStream(child.getContent())
</span><span class="cx">                     yield self.send(request)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_caldavxmlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,9 +14,16 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><ins>+import twistedcaldav.test.util
</ins><span class="cx"> from twistedcaldav import caldavxml
</span><del>-import twistedcaldav.test.util
</del><ins>+from twistedcaldav.caldavxml import CalendarData
+from twistedcaldav.ical import normalize_iCalStr, Component
</ins><span class="cx"> 
</span><ins>+def normalizeJSON(j):
+    return &quot;&quot;.join(map(str.strip, j.splitlines())).replace(&quot;, &quot;, &quot;,&quot;).replace(&quot;: &quot;, &quot;:&quot;)
+
+
+
</ins><span class="cx"> class CustomXML (twistedcaldav.test.util.TestCase):
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -50,3 +57,99 @@
</span><span class="cx"> 
</span><span class="cx">         tr = caldavxml.CalDAVTimeRangeElement(start=&quot;20110201T120000Z&quot;, end=&quot;20110202&quot;)
</span><span class="cx">         self.assertFalse(tr.valid())
</span><ins>+
+
+    def test_CalendarDataTextAndJSON(self):
+        &quot;&quot;&quot;
+        Text that we can both parse and generate CalendarData elements with both text and json formats.
+        &quot;&quot;&quot;
+        dataText = &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE:mailto:user2@example.com
+DTSTAMP:20080601T120000Z
+EXDATE:20080602T120000Z
+EXDATE:20080603T120000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+RRULE:FREQ=DAILY;COUNT=400
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;)
+
+        dataXML = &quot;&quot;&quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;
+&lt;calendar-data xmlns='urn:ietf:params:xml:ns:caldav'&gt;&lt;![CDATA[%s]]&gt;&lt;/calendar-data&gt;&quot;&quot;&quot; % (dataText,)
+
+        jsonText = &quot;&quot;&quot;[
+  &quot;vcalendar&quot;,
+  [
+    [&quot;version&quot;, {}, &quot;text&quot;, &quot;2.0&quot;],
+    [&quot;prodid&quot;, {}, &quot;text&quot;, &quot;-//CALENDARSERVER.ORG//NONSGML Version 1//EN&quot;]
+  ],
+  [
+    [&quot;vevent&quot;,
+      [
+        [&quot;uid&quot;, {}, &quot;text&quot;, &quot;12345-67890&quot;],
+        [&quot;dtstart&quot;, {}, &quot;date-time&quot;, &quot;2008-06-01T12:00:00Z&quot;],
+        [&quot;dtend&quot;, {}, &quot;date-time&quot;, &quot;2008-06-01T13:00:00Z&quot;],
+        [&quot;attendee&quot;, {}, &quot;cal-address&quot;, &quot;mailto:user1@example.com&quot;],
+        [&quot;attendee&quot;, {}, &quot;cal-address&quot;, &quot;mailto:user2@example.com&quot;],
+        [&quot;dtstamp&quot;, {}, &quot;date-time&quot;, &quot;2008-06-01T12:00:00Z&quot;],
+        [&quot;exdate&quot;, {}, &quot;date-time&quot;, &quot;2008-06-02T12:00:00Z&quot;],
+        [&quot;exdate&quot;, {}, &quot;date-time&quot;, &quot;2008-06-03T12:00:00Z&quot;],
+        [&quot;organizer&quot;, {&quot;cn&quot;: &quot;User 01&quot;}, &quot;cal-address&quot;, &quot;mailto:user1@example.com&quot;],
+        [&quot;rrule&quot;, {}, &quot;recur&quot;, {&quot;count&quot;: 400, &quot;freq&quot;: &quot;DAILY&quot;}],
+        [&quot;summary&quot;, {}, &quot;text&quot;, &quot;Test&quot;]
+      ],
+      [
+      ]
+    ]
+  ]
+]
+&quot;&quot;&quot;
+
+        jsonXML = &quot;&quot;&quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;
+&lt;calendar-data content-type='application/calendar+json' xmlns='urn:ietf:params:xml:ns:caldav'&gt;&lt;![CDATA[%s]]&gt;&lt;/calendar-data&gt;&quot;&quot;&quot; % (jsonText,)
+
+        cd = CalendarData.fromTextData(dataText)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;text/calendar&quot;)
+        self.assertEqual(cd.toxml(), dataXML)
+
+        comp = Component.fromString(dataText)
+        cd = CalendarData.fromCalendar(comp)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;text/calendar&quot;)
+        self.assertEqual(cd.toxml(), dataXML)
+
+        cd = CalendarData.fromCalendar(comp, format=&quot;application/calendar+json&quot;)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;application/calendar+json&quot;)
+        self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML))
+
+        cd = CalendarData.fromTextData(jsonText, format=&quot;application/calendar+json&quot;)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;application/calendar+json&quot;)
+        self.assertEqual(cd.toxml(), jsonXML)
+
+        comp = Component.fromString(jsonText, format=&quot;application/calendar+json&quot;)
+        cd = CalendarData.fromCalendar(comp)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;text/calendar&quot;)
+        self.assertEqual(cd.toxml(), dataXML)
+
+        cd = CalendarData.fromCalendar(comp, format=&quot;application/calendar+json&quot;)
+        self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format=&quot;text/calendar&quot;)), normalize_iCalStr(dataText))
+        self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format=&quot;application/calendar+json&quot;)), normalizeJSON(jsonText))
+        self.assertEqual(cd.content_type, &quot;application/calendar+json&quot;)
+        self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML))
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_calendarquerypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> from txdav.caldav.icalendarstore import ComponentUpdateState
</span><span class="cx"> from twistedcaldav.directory.directory import DirectoryService
</span><span class="lines">@@ -124,8 +124,8 @@
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         query_timerange = caldavxml.TimeRange(
</span><del>-            start=&quot;%04d1001T000000Z&quot; % (PyCalendarDateTime.getToday().getYear(),),
-            end=&quot;%04d1101T000000Z&quot; % (PyCalendarDateTime.getToday().getYear(),),
</del><ins>+            start=&quot;%04d1001T000000Z&quot; % (DateTime.getToday().getYear(),),
+            end=&quot;%04d1101T000000Z&quot; % (DateTime.getToday().getYear(),),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         query = caldavxml.CalendarQuery(
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_dateopspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_dateops.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_dateops.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_dateops.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="cx"> from twisted.trial.unittest import SkipTest
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twistedcaldav.dateops import parseSQLTimestampToPyCalendar, \
</span><span class="cx">     parseSQLDateToPyCalendar, pyCalendarTodatetime, \
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> 
</span><span class="cx"> import datetime
</span><span class="cx"> import dateutil
</span><del>-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.timezone import Timezone
</ins><span class="cx"> from twistedcaldav.timezones import TimezoneCache
</span><span class="cx"> 
</span><span class="cx"> class Dateops(twistedcaldav.test.util.TestCase):
</span><span class="lines">@@ -43,10 +43,10 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         data = (
</span><del>-            (PyCalendarDateTime(2012, 1, 1), PyCalendarDateTime(2012, 1, 1, 0, 0, 0)),
-            (PyCalendarDateTime(2012, 1, 1, 10, 0, 0), PyCalendarDateTime(2012, 1, 1, 10, 0, 0)),
-            (PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)), PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-            (PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(tzid=&quot;America/New_York&quot;)), PyCalendarDateTime(2012, 1, 1, 17, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+            (DateTime(2012, 1, 1), DateTime(2012, 1, 1, 0, 0, 0)),
+            (DateTime(2012, 1, 1, 10, 0, 0), DateTime(2012, 1, 1, 10, 0, 0)),
+            (DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)), DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True))),
+            (DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(tzid=&quot;America/New_York&quot;)), DateTime(2012, 1, 1, 17, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for value, result in data:
</span><span class="lines">@@ -59,10 +59,10 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         data = (
</span><del>-            (PyCalendarDateTime(2012, 1, 1), PyCalendarDateTime(2012, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-            (PyCalendarDateTime(2012, 1, 1, 10, 0, 0), PyCalendarDateTime(2012, 1, 1, 10, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-            (PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)), PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-            (PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(tzid=&quot;America/New_York&quot;)), PyCalendarDateTime(2012, 1, 1, 17, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+            (DateTime(2012, 1, 1), DateTime(2012, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))),
+            (DateTime(2012, 1, 1, 10, 0, 0), DateTime(2012, 1, 1, 10, 0, 0, tzid=Timezone(utc=True))),
+            (DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)), DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True))),
+            (DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(tzid=&quot;America/New_York&quot;)), DateTime(2012, 1, 1, 17, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for value, result in data:
</span><span class="lines">@@ -75,10 +75,10 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         data = (
</span><del>-            (PyCalendarDateTime(2012, 1, 1), PyCalendarDateTime(2012, 1, 1)),
-            (PyCalendarDateTime(2012, 1, 1, 10, 0, 0), PyCalendarDateTime(2012, 1, 1, 10, 0, 0)),
-            (PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)), PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-            (PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(tzid=&quot;America/New_York&quot;)), PyCalendarDateTime(2012, 1, 1, 17, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+            (DateTime(2012, 1, 1), DateTime(2012, 1, 1)),
+            (DateTime(2012, 1, 1, 10, 0, 0), DateTime(2012, 1, 1, 10, 0, 0)),
+            (DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)), DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True))),
+            (DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(tzid=&quot;America/New_York&quot;)), DateTime(2012, 1, 1, 17, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for value, result in data:
</span><span class="lines">@@ -107,132 +107,132 @@
</span><span class="cx">             # Timed
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start within, end within - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start before, end before - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 3, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start before, end right before - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 23, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 23, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 3, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start before, end within - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 3, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start after, end after - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 2, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 2, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 12, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start right after, end after - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 1, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start within, end after - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 12, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 12, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Start before, end after - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 3, 11, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 2, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 3, 11, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 2, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 3, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx"> 
</span><span class="cx">             # All day
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start within, end within - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 9),
-                PyCalendarDateTime(2012, 1, 10),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 9),
+                DateTime(2012, 1, 10),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start before, end before - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1),
-                PyCalendarDateTime(2012, 1, 2),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 1),
+                DateTime(2012, 1, 2),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start before, end right before - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 7),
-                PyCalendarDateTime(2012, 1, 8),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 7),
+                DateTime(2012, 1, 8),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start before, end within - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 7),
-                PyCalendarDateTime(2012, 1, 9),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 7),
+                DateTime(2012, 1, 9),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start after, end after - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 16),
-                PyCalendarDateTime(2012, 1, 17),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 16),
+                DateTime(2012, 1, 17),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start right after, end after - no overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 15),
-                PyCalendarDateTime(2012, 1, 16),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 15),
+                DateTime(2012, 1, 16),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 False,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start within, end after - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 14),
-                PyCalendarDateTime(2012, 1, 16),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 14),
+                DateTime(2012, 1, 16),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;All day: Start before, end after - overlap&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 7),
-                PyCalendarDateTime(2012, 1, 16),
-                PyCalendarDateTime(2012, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                PyCalendarDateTime(2012, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2012, 1, 7),
+                DateTime(2012, 1, 16),
+                DateTime(2012, 1, 8, 0, 0, 0, tzid=Timezone(utc=True)),
+                DateTime(2012, 1, 15, 0, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 True,
</span><span class="cx">             ),
</span><span class="cx">         )
</span><span class="lines">@@ -254,8 +254,8 @@
</span><span class="cx">         dateops.pyCalendarTodatetime
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         tests = (
</span><del>-            (PyCalendarDateTime(2012, 4, 4, 12, 34, 56), datetime.datetime(2012, 4, 4, 12, 34, 56, tzinfo=dateutil.tz.tzutc())),
-            (PyCalendarDateTime(2012, 12, 31), datetime.date(2012, 12, 31)),
</del><ins>+            (DateTime(2012, 4, 4, 12, 34, 56), datetime.datetime(2012, 4, 4, 12, 34, 56, tzinfo=dateutil.tz.tzutc())),
+            (DateTime(2012, 12, 31), datetime.date(2012, 12, 31)),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for pycal, result in tests:
</span><span class="lines">@@ -267,8 +267,8 @@
</span><span class="cx">         dateops.parseSQLTimestampToPyCalendar
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         tests = (
</span><del>-            (&quot;2012-04-04 12:34:56&quot;, PyCalendarDateTime(2012, 4, 4, 12, 34, 56)),
-            (&quot;2012-12-31 01:01:01&quot;, PyCalendarDateTime(2012, 12, 31, 1, 1, 1)),
</del><ins>+            (&quot;2012-04-04 12:34:56&quot;, DateTime(2012, 4, 4, 12, 34, 56)),
+            (&quot;2012-12-31 01:01:01&quot;, DateTime(2012, 12, 31, 1, 1, 1)),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for sqlStr, result in tests:
</span><span class="lines">@@ -281,8 +281,8 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         tests = (
</span><del>-            (&quot;2012-04-04&quot;, PyCalendarDateTime(2012, 4, 4)),
-            (&quot;2012-12-31 00:00:00&quot;, PyCalendarDateTime(2012, 12, 31)),
</del><ins>+            (&quot;2012-04-04&quot;, DateTime(2012, 4, 4)),
+            (&quot;2012-12-31 00:00:00&quot;, DateTime(2012, 12, 31)),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for sqlStr, result in tests:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_icalendarpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_icalendar.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_icalendar.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -25,12 +25,12 @@
</span><span class="cx"> from twistedcaldav.instance import InvalidOverriddenInstanceError
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> from twistedcaldav.ical import iCalendarProductID
</span><del>-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.duration import Duration
</ins><span class="cx"> from twistedcaldav.dateops import normalizeForExpand
</span><del>-from pycalendar.value import PyCalendarValue
</del><ins>+from pycalendar.value import Value
</ins><span class="cx"> 
</span><span class="cx"> class iCalendar (twistedcaldav.test.util.TestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -469,7 +469,7 @@
</span><span class="cx">         calendar.validCalendarData(doFix=False, validateRecurrences=True)
</span><span class="cx"> 
</span><span class="cx">         # Verify expansion works, even for an RDATE prior to master DTSTART:
</span><del>-        calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx"> 
</span><span class="cx">         # Test EXDATEs *prior* to master (as the result of client splitting a
</span><span class="cx">         # a recurring event and copying *all* EXDATEs to new event):
</span><span class="lines">@@ -568,13 +568,13 @@
</span><span class="cx"> 
</span><span class="cx">         year = 2004
</span><span class="cx"> 
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="cx">             end = instance.end
</span><del>-            self.assertEqual(start, PyCalendarDateTime(year, 7, 4))
-            self.assertEqual(end  , PyCalendarDateTime(year, 7, 5))
</del><ins>+            self.assertEqual(start, DateTime(year, 7, 4))
+            self.assertEqual(end  , DateTime(year, 7, 5))
</ins><span class="cx">             if year == 2050:
</span><span class="cx">                 break
</span><span class="cx">             year += 1
</span><span class="lines">@@ -594,14 +594,14 @@
</span><span class="cx">         }
</span><span class="cx">         year = 2004
</span><span class="cx"> 
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="cx">             end = instance.end
</span><span class="cx">             if year in results:
</span><del>-                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
</del><ins>+                self.assertEqual(start, DateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , DateTime(year, results[year][0], results[year][2]))
</ins><span class="cx">             if year == 2050:
</span><span class="cx">                 break
</span><span class="cx">             year += 1
</span><span class="lines">@@ -621,14 +621,14 @@
</span><span class="cx">         }
</span><span class="cx">         year = 2002
</span><span class="cx"> 
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="cx">             end = instance.end
</span><span class="cx">             if year in results:
</span><del>-                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
</del><ins>+                self.assertEqual(start, DateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , DateTime(year, results[year][0], results[year][2]))
</ins><span class="cx">             if year == 2050:
</span><span class="cx">                 break
</span><span class="cx">             year += 1
</span><span class="lines">@@ -642,13 +642,13 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         calendar = Component.fromStream(file(os.path.join(self.data_dir, &quot;Holidays&quot;, &quot;C318ABFE-1ED0-11D9-A5E0-000A958A3252.ics&quot;)))
</span><span class="cx"> 
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="cx">             end = instance.end
</span><del>-            self.assertEqual(start, PyCalendarDateTime(2004, 11, 25))
-            self.assertEqual(end, PyCalendarDateTime(2004, 11, 27))
</del><ins>+            self.assertEqual(start, DateTime(2004, 11, 25))
+            self.assertEqual(end, DateTime(2004, 11, 27))
</ins><span class="cx">             break
</span><span class="cx"> 
</span><span class="cx">     # test_component_timerange.todo = &quot;recurrence expansion should give us no end date here&quot;
</span><span class="lines">@@ -658,44 +658,44 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         parse_date()
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        self.assertEqual(PyCalendarDateTime.parseText(&quot;19970714&quot;), PyCalendarDateTime(1997, 7, 14))
</del><ins>+        self.assertEqual(DateTime.parseText(&quot;19970714&quot;), DateTime(1997, 7, 14))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_parse_datetime(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         parse_datetime()
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        dt = PyCalendarDateTime.parseText(&quot;19980118T230000&quot;)
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
</del><ins>+        dt = DateTime.parseText(&quot;19980118T230000&quot;)
+        self.assertEqual(dt, DateTime(1998, 1, 18, 23, 0, 0))
</ins><span class="cx">         self.assertTrue(dt.floating())
</span><span class="cx"> 
</span><del>-        dt = PyCalendarDateTime.parseText(&quot;19980119T070000Z&quot;)
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        dt = DateTime.parseText(&quot;19980119T070000Z&quot;)
+        self.assertEqual(dt, DateTime(1998, 1, 19, 7, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_parse_date_or_datetime(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         parse_date_or_datetime()
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        self.assertEqual(PyCalendarDateTime.parseText(&quot;19970714&quot;), PyCalendarDateTime(1997, 7, 14))
</del><ins>+        self.assertEqual(DateTime.parseText(&quot;19970714&quot;), DateTime(1997, 7, 14))
</ins><span class="cx"> 
</span><del>-        dt = PyCalendarDateTime.parseText(&quot;19980118T230000&quot;)
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
</del><ins>+        dt = DateTime.parseText(&quot;19980118T230000&quot;)
+        self.assertEqual(dt, DateTime(1998, 1, 18, 23, 0, 0))
</ins><span class="cx">         self.assertTrue(dt.floating())
</span><span class="cx"> 
</span><del>-        dt = PyCalendarDateTime.parseText(&quot;19980119T070000Z&quot;)
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        dt = DateTime.parseText(&quot;19980119T070000Z&quot;)
+        self.assertEqual(dt, DateTime(1998, 1, 19, 7, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_parse_duration(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         parse_duration()
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        self.assertEqual(PyCalendarDuration.parseText(&quot;P15DT5H0M20S&quot;), PyCalendarDuration(days=15, hours=5, minutes=0, seconds=20))
-        self.assertEqual(PyCalendarDuration.parseText(&quot;+P15DT5H0M20S&quot;), PyCalendarDuration(days=15, hours=5, minutes=0, seconds=20))
-        self.assertEqual(PyCalendarDuration.parseText(&quot;-P15DT5H0M20S&quot;), PyCalendarDuration(days=15 * -1, hours=5 * -1, minutes=0, seconds=20 * -1))
</del><ins>+        self.assertEqual(Duration.parseText(&quot;P15DT5H0M20S&quot;), Duration(days=15, hours=5, minutes=0, seconds=20))
+        self.assertEqual(Duration.parseText(&quot;+P15DT5H0M20S&quot;), Duration(days=15, hours=5, minutes=0, seconds=20))
+        self.assertEqual(Duration.parseText(&quot;-P15DT5H0M20S&quot;), Duration(days=15 * -1, hours=5 * -1, minutes=0, seconds=20 * -1))
</ins><span class="cx"> 
</span><del>-        self.assertEqual(PyCalendarDuration.parseText(&quot;P7W&quot;), PyCalendarDuration(weeks=7))
</del><ins>+        self.assertEqual(Duration.parseText(&quot;P7W&quot;), Duration(weeks=7))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_correct_attendee_properties(self):
</span><span class="lines">@@ -807,7 +807,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (&quot;mailto:user1@example.com&quot;, None),
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -833,7 +833,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (&quot;mailto:user1@example.com&quot;, None),
</span><del>-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+                    (&quot;mailto:user3@example.com&quot;, DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -946,8 +946,8 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (&quot;mailto:user2@example.com&quot;, None),
</span><del>-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -1177,7 +1177,7 @@
</span><span class="cx"> 
</span><span class="cx">         component = Component.fromString(data)
</span><span class="cx">         vevent = component.mainComponent()
</span><del>-        vevent.addProperty(Property(&quot;ATTACH&quot;, &quot;foobar&quot;, valuetype=PyCalendarValue.VALUETYPE_BINARY))
</del><ins>+        vevent.addProperty(Property(&quot;ATTACH&quot;, &quot;foobar&quot;, valuetype=Value.VALUETYPE_BINARY))
</ins><span class="cx">         self.assertEqual(str(component), result)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2277,8 +2277,8 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2299,12 +2299,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2326,16 +2326,16 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 2, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2357,12 +2357,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2384,12 +2384,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2417,12 +2417,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 2, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2474,12 +2474,12 @@
</span><span class="cx">                 True,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2488,9 +2488,9 @@
</span><span class="cx">         for description, original, ignoreInvalidInstances, results in data:
</span><span class="cx">             component = Component.fromString(original)
</span><span class="cx">             if results is None:
</span><del>-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</del><ins>+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</ins><span class="cx">             else:
</span><del>-                instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</del><ins>+                instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</ins><span class="cx">                 self.assertTrue(len(instances.instances) == len(results), &quot;%s: wrong number of instances&quot; % (description,))
</span><span class="cx">                 periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
</span><span class="cx">                 self.assertEqual(periods, results)
</span><span class="lines">@@ -2518,8 +2518,8 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2539,8 +2539,8 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
</del><ins>+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2561,12 +2561,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2587,12 +2587,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
</del><ins>+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 17),
</del><ins>+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 17),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2614,16 +2614,16 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 2, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2645,16 +2645,16 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
</del><ins>+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 17),
</del><ins>+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 17),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 18),
-                        PyCalendarDateTime(2007, 11, 19),
</del><ins>+                        DateTime(2007, 11, 18),
+                        DateTime(2007, 11, 19),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2676,12 +2676,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2703,12 +2703,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
</del><ins>+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 17),
-                        PyCalendarDateTime(2007, 11, 18),
</del><ins>+                        DateTime(2007, 11, 17),
+                        DateTime(2007, 11, 18),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2736,12 +2736,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 2, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2769,12 +2769,12 @@
</span><span class="cx">                 False,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
</del><ins>+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 18),
</del><ins>+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 18),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -2831,9 +2831,9 @@
</span><span class="cx">         for description, original, ignoreInvalidInstances, results in data:
</span><span class="cx">             component = Component.fromString(original)
</span><span class="cx">             if results is None:
</span><del>-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</del><ins>+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
</ins><span class="cx">             else:
</span><del>-                instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances, normalizeFunction=normalizeForExpand)
</del><ins>+                instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances, normalizeFunction=normalizeForExpand)
</ins><span class="cx">                 self.assertTrue(len(instances.instances) == len(results), &quot;%s: wrong number of instances&quot; % (description,))
</span><span class="cx">                 periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
</span><span class="cx">                 self.assertEqual(periods, results)
</span><span class="lines">@@ -2861,8 +2861,8 @@
</span><span class="cx">                 None,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -2880,11 +2880,11 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2007, 1, 1),
</del><ins>+                DateTime(2007, 1, 1),
</ins><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -2902,9 +2902,9 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">                 (),
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Simple recurring - no limit&quot;,
</span><span class="lines">@@ -2923,20 +2923,20 @@
</span><span class="cx">                 None,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -2955,23 +2955,23 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2007, 1, 1),
</del><ins>+                DateTime(2007, 1, 1),
</ins><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -2990,14 +2990,14 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Simple recurring - limit effective full&quot;,
</span><span class="lines">@@ -3013,9 +3013,9 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1),
</del><ins>+                DateTime(2012, 1, 1),
</ins><span class="cx">                 (),
</span><del>-                PyCalendarDateTime(2012, 1, 1),
</del><ins>+                DateTime(2012, 1, 1),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Complex recurring - no limit&quot;,
</span><span class="lines">@@ -3048,20 +3048,20 @@
</span><span class="cx">                 None,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2008, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2008, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -3094,23 +3094,23 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2007, 1, 1),
</del><ins>+                DateTime(2007, 1, 1),
</ins><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2008, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2008, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><span class="cx">                 None,
</span><span class="lines">@@ -3143,14 +3143,14 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 ),
</span><del>-                PyCalendarDateTime(2010, 1, 1),
</del><ins>+                DateTime(2010, 1, 1),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;Complex recurring - limit effective full&quot;,
</span><span class="lines">@@ -3180,15 +3180,15 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2012, 1, 1),
</del><ins>+                DateTime(2012, 1, 1),
</ins><span class="cx">                 (),
</span><del>-                PyCalendarDateTime(2012, 1, 1),
</del><ins>+                DateTime(2012, 1, 1),
</ins><span class="cx">             ),
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         for description, original, lowerLimit, results, limited in data:
</span><span class="cx">             component = Component.fromString(original)
</span><del>-            instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), lowerLimit=lowerLimit)
</del><ins>+            instances = component.expandTimeRanges(DateTime(2100, 1, 1), lowerLimit=lowerLimit)
</ins><span class="cx">             self.assertTrue(len(instances.instances) == len(results), &quot;%s: wrong number of instances&quot; % (description,))
</span><span class="cx">             periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
</span><span class="cx">             self.assertEqual(periods, results)
</span><span class="lines">@@ -4040,7 +4040,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID:20090102T080000Z
</span><span class="lines">@@ -4065,7 +4065,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 18, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID:20090102T180000Z
</span><span class="lines">@@ -4091,7 +4091,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 3, 18, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID:20090103T180000Z
</span><span class="lines">@@ -4115,7 +4115,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 9, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4133,7 +4133,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 19, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4152,7 +4152,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 3, 19, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4169,7 +4169,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 8),
</del><ins>+                DateTime(2009, 1, 8),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID;VALUE=DATE:20090108
</span><span class="lines">@@ -4194,7 +4194,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 3),
</del><ins>+                DateTime(2009, 1, 3),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID;VALUE=DATE:20090103
</span><span class="lines">@@ -4220,7 +4220,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 10),
</del><ins>+                DateTime(2009, 1, 10),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID;VALUE=DATE:20090110
</span><span class="lines">@@ -4244,7 +4244,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 3),
</del><ins>+                DateTime(2009, 1, 3),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4262,7 +4262,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 5),
</del><ins>+                DateTime(2009, 1, 5),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4281,7 +4281,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 19),
</del><ins>+                DateTime(2009, 1, 19),
</ins><span class="cx">                 None,
</span><span class="cx">             ),
</span><span class="cx">         )
</span><span class="lines">@@ -4311,8 +4311,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 4, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="lines">@@ -4349,8 +4349,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 2, 18, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 4, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="lines">@@ -4388,8 +4388,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 5, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 3, 18, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 5, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="lines">@@ -4425,8 +4425,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 2, 9, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     None,
</span><span class="lines">@@ -4456,8 +4456,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 2, 19, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     None,
</span><span class="lines">@@ -4488,8 +4488,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                    DateTime(2009, 1, 3, 19, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 ),
</span><span class="cx">                 (
</span><span class="cx">                     None,
</span><span class="lines">@@ -4534,7 +4534,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID:20090102T080000Z
</span><span class="lines">@@ -4561,7 +4561,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890-1
</span><span class="cx"> RECURRENCE-ID:20090102T080000Z
</span><span class="lines">@@ -4604,19 +4604,19 @@
</span><span class="cx">         self.assertFalse(hasattr(ical, &quot;cachedInstances&quot;))
</span><span class="cx"> 
</span><span class="cx">         # Derive one day apart - no re-cache
</span><del>-        ical.deriveInstance(PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        ical.deriveInstance(DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">         self.assertTrue(hasattr(ical, &quot;cachedInstances&quot;))
</span><span class="cx">         oldLimit = ical.cachedInstances.limit
</span><del>-        ical.deriveInstance(PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        ical.deriveInstance(DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">         self.assertEqual(ical.cachedInstances.limit, oldLimit)
</span><span class="cx"> 
</span><span class="cx">         # Derive several years ahead - re-cached
</span><del>-        ical.deriveInstance(PyCalendarDateTime(2011, 1, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        ical.deriveInstance(DateTime(2011, 1, 1, 8, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">         self.assertNotEqual(ical.cachedInstances.limit, oldLimit)
</span><span class="cx">         oldLimit = ical.cachedInstances.limit
</span><span class="cx"> 
</span><span class="cx">         # Check one day ahead again - no re-cache
</span><del>-        ical.deriveInstance(PyCalendarDateTime(2011, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+        ical.deriveInstance(DateTime(2011, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)))
</ins><span class="cx">         self.assertEqual(ical.cachedInstances.limit, oldLimit)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -4661,13 +4661,13 @@
</span><span class="cx">         masterDerived = ical.masterDerived()
</span><span class="cx"> 
</span><span class="cx">         # Derive one day apart - no re-cache
</span><del>-        result = ical.deriveInstance(PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
</del><ins>+        result = ical.deriveInstance(DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
</ins><span class="cx">         self.assertEqual(str(result), derived1)
</span><span class="cx"> 
</span><del>-        result = ical.deriveInstance(PyCalendarDateTime(2009, 2, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
</del><ins>+        result = ical.deriveInstance(DateTime(2009, 2, 3, 8, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
</ins><span class="cx">         self.assertEqual(str(result), derived2)
</span><span class="cx"> 
</span><del>-        result = ical.deriveInstance(PyCalendarDateTime(2009, 3, 3, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
</del><ins>+        result = ical.deriveInstance(DateTime(2009, 3, 3, 9, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
</ins><span class="cx">         self.assertEqual(result, None)
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(str(ical), event)
</span><span class="lines">@@ -4847,8 +4847,8 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4866,9 +4866,9 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 5, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 5, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4886,10 +4886,10 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 1, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4908,11 +4908,11 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 1, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 2, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4932,12 +4932,12 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
-                    (PyCalendarDateTime(2009, 10, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 1, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 2, 0, 0, tzid=Timezone(utc=True)), False),
+                    (DateTime(2009, 10, 3, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4960,11 +4960,11 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)), False),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 1, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -4989,12 +4989,12 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, True),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2007, 11, 15, 2, 0, 0, tzid=Timezone(utc=True)), False),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 1, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -5012,9 +5012,9 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (None, False),
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), False),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -5046,7 +5046,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
</del><ins>+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -5062,7 +5062,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -5084,7 +5084,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
</del><ins>+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), False),
</ins><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="cx">         )
</span><span class="lines">@@ -5396,12 +5396,12 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 14, 20, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 21, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 14, 20, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 21, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                     (
</span><del>-                        PyCalendarDateTime(2007, 11, 15, 21, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 22, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                        DateTime(2007, 11, 15, 21, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 22, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                     ),
</span><span class="cx">                 )
</span><span class="cx">             ),
</span><span class="lines">@@ -5409,7 +5409,7 @@
</span><span class="cx"> 
</span><span class="cx">         for description, original, fixed, results in data:
</span><span class="cx">             component = Component.fromString(original)
</span><del>-            instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=False)
</del><ins>+            instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=False)
</ins><span class="cx">             self.assertTrue(len(instances.instances) == len(results), &quot;%s: wrong number of instances&quot; % (description,))
</span><span class="cx">             periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
</span><span class="cx">             self.assertEqual(periods, results)
</span><span class="lines">@@ -5696,7 +5696,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                 ),
</span><span class="lines">@@ -5741,7 +5741,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, False,),
</span><span class="lines">@@ -5795,7 +5795,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, False,),
</span><span class="lines">@@ -5841,19 +5841,19 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, True,),
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, True,),
</span><span class="cx">                                 ),
</span><span class="lines">@@ -5916,21 +5916,21 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, True,),
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, True,),
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, False,),
</span><span class="lines">@@ -6015,7 +6015,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, True,),
</span><span class="lines">@@ -6023,7 +6023,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, True,),
</span><span class="lines">@@ -6031,7 +6031,7 @@
</span><span class="cx">                                 ),
</span><span class="cx">                             ),
</span><span class="cx">                             (
</span><del>-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                                 (
</span><span class="cx">                                     (&quot;&quot;, False,),
</span><span class="cx">                                     (&quot;user01&quot;, False,),
</span><span class="lines">@@ -7415,7 +7415,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">             ),
</span><span class="cx">         )
</span><del>-        cutoff = PyCalendarDateTime(2011, 11, 30, 0, 0, 0)
</del><ins>+        cutoff = DateTime(2011, 11, 30, 0, 0, 0)
</ins><span class="cx">         for _ignore_title, expected, body in data:
</span><span class="cx">             ical = Component.fromString(body)
</span><span class="cx">             self.assertEquals(expected, ical.hasInstancesAfter(cutoff))
</span><span class="lines">@@ -9437,7 +9437,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9505,7 +9505,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9577,7 +9577,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9626,7 +9626,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9676,7 +9676,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 31, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 31, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9725,7 +9725,7 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 1, 31, 6, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 1, 31, 6, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9795,7 +9795,7 @@
</span><span class="cx"> END:X-CALENDARSERVER-PERUSER
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="lines">@@ -9944,7 +9944,7 @@
</span><span class="cx"> END:X-CALENDARSERVER-PERUSER
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><del>-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
</del><ins>+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
</ins><span class="cx">                 &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_localizationpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_localization.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_localization.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_localization.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -20,7 +20,8 @@
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> from twistedcaldav.test.util import TestCase
</span><span class="cx"> from twistedcaldav.config import ConfigDict
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from twistedcaldav.timezones import TimezoneCache
+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="lines">@@ -52,6 +53,11 @@
</span><span class="cx"> 
</span><span class="cx"> class LocalizationTests(TestCase):
</span><span class="cx"> 
</span><ins>+    def setUp(self):
+        super(LocalizationTests, self).setUp()
+        TimezoneCache.create()
+
+
</ins><span class="cx">     def test_BasicStringLocalization(self):
</span><span class="cx"> 
</span><span class="cx">         with translationTo('pig', localeDir=localeDir):
</span><span class="lines">@@ -68,22 +74,22 @@
</span><span class="cx"> 
</span><span class="cx">         with translationTo('en', localeDir=localeDir) as t:
</span><span class="cx"> 
</span><del>-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 0, 0, 0)), &quot;12:00 AM&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 12, 0, 0)), &quot;12:00 PM&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 23, 59, 0)), &quot;11:59 PM&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 6, 5, 0)), &quot;6:05 AM&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 16, 5, 0)), &quot;4:05 PM&quot;)
</del><ins>+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 0, 0, 0)), &quot;12:00 AM&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 12, 0, 0)), &quot;12:00 PM&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 23, 59, 0)), &quot;11:59 PM&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 6, 5, 0)), &quot;6:05 AM&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 16, 5, 0)), &quot;4:05 PM&quot;)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_TimeFormatting24Hour(self):
</span><span class="cx"> 
</span><span class="cx">         with translationTo('pig', localeDir=localeDir) as t:
</span><span class="cx"> 
</span><del>-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 0, 0, 0)), &quot;00:00&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 12, 0, 0)), &quot;12:00&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 23, 59, 0)), &quot;23:59&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 6, 5, 0)), &quot;06:05&quot;)
-            self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 16, 5, 0)), &quot;16:05&quot;)
</del><ins>+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 0, 0, 0)), &quot;00:00&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 12, 0, 0)), &quot;12:00&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 23, 59, 0)), &quot;23:59&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 6, 5, 0)), &quot;06:05&quot;)
+            self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 16, 5, 0)), &quot;16:05&quot;)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_CalendarFormatting(self):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_multigetpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_multiget.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_multiget.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_multiget.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,6 +16,7 @@
</span><span class="cx"> from twext.python.filepath import CachingFilePath as FilePath
</span><span class="cx"> from twext.web2 import responsecode
</span><span class="cx"> from twext.web2.dav.util import davXMLFromStream, joinURL
</span><ins>+from twext.web2.http_headers import Headers, MimeType
</ins><span class="cx"> from twext.web2.iweb import IResponse
</span><span class="cx"> from twext.web2.stream import MemoryStream
</span><span class="cx"> 
</span><span class="lines">@@ -268,7 +269,13 @@
</span><span class="cx"> 
</span><span class="cx">             if data:
</span><span class="cx">                 for filename, icaldata in data.iteritems():
</span><del>-                    request = SimpleStoreRequest(self, &quot;PUT&quot;, joinURL(calendar_uri, filename + &quot;.ics&quot;), authid=&quot;wsanchez&quot;)
</del><ins>+                    request = SimpleStoreRequest(
+                        self,
+                        &quot;PUT&quot;,
+                        joinURL(calendar_uri, filename + &quot;.ics&quot;),
+                        headers=Headers({&quot;content-type&quot;: MimeType.fromString(&quot;text/calendar&quot;)}),
+                        authid=&quot;wsanchez&quot;
+                    )
</ins><span class="cx">                     request.stream = MemoryStream(icaldata)
</span><span class="cx">                     yield self.send(request)
</span><span class="cx">             else:
</span><span class="lines">@@ -276,7 +283,13 @@
</span><span class="cx">                 for child in FilePath(self.holidays_dir).children():
</span><span class="cx">                     if os.path.splitext(child.basename())[1] != &quot;.ics&quot;:
</span><span class="cx">                         continue
</span><del>-                    request = SimpleStoreRequest(self, &quot;PUT&quot;, joinURL(calendar_uri, child.basename()), authid=&quot;wsanchez&quot;)
</del><ins>+                    request = SimpleStoreRequest(
+                        self,
+                        &quot;PUT&quot;,
+                        joinURL(calendar_uri, child.basename()),
+                        headers=Headers({&quot;content-type&quot;: MimeType.fromString(&quot;text/calendar&quot;)}),
+                        authid=&quot;wsanchez&quot;
+                    )
</ins><span class="cx">                     request.stream = MemoryStream(child.getContent())
</span><span class="cx">                     yield self.send(request)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_propspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_props.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_props.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_props.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">                         self.fail(&quot;Expected CalDAV:supported-calendar-data element; but got none.&quot;)
</span><span class="cx"> 
</span><span class="cx">                     for calendar in supported_calendar.children:
</span><del>-                        if calendar.content_type != &quot;text/calendar&quot;:
</del><ins>+                        if calendar.content_type not in (&quot;text/calendar&quot;, &quot;application/calendar+json&quot;):
</ins><span class="cx">                             self.fail(&quot;Expected a text/calendar calendar-data type restriction&quot;)
</span><span class="cx">                         if calendar.version != &quot;2.0&quot;:
</span><span class="cx">                             self.fail(&quot;Expected a version 2.0 calendar-data restriction&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_timezonespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_timezones.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_timezones.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_timezones.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -19,8 +19,8 @@
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> from twistedcaldav.timezones import TimezoneCache, TimezoneException
</span><span class="cx"> from twistedcaldav.timezones import readTZ, listTZs
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> import os
</span><span class="cx"> import threading
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">         if calendar.name() != &quot;VCALENDAR&quot;:
</span><span class="cx">             self.fail(&quot;Calendar is not a VCALENDAR&quot;)
</span><span class="cx"> 
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="lines">@@ -69,8 +69,8 @@
</span><span class="cx"> 
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedApr01.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True))
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -84,8 +84,8 @@
</span><span class="cx"> 
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedDec10.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True))
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -99,13 +99,13 @@
</span><span class="cx"> 
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedApr01.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True)),
</ins><span class="cx">         )
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedDec10.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True)),
</ins><span class="cx">             testEqual=False
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="lines">@@ -119,13 +119,13 @@
</span><span class="cx"> 
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedApr01.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True)),
</ins><span class="cx">         )
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedDec10.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True)),
</del><ins>+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True)),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -139,13 +139,13 @@
</span><span class="cx"> 
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedDec10.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True))
</ins><span class="cx">         )
</span><span class="cx">         self.doTest(
</span><span class="cx">             &quot;TruncatedApr01.ics&quot;,
</span><del>-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True))
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -201,13 +201,13 @@
</span><span class="cx">         calendar = Component.fromString(data)
</span><span class="cx">         if calendar.name() != &quot;VCALENDAR&quot;:
</span><span class="cx">             self.fail(&quot;Calendar is not a VCALENDAR&quot;)
</span><del>-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
</del><ins>+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
</ins><span class="cx">         for key in instances:
</span><span class="cx">             instance = instances[key]
</span><span class="cx">             start = instance.start
</span><span class="cx">             end = instance.end
</span><del>-            self.assertEqual(start, PyCalendarDateTime(2007, 12, 25, 05, 0, 0, PyCalendarTimezone(utc=True)))
-            self.assertEqual(end, PyCalendarDateTime(2007, 12, 25, 06, 0, 0, PyCalendarTimezone(utc=True)))
</del><ins>+            self.assertEqual(start, DateTime(2007, 12, 25, 05, 0, 0, Timezone(utc=True)))
+            self.assertEqual(end, DateTime(2007, 12, 25, 06, 0, 0, Timezone(utc=True)))
</ins><span class="cx">             break
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_upgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/test/test_upgrade.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_upgrade.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/test/test_upgrade.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1675,8 +1675,8 @@
</span><span class="cx"> ATTENDEE;CN=Double 'quotey' Quotes;CUTYPE=INDIVIDUAL;EMAIL=doublequotes@ex
</span><span class="cx">  ample.com;PARTSTAT=ACCEPTED:urn:uuid:8E04787E-336D-41ED-A70B-D233AD0DCE6F
</span><span class="cx"> ATTENDEE;CN=Cyrus Daboo;CUTYPE=INDIVIDUAL;EMAIL=cdaboo@example.com;PARTSTA
</span><del>- T=ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89
- 500
</del><ins>+ T=ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A8
+ 9500
</ins><span class="cx"> CREATED:20090203T181910Z
</span><span class="cx"> DESCRIPTION:This has &quot; Bad Quotes &quot; in it
</span><span class="cx"> DTSTAMP:20090203T181924Z
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtesttest_utilpyfromrev11912CalendarServerbranchesuserscdaboojsontwistedcaldavtesttest_utilpy"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/twistedcaldav/test/test_util.py (from rev 11912, CalendarServer/branches/users/cdaboo/json/twistedcaldav/test/test_util.py) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/test/test_util.py                                (rev 0)
+++ CalendarServer/trunk/twistedcaldav/test/test_util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,144 @@
</span><ins>+##
+# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twext.web2.http_headers import Headers
+
+import twistedcaldav.test.util
+from twistedcaldav.util import bestAcceptType
+
+class AcceptType(twistedcaldav.test.util.TestCase):
+    &quot;&quot;&quot;
+    L{bestAcceptType} tests
+    &quot;&quot;&quot;
+    def test_bestAcceptType(self):
+
+        data = (
+            (
+                &quot;#1.1&quot;,
+                (&quot;Accept&quot;, &quot;text/plain&quot;),
+                [&quot;text/plain&quot;],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#1.2&quot;,
+                (&quot;Accept&quot;, &quot;text/plain&quot;),
+                [&quot;text/calendar&quot;],
+                None,
+            ),
+            (
+                &quot;#1.3&quot;,
+                (&quot;Accept&quot;, &quot;text/*&quot;),
+                [&quot;text/plain&quot;],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#1.4&quot;,
+                (&quot;Accept&quot;, &quot;*/*&quot;),
+                [&quot;text/plain&quot;],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#2.1&quot;,
+                (&quot;Accept&quot;, &quot;text/plain&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#2.2&quot;,
+                (&quot;Accept&quot;, &quot;text/plain&quot;),
+                [&quot;text/calendar&quot;, &quot;application/text&quot;, ],
+                None,
+            ),
+            (
+                &quot;#2.3&quot;,
+                (&quot;Accept&quot;, &quot;text/*&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#2.4&quot;,
+                (&quot;Accept&quot;, &quot;*/*&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#2.5&quot;,
+                (&quot;Accept&quot;, &quot;application/text&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;application/text&quot;,
+            ),
+            (
+                &quot;#2.6&quot;,
+                (&quot;Accept&quot;, &quot;application/*&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;application/text&quot;,
+            ),
+            (
+                &quot;#3.1&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/text;q=0.3&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#3.2&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/text;q=0.3&quot;),
+                [&quot;text/calendar&quot;, &quot;application/calendar&quot;, ],
+                None,
+            ),
+            (
+                &quot;#3.3&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/text;q=0.3&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#3.4&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/text;q=0.3&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#3.5&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.3, application/text;q=0.5&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;application/text&quot;,
+            ),
+            (
+                &quot;#3.6&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/*;q=0.3&quot;),
+                [&quot;text/plain&quot;, &quot;application/text&quot;, ],
+                &quot;text/plain&quot;,
+            ),
+            (
+                &quot;#4.1&quot;,
+                (&quot;Accept&quot;, &quot;text/plain;q=0.5, application/text;q=0.2, text/*;q=0.3&quot;),
+                [&quot;text/calendar&quot;, &quot;application/text&quot;, ],
+                &quot;text/calendar&quot;,
+            ),
+            (
+                &quot;#5.1&quot;,
+                None,
+                [&quot;text/calendar&quot;, &quot;application/text&quot;, ],
+                &quot;text/calendar&quot;,
+            ),
+        )
+
+        for title, hdr, allowedTypes, result in data:
+            hdrs = Headers()
+            if hdr:
+                hdrs.addRawHeader(*hdr)
+            check = bestAcceptType(hdrs.getHeader(&quot;accept&quot;), allowedTypes)
+            self.assertEqual(check, result, msg=&quot;Failed %s&quot; % (title,))
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtimezonespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/timezones.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/timezones.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/timezones.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> 
</span><del>-from pycalendar.timezonedb import PyCalendarTimezoneDatabase
</del><ins>+from pycalendar.timezonedb import TimezoneDatabase
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx">             TimezoneCache.dirName = None
</span><span class="cx">             TimezoneCache.validatePath()
</span><span class="cx">         TimezoneCache.version = TimezoneCache.getTZVersion(TimezoneCache.getDBPath())
</span><del>-        PyCalendarTimezoneDatabase.createTimezoneDatabase(TimezoneCache.getDBPath())
</del><ins>+        TimezoneDatabase.createTimezoneDatabase(TimezoneCache.getDBPath())
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><span class="lines">@@ -171,7 +171,7 @@
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><span class="cx">     def clear():
</span><del>-        PyCalendarTimezoneDatabase.clearTimezoneDatabase()
</del><ins>+        TimezoneDatabase.clearTimezoneDatabase()
</ins><span class="cx"> 
</span><span class="cx"> # zoneinfo never changes in a running instance so cache all this data as we use it
</span><span class="cx"> cachedTZs = {}
</span><span class="lines">@@ -207,7 +207,7 @@
</span><span class="cx"> 
</span><span class="cx">     if tzid not in cachedVTZs:
</span><span class="cx"> 
</span><del>-        tzcal = PyCalendarTimezoneDatabase.getTimezoneInCalendar(tzid)
</del><ins>+        tzcal = TimezoneDatabase.getTimezoneInCalendar(tzid)
</ins><span class="cx">         if tzcal:
</span><span class="cx">             cachedVTZs[tzid] = tzcal
</span><span class="cx">         else:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtimezoneservicepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/timezoneservice.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/timezoneservice.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/timezoneservice.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> from twistedcaldav.timezones import listTZs
</span><span class="cx"> from twistedcaldav.timezones import readTZ
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> class TimezoneServiceResource (ReadOnlyNoCopyResourceMixIn, DAVResourceWithoutChildrenMixin, DAVResource):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -66,20 +66,25 @@
</span><span class="cx">         self.parent = parent
</span><span class="cx">         self.cache = {}
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def deadProperties(self):
</span><span class="cx">         if not hasattr(self, &quot;_dead_properties&quot;):
</span><span class="cx">             self._dead_properties = NonePropertyStore(self)
</span><span class="cx">         return self._dead_properties
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def etag(self):
</span><span class="cx">         return succeed(None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def checkPreconditions(self, request):
</span><span class="cx">         return None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def checkPrivileges(self, request, privileges, recurse=False, principal=None, inherited_aces=None):
</span><span class="cx">         return succeed(None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def defaultAccessControlList(self):
</span><span class="cx">         return davxml.ACL(
</span><span class="cx">             # DAV:Read for all principals (includes anonymous)
</span><span class="lines">@@ -92,21 +97,27 @@
</span><span class="cx">             ),
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def contentType(self):
</span><span class="cx">         return MimeType.fromString(&quot;text/xml&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceType(self):
</span><span class="cx">         return davxml.ResourceType.timezones
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCollection(self):
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isCalendarCollection(self):
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isPseudoCalendarCollection(self):
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def render(self, request):
</span><span class="cx">         output = &quot;&quot;&quot;&lt;html&gt;
</span><span class="cx"> &lt;head&gt;
</span><span class="lines">@@ -127,10 +138,11 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         The timezone service POST method.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         # GET and POST do the same thing
</span><span class="cx">         return self.http_POST(request)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def http_POST(self, request):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         The timezone service POST method.
</span><span class="lines">@@ -138,11 +150,11 @@
</span><span class="cx"> 
</span><span class="cx">         # Check authentication and access controls
</span><span class="cx">         def _gotResult(_):
</span><del>-            
</del><ins>+
</ins><span class="cx">             if not request.args:
</span><span class="cx">                 # Do normal GET behavior
</span><span class="cx">                 return self.render(request)
</span><del>-    
</del><ins>+
</ins><span class="cx">             method = request.args.get(&quot;method&quot;, (&quot;&quot;,))
</span><span class="cx">             if len(method) != 1:
</span><span class="cx">                 raise HTTPError(ErrorResponse(
</span><span class="lines">@@ -151,41 +163,43 @@
</span><span class="cx">                     &quot;Invalid method query parameter&quot;,
</span><span class="cx">                 ))
</span><span class="cx">             method = method[0]
</span><del>-                
</del><ins>+
</ins><span class="cx">             action = {
</span><span class="cx">                 &quot;list&quot;   : self.doPOSTList,
</span><span class="cx">                 &quot;get&quot;    : self.doPOSTGet,
</span><span class="cx">                 &quot;expand&quot; : self.doPOSTExpand,
</span><span class="cx">             }.get(method, None)
</span><del>-            
</del><ins>+
</ins><span class="cx">             if action is None:
</span><span class="cx">                 raise HTTPError(ErrorResponse(
</span><span class="cx">                     responsecode.BAD_REQUEST,
</span><span class="cx">                     (calendarserver_namespace, &quot;supported-method&quot;),
</span><span class="cx">                     &quot;Unknown method query parameter&quot;,
</span><span class="cx">                 ))
</span><del>-    
</del><ins>+
</ins><span class="cx">             return action(request)
</span><del>-            
</del><ins>+
</ins><span class="cx">         d = self.authorize(request, (davxml.Read(),))
</span><span class="cx">         d.addCallback(_gotResult)
</span><span class="cx">         return d
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def doPOSTList(self, request):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return a list of all timezones known to the server.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         tzids = listTZs()
</span><span class="cx">         tzids.sort()
</span><span class="cx">         result = customxml.TZIDs(*[customxml.TZID(tzid) for tzid in tzids])
</span><span class="cx">         return XMLResponse(responsecode.OK, result)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def doPOSTGet(self, request):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return the specified timezone data.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        
</del><ins>+
</ins><span class="cx">         tzid = request.args.get(&quot;tzid&quot;, ())
</span><span class="cx">         if len(tzid) != 1:
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="lines">@@ -209,6 +223,7 @@
</span><span class="cx">         response.headers.setHeader(&quot;content-type&quot;, MimeType.fromString(&quot;text/calendar; charset=utf-8&quot;))
</span><span class="cx">         return response
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def doPOSTExpand(self, request):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Expand a timezone within specified start/end dates.
</span><span class="lines">@@ -235,7 +250,7 @@
</span><span class="cx">             start = request.args.get(&quot;start&quot;, ())
</span><span class="cx">             if len(start) != 1:
</span><span class="cx">                 raise ValueError()
</span><del>-            start = PyCalendarDateTime.parseText(start[0])
</del><ins>+            start = DateTime.parseText(start[0])
</ins><span class="cx">         except ValueError:
</span><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 responsecode.BAD_REQUEST,
</span><span class="lines">@@ -247,7 +262,7 @@
</span><span class="cx">             end = request.args.get(&quot;end&quot;, ())
</span><span class="cx">             if len(end) != 1:
</span><span class="cx">                 raise ValueError()
</span><del>-            end = PyCalendarDateTime.parseText(end[0])
</del><ins>+            end = DateTime.parseText(end[0])
</ins><span class="cx">             if end &lt;= start:
</span><span class="cx">                 raise ValueError()
</span><span class="cx">         except ValueError:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavtimezonestdservicepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/timezonestdservice.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/timezonestdservice.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/timezonestdservice.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -49,9 +49,9 @@
</span><span class="cx">     addVTZ
</span><span class="cx"> from twistedcaldav.xmlutil import addSubElement
</span><span class="cx"> 
</span><del>-from pycalendar.calendar import PyCalendar
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.exceptions import PyCalendarInvalidData
</del><ins>+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.datetime import DateTime
+from pycalendar.exceptions import InvalidData
</ins><span class="cx"> 
</span><span class="cx"> import hashlib
</span><span class="cx"> import itertools
</span><span class="lines">@@ -89,7 +89,13 @@
</span><span class="cx">         else:
</span><span class="cx">             raise ValueError(&quot;Invalid TimezoneService mode: %s&quot; % (config.TimezoneService.Mode,))
</span><span class="cx"> 
</span><ins>+        self.formats = []
+        self.formats.append(&quot;text/calendar&quot;)
+        self.formats.append(&quot;text/plain&quot;)
+        if config.EnableJSONData:
+            self.formats.append(&quot;application/calendar+json&quot;)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _initPrimaryService(self):
</span><span class="cx">         tzpath = TimezoneCache.getDBPath()
</span><span class="cx">         xmlfile = os.path.join(tzpath, &quot;timezones.xml&quot;)
</span><span class="lines">@@ -268,7 +274,7 @@
</span><span class="cx">                 {
</span><span class="cx">                     &quot;name&quot;: &quot;get&quot;,
</span><span class="cx">                     &quot;parameters&quot;: [
</span><del>-                        {&quot;name&quot;: &quot;format&quot;, &quot;required&quot;: False, &quot;multi&quot;: False, &quot;values&quot;: [&quot;text/calendar&quot;, &quot;text/plain&quot;, ], },
</del><ins>+                        {&quot;name&quot;: &quot;format&quot;, &quot;required&quot;: False, &quot;multi&quot;: False, &quot;values&quot;: self.formats, },
</ins><span class="cx">                         {&quot;name&quot;: &quot;tzid&quot;, &quot;required&quot;: True, &quot;multi&quot;: False, },
</span><span class="cx">                     ],
</span><span class="cx">                 },
</span><span class="lines">@@ -303,7 +309,7 @@
</span><span class="cx">             # Validate a date-time stamp
</span><span class="cx">             changedsince = changedsince[0]
</span><span class="cx">             try:
</span><del>-                dt = PyCalendarDateTime.parseText(changedsince)
</del><ins>+                dt = DateTime.parseText(changedsince)
</ins><span class="cx">             except ValueError:
</span><span class="cx">                 raise HTTPError(JSONResponse(
</span><span class="cx">                     responsecode.BAD_REQUEST,
</span><span class="lines">@@ -348,7 +354,7 @@
</span><span class="cx">             ))
</span><span class="cx"> 
</span><span class="cx">         format = request.args.get(&quot;format&quot;, (&quot;text/calendar&quot;,))
</span><del>-        if len(format) != 1 or format[0] not in (&quot;text/calendar&quot;, &quot;text/plain&quot;,):
</del><ins>+        if len(format) != 1 or format[0] not in self.formats:
</ins><span class="cx">             raise HTTPError(JSONResponse(
</span><span class="cx">                 responsecode.BAD_REQUEST,
</span><span class="cx">                 {
</span><span class="lines">@@ -368,7 +374,7 @@
</span><span class="cx">                 }
</span><span class="cx">             ))
</span><span class="cx"> 
</span><del>-        tzdata = calendar.getText()
</del><ins>+        tzdata = calendar.getText(format=format if format != &quot;text/plain&quot; else None)
</ins><span class="cx"> 
</span><span class="cx">         response = Response()
</span><span class="cx">         response.stream = MemoryStream(tzdata)
</span><span class="lines">@@ -396,9 +402,9 @@
</span><span class="cx">             if len(start) &gt; 1:
</span><span class="cx">                 raise ValueError()
</span><span class="cx">             elif len(start) == 1:
</span><del>-                start = PyCalendarDateTime.parseText(start[0])
</del><ins>+                start = DateTime.parseText(start[0])
</ins><span class="cx">             else:
</span><del>-                start = PyCalendarDateTime.getToday()
</del><ins>+                start = DateTime.getToday()
</ins><span class="cx">                 start.setDay(1)
</span><span class="cx">                 start.setMonth(1)
</span><span class="cx">         except ValueError:
</span><span class="lines">@@ -415,9 +421,9 @@
</span><span class="cx">             if len(end) &gt; 1:
</span><span class="cx">                 raise ValueError()
</span><span class="cx">             elif len(end) == 1:
</span><del>-                end = PyCalendarDateTime.parseText(end[0])
</del><ins>+                end = DateTime.parseText(end[0])
</ins><span class="cx">             else:
</span><del>-                end = PyCalendarDateTime.getToday()
</del><ins>+                end = DateTime.getToday()
</ins><span class="cx">                 end.setDay(1)
</span><span class="cx">                 end.setMonth(1)
</span><span class="cx">                 end.offsetYear(10)
</span><span class="lines">@@ -558,7 +564,7 @@
</span><span class="cx">         Generate a PyCalendar containing the requested timezone.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # We will just use our existing TimezoneCache here
</span><del>-        calendar = PyCalendar()
</del><ins>+        calendar = Calendar()
</ins><span class="cx">         try:
</span><span class="cx">             vtz = readVTZ(tzid)
</span><span class="cx">             calendar.addComponent(vtz.getComponents()[0].duplicate())
</span><span class="lines">@@ -618,7 +624,7 @@
</span><span class="cx">         Create a new DB xml file from scratch by scanning zoneinfo.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        self.dtstamp = PyCalendarDateTime.getNowUTC().getXMLText()
</del><ins>+        self.dtstamp = DateTime.getNowUTC().getXMLText()
</ins><span class="cx">         self._scanTZs(&quot;&quot;)
</span><span class="cx">         self._dumpTZs()
</span><span class="cx"> 
</span><span class="lines">@@ -672,7 +678,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Update existing DB info by comparing md5's.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        self.dtstamp = PyCalendarDateTime.getNowUTC().getXMLText()
</del><ins>+        self.dtstamp = DateTime.getNowUTC().getXMLText()
</ins><span class="cx">         self.changeCount = 0
</span><span class="cx">         self.changed = set()
</span><span class="cx">         self._scanTZs(&quot;&quot;, checkIfChanged=True)
</span><span class="lines">@@ -847,8 +853,8 @@
</span><span class="cx"> 
</span><span class="cx">         ical = response.data
</span><span class="cx">         try:
</span><del>-            calendar = PyCalendar.parseText(ical)
-        except PyCalendarInvalidData:
</del><ins>+            calendar = Calendar.parseText(ical)
+        except InvalidData:
</ins><span class="cx">             log.error(&quot;Invalid calendar data for tzid: %s&quot; % (tzinfo.tzid,))
</span><span class="cx">             returnValue(None)
</span><span class="cx">         ical = calendar.getText()
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavupgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/upgrade.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/upgrade.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/upgrade.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1065,7 +1065,6 @@
</span><span class="cx">             # Migrate mail tokens from sqlite to store
</span><span class="cx">             yield migrateTokensToStore(self.config.DataRoot, self.store)
</span><span class="cx"> 
</span><del>-            
</del><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def processInboxItems(self):
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/util.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/util.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -517,3 +517,52 @@
</span><span class="cx">         cuas = principal.record.calendarUserAddresses
</span><span class="cx"> 
</span><span class="cx">         return (fullName, rec.guid, cuas)
</span><ins>+
+
+
+def bestAcceptType(accepts, allowedTypes):
+    &quot;&quot;&quot;
+    Given a set of Accept headers and the set of types the server can return, determine the best choice
+    of format to return to the client.
+
+    @param accepts: parsed accept headers
+    @type accepts: C{dict}
+    @param allowedTypes: list of allowed types in server preferred order
+    @type allowedTypes: C{list}
+    &quot;&quot;&quot;
+
+    # If no Accept present just use the first allowed type - the server's preference
+    if not accepts:
+        return allowedTypes[0]
+
+    # Get mapping for ordered top-level types for use in subtype wildcard match
+    toptypes = {}
+    for allowed in allowedTypes:
+        mediaType = allowed.split(&quot;/&quot;)[0]
+        if mediaType not in toptypes:
+            toptypes[mediaType] = allowed
+
+    result = None
+    result_qval = 0.0
+    for content_type, qval in accepts.items():
+        # Exact match
+        ctype = &quot;%s/%s&quot; % (content_type.mediaType, content_type.mediaSubtype,)
+        if ctype in allowedTypes:
+            if qval &gt; result_qval:
+                result = ctype
+                result_qval = qval
+
+        # Subtype wildcard match
+        elif content_type.mediaType != &quot;*&quot; and content_type.mediaSubtype == &quot;*&quot;:
+            if content_type.mediaType in toptypes:
+                if qval &gt; result_qval:
+                    result = toptypes[content_type.mediaType]
+                    result_qval = qval
+
+        # Full wildcard match
+        elif content_type.mediaType == &quot;*&quot; and content_type.mediaSubtype == &quot;*&quot;:
+            if qval &gt; result_qval:
+                result = allowedTypes[0]
+                result_qval = qval
+
+    return result
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavvcardpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/vcard.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/vcard.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/vcard.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -31,9 +31,11 @@
</span><span class="cx"> from twext.web2.stream import IStream
</span><span class="cx"> from twext.web2.dav.util import allDataFromStream
</span><span class="cx"> 
</span><del>-from pycalendar.attribute import PyCalendarAttribute
-from pycalendar.componentbase import PyCalendarComponentBase
-from pycalendar.exceptions import PyCalendarError
</del><ins>+from twistedcaldav.config import config
+
+from pycalendar.parameter import Parameter
+from pycalendar.componentbase import ComponentBase
+from pycalendar.exceptions import ErrorBase
</ins><span class="cx"> from pycalendar.vcard.card import Card
</span><span class="cx"> from pycalendar.vcard.property import Property as pyProperty
</span><span class="cx"> 
</span><span class="lines">@@ -44,6 +46,8 @@
</span><span class="cx"> class InvalidVCardDataError(ValueError):
</span><span class="cx">     pass
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class Property (object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     vCard Property
</span><span class="lines">@@ -73,31 +77,55 @@
</span><span class="cx">             for attrname, attrvalue in params.items():
</span><span class="cx">                 if isinstance(attrvalue, unicode):
</span><span class="cx">                     attrvalue = attrvalue.encode(&quot;utf-8&quot;)
</span><del>-                self._pycard.addAttribute(PyCalendarAttribute(attrname, attrvalue))
</del><ins>+                self._pycard.addParameter(Parameter(attrname, attrvalue))
</ins><span class="cx"> 
</span><del>-    def __str__ (self): return str(self._pycard)
-    def __repr__(self): return &quot;&lt;%s: %r: %r&gt;&quot; % (self.__class__.__name__, self.name(), self.value())
</del><span class="cx"> 
</span><del>-    def __hash__(self): return hash(str(self))
</del><ins>+    def __str__(self):
+        return str(self._pycard)
</ins><span class="cx"> 
</span><del>-    def __ne__(self, other): return not self.__eq__(other)
</del><ins>+
+    def __repr__(self):
+        return &quot;&lt;%s: %r: %r&gt;&quot; % (self.__class__.__name__, self.name(), self.value())
+
+
+    def __hash__(self):
+        return hash(str(self))
+
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+
</ins><span class="cx">     def __eq__(self, other):
</span><del>-        if not isinstance(other, Property): return False
</del><ins>+        if not isinstance(other, Property):
+            return False
</ins><span class="cx">         return self._pycard == other._pycard
</span><span class="cx"> 
</span><del>-    def __gt__(self, other): return not (self.__eq__(other) or self.__lt__(other))
</del><ins>+
+    def __gt__(self, other):
+        return not (self.__eq__(other) or self.__lt__(other))
+
+
</ins><span class="cx">     def __lt__(self, other):
</span><span class="cx">         my_name = self.name()
</span><span class="cx">         other_name = other.name()
</span><span class="cx"> 
</span><del>-        if my_name &lt; other_name: return True
-        if my_name &gt; other_name: return False
</del><ins>+        if my_name &lt; other_name:
+            return True
+        if my_name &gt; other_name:
+            return False
</ins><span class="cx"> 
</span><span class="cx">         return self.value() &lt; other.value()
</span><span class="cx"> 
</span><del>-    def __ge__(self, other): return self.__eq__(other) or self.__gt__(other)
-    def __le__(self, other): return self.__eq__(other) or self.__lt__(other)
</del><span class="cx"> 
</span><ins>+    def __ge__(self, other):
+        return self.__eq__(other) or self.__gt__(other)
+
+
+    def __le__(self, other):
+        return self.__eq__(other) or self.__lt__(other)
+
+
</ins><span class="cx">     def duplicate(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Duplicate this object and all its contents.
</span><span class="lines">@@ -105,35 +133,45 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return Property(None, None, params=None, pycard=self._pycard.duplicate())
</span><span class="cx"> 
</span><del>-    def name  (self): return self._pycard.getName()
</del><span class="cx"> 
</span><del>-    def value (self): return self._pycard.getValue().getValue()
</del><ins>+    def name(self):
+        return self._pycard.getName()
</ins><span class="cx"> 
</span><del>-    def strvalue (self): return str(self._pycard.getValue())
</del><span class="cx"> 
</span><ins>+    def value(self):
+        return self._pycard.getValue().getValue()
+
+
+    def strvalue(self):
+        return str(self._pycard.getValue())
+
+
</ins><span class="cx">     def setValue(self, value):
</span><span class="cx">         self._pycard.setValue(value)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def parameterNames(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Returns a set containing parameter names for this property.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         result = set()
</span><del>-        for pyattrlist in self._pycard.getAttributes().values():
</del><ins>+        for pyattrlist in self._pycard.getParameters().values():
</ins><span class="cx">             for pyattr in pyattrlist:
</span><span class="cx">                 result.add(pyattr.getName())
</span><span class="cx">         return result
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def parameterValue(self, name, default=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Returns a single value for the given parameter.  Raises
</span><span class="cx">         InvalidICalendarDataError if the parameter has more than one value.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         try:
</span><del>-            return self._pycard.getAttributeValue(name)
</del><ins>+            return self._pycard.getParameterValue(name)
</ins><span class="cx">         except KeyError:
</span><span class="cx">             return default
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def parameterValues(self, name):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Returns a single value for the given parameter.  Raises
</span><span class="lines">@@ -141,7 +179,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         results = []
</span><span class="cx">         try:
</span><del>-            attrs = self._pycard.getAttributes()[name.upper()]
</del><ins>+            attrs = self._pycard.getParameters()[name.upper()]
</ins><span class="cx">         except KeyError:
</span><span class="cx">             return []
</span><span class="cx"> 
</span><span class="lines">@@ -149,28 +187,33 @@
</span><span class="cx">             results.extend(attr.getValues())
</span><span class="cx">         return results
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def hasParameter(self, paramname):
</span><del>-        return self._pycard.hasAttribute(paramname)
</del><ins>+        return self._pycard.hasParameter(paramname)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def setParameter(self, paramname, paramvalue):
</span><del>-        self._pycard.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
</del><ins>+        self._pycard.replaceParameter(Parameter(paramname, paramvalue))
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def removeParameter(self, paramname):
</span><del>-        self._pycard.removeAttributes(paramname)
</del><ins>+        self._pycard.removeParameters(paramname)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def removeAllParameters(self):
</span><del>-        self._pycard.setAttributes({})
</del><ins>+        self._pycard.setParameters({})
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def removeParameterValue(self, paramname, paramvalue):
</span><span class="cx"> 
</span><span class="cx">         paramname = paramname.upper()
</span><span class="cx">         for attrName in self.parameterNames():
</span><span class="cx">             if attrName.upper() == paramname:
</span><del>-                for attr in tuple(self._pycard.getAttributes()[attrName]):
</del><ins>+                for attr in tuple(self._pycard.getParameters()[attrName]):
</ins><span class="cx">                     for value in attr.getValues():
</span><span class="cx">                         if value == paramvalue:
</span><span class="cx">                             if not attr.removeValue(value):
</span><del>-                                self._pycard.removeAttributes(paramname)
</del><ins>+                                self._pycard.removeParameters(paramname)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -178,8 +221,20 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     X{vCard} component.
</span><span class="cx">     &quot;&quot;&quot;
</span><ins>+    allowedTypesList = None
+
+
</ins><span class="cx">     @classmethod
</span><del>-    def allFromString(clazz, string):
</del><ins>+    def allowedTypes(cls):
+        if cls.allowedTypesList is None:
+            cls.allowedTypesList = [&quot;text/vcard&quot;]
+            if config.EnableJSONData:
+                cls.allowedTypesList.append(&quot;application/vcard+json&quot;)
+        return cls.allowedTypesList
+
+
+    @classmethod
+    def allFromString(clazz, string, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         FIXME: Just default to reading a single VCARD - actually need more
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -193,62 +248,85 @@
</span><span class="cx">         if string[:3] == codecs.BOM_UTF8:
</span><span class="cx">             string = string[3:]
</span><span class="cx"> 
</span><del>-        return clazz.allFromStream(StringIO.StringIO(string))
</del><ins>+        return clazz.allFromStream(StringIO.StringIO(string), format)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><del>-    def allFromStream(clazz, stream):
</del><ins>+    def allFromStream(clazz, stream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         FIXME: Just default to reading a single VCARD - actually need more
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         try:
</span><del>-            results = Card.parseMultiple(stream)
-        except PyCalendarError:
</del><ins>+            results = Card.parseMultipleData(stream, format)
+        except ErrorBase:
</ins><span class="cx">             results = None
</span><span class="cx">         if not results:
</span><span class="cx">             stream.seek(0)
</span><span class="cx">             raise InvalidVCardDataError(&quot;%s&quot; % (stream.read(),))
</span><span class="cx">         return [clazz(None, pycard=result) for result in results]
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><del>-    def fromString(clazz, string):
</del><ins>+    def fromString(clazz, string, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a string.
</span><span class="cx">         @param string: a string containing vCard data.
</span><span class="cx">         @return: a L{Component} representing the first component described by
</span><span class="cx">             C{string}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if type(string) is unicode:
-            string = string.encode(&quot;utf-8&quot;)
-        else:
-            # Valid utf-8 please
-            string.decode(&quot;utf-8&quot;)
</del><ins>+        return clazz._fromData(string, False, format)
</ins><span class="cx"> 
</span><del>-        # No BOMs please
-        if string[:3] == codecs.BOM_UTF8:
-            string = string[3:]
</del><span class="cx"> 
</span><del>-        return clazz.fromStream(StringIO.StringIO(string))
</del><ins>+    @classmethod
+    def fromStream(clazz, stream, format=None):
+        &quot;&quot;&quot;
+        Construct a L{Component} from a stream.
+        @param stream: a C{read()}able stream containing vCard data.
+        @return: a L{Component} representing the first component described by
+            C{stream}.
+        &quot;&quot;&quot;
+        return clazz._fromData(stream, True, format)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><del>-    def fromStream(clazz, stream):
</del><ins>+    def _fromData(clazz, data, isstream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a stream.
</span><span class="cx">         @param stream: a C{read()}able stream containing vCard data.
</span><ins>+        @param format: a C{str} indicating whether the data is vCard or jCard
</ins><span class="cx">         @return: a L{Component} representing the first component described by
</span><span class="cx">             C{stream}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        cal = Card()
</del><ins>+
+        if isstream:
+            pass
+        else:
+            if type(data) is unicode:
+                data = data.encode(&quot;utf-8&quot;)
+            else:
+                # Valid utf-8 please
+                data.decode(&quot;utf-8&quot;)
+
+            # No BOMs please
+            if data[:3] == codecs.BOM_UTF8:
+                data = data[3:]
+
+        errmsg = &quot;Unknown&quot;
</ins><span class="cx">         try:
</span><del>-            result = cal.parse(stream)
-        except PyCalendarError:
</del><ins>+            result = Card.parseData(data, format)
+        except ErrorBase, e:
+            errmsg = &quot;%s: %s&quot; % (e.mReason, e.mData,)
</ins><span class="cx">             result = None
</span><span class="cx">         if not result:
</span><del>-            stream.seek(0)
-            raise InvalidVCardDataError(&quot;%s&quot; % (stream.read(),))
-        return clazz(None, pycard=cal)
</del><ins>+            if isstream:
+                data.seek(0)
+                data = data.read()
+            raise InvalidVCardDataError(&quot;%s\n%s&quot; % (errmsg, data,))
+        return clazz(None, pycard=result)
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><del>-    def fromIStream(clazz, stream):
</del><ins>+    def fromIStream(clazz, stream, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Construct a L{Component} from a stream.
</span><span class="cx">         @param stream: an L{IStream} containing vCard data.
</span><span class="lines">@@ -261,9 +339,11 @@
</span><span class="cx">         #   A better solution would parse directly and incrementally from the
</span><span class="cx">         #   request stream.
</span><span class="cx">         #
</span><del>-        def parse(data): return clazz.fromString(data)
</del><ins>+        def parse(data):
+            return clazz.fromString(data, format)
</ins><span class="cx">         return allDataFromStream(IStream(stream), parse)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def __init__(self, name, **kwargs):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Use this constructor to initialize an empty L{Component}.
</span><span class="lines">@@ -277,8 +357,8 @@
</span><span class="cx">                 pyobj = kwargs[&quot;pycard&quot;]
</span><span class="cx"> 
</span><span class="cx">                 if pyobj is not None:
</span><del>-                    if not isinstance(pyobj, PyCalendarComponentBase):
-                        raise TypeError(&quot;Not a PyCalendarComponentBase: %r&quot; % (pyobj,))
</del><ins>+                    if not isinstance(pyobj, ComponentBase):
+                        raise TypeError(&quot;Not a ComponentBase: %r&quot; % (pyobj,))
</ins><span class="cx"> 
</span><span class="cx">                 self._pycard = pyobj
</span><span class="cx">             else:
</span><span class="lines">@@ -302,28 +382,53 @@
</span><span class="cx">         else:
</span><span class="cx">             raise ValueError(&quot;VCards have no child components&quot;)
</span><span class="cx"> 
</span><del>-    def __str__ (self): return str(self._pycard)
-    def __repr__(self): return &quot;&lt;%s: %r&gt;&quot; % (self.__class__.__name__, str(self._pycard))
</del><span class="cx"> 
</span><ins>+    def __str__(self):
+        return str(self._pycard)
+
+
+    def __repr__(self):
+        return &quot;&lt;%s: %r&gt;&quot; % (self.__class__.__name__, str(self._pycard))
+
+
</ins><span class="cx">     def __hash__(self):
</span><span class="cx">         return hash(str(self))
</span><span class="cx"> 
</span><del>-    def __ne__(self, other): return not self.__eq__(other)
</del><ins>+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+
</ins><span class="cx">     def __eq__(self, other):
</span><span class="cx">         if not isinstance(other, Component):
</span><span class="cx">             return False
</span><span class="cx">         return self._pycard == other._pycard
</span><span class="cx"> 
</span><ins>+
+    def getText(self, format=None):
+        &quot;&quot;&quot;
+        Return text representation
+        &quot;&quot;&quot;
+        assert self.name() == &quot;VCARD&quot;, &quot;Must be a VCARD: %r&quot; % (self,)
+
+        result = self._pycard.getText(format)
+        if result is None:
+            raise ValueError(&quot;Unknown format requested for address data.&quot;)
+        return result
+
+
</ins><span class="cx">     # FIXME: Should this not be in __eq__?
</span><span class="cx">     def same(self, other):
</span><span class="cx">         return self._pycard == other._pycard
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def name(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        @return: the name of the iCalendar type of this component.
</del><ins>+        @return: the name of the vCard type of this component.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._pycard.getType()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def duplicate(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Duplicate this object and all its contents.
</span><span class="lines">@@ -331,6 +436,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return Component(None, pycard=self._pycard.duplicate())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def hasProperty(self, name):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @param name: the name of the property whose existence is being tested.
</span><span class="lines">@@ -338,6 +444,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._pycard.hasProperty(name)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def getProperty(self, name):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Get one property from the property list.
</span><span class="lines">@@ -346,10 +453,13 @@
</span><span class="cx">         @raise: L{ValueError} if there is more than one property of the given name.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         properties = tuple(self.properties(name))
</span><del>-        if len(properties) == 1: return properties[0]
-        if len(properties) &gt; 1: raise InvalidVCardDataError(&quot;More than one %s property in component %r&quot; % (name, self))
</del><ins>+        if len(properties) == 1:
+            return properties[0]
+        if len(properties) &gt; 1:
+            raise InvalidVCardDataError(&quot;More than one %s property in component %r&quot; % (name, self))
</ins><span class="cx">         return None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def properties(self, name=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @param name: if given and not C{None}, restricts the returned properties
</span><span class="lines">@@ -368,6 +478,7 @@
</span><span class="cx">             for p in properties
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def propertyValue(self, name):
</span><span class="cx">         properties = tuple(self.properties(name))
</span><span class="cx">         if len(properties) == 1:
</span><span class="lines">@@ -385,6 +496,7 @@
</span><span class="cx">         self._pycard.addProperty(property._pycard)
</span><span class="cx">         self._pycard.finalise()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def removeProperty(self, property):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Remove a property from this component.
</span><span class="lines">@@ -393,6 +505,7 @@
</span><span class="cx">         self._pycard.removeProperty(property._pycard)
</span><span class="cx">         self._pycard.finalise()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def removeProperties(self, name):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         remove all properties with name
</span><span class="lines">@@ -400,6 +513,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         self._pycard.removeProperties(name)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def replaceProperty(self, property):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Add or replace a property in this component.
</span><span class="lines">@@ -410,6 +524,7 @@
</span><span class="cx">         self._pycard.removeProperties(property.name())
</span><span class="cx">         self.addProperty(property)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceUID(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the UID of the subcomponents in this component.
</span><span class="lines">@@ -421,6 +536,7 @@
</span><span class="cx"> 
</span><span class="cx">         return self._resource_uid
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceKind(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the kind of the subcomponents in this component.
</span><span class="lines">@@ -432,6 +548,7 @@
</span><span class="cx"> 
</span><span class="cx">         return self._resource_kind
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def resourceMemberAddresses(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: an iterable of X-ADDRESSBOOKSERVER-MEMBER property values
</span><span class="lines">@@ -440,6 +557,7 @@
</span><span class="cx"> 
</span><span class="cx">         return [prop.value() for prop in list(self.properties(&quot;X-ADDRESSBOOKSERVER-MEMBER&quot;))]
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def validVCardData(self, doFix=True, doRaise=True):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: tuple of fixed, unfixed issues
</span><span class="lines">@@ -454,17 +572,19 @@
</span><span class="cx">         if unfixed:
</span><span class="cx">             log.debug(&quot;vCard data had unfixable problems:\n  %s&quot; % (&quot;\n  &quot;.join(unfixed),))
</span><span class="cx">             if doRaise:
</span><del>-                raise InvalidVCardDataError(&quot;Calendar data had unfixable problems:\n  %s&quot; % (&quot;\n  &quot;.join(unfixed),))
</del><ins>+                raise InvalidVCardDataError(&quot;Address data had unfixable problems:\n  %s&quot; % (&quot;\n  &quot;.join(unfixed),))
</ins><span class="cx">         if fixed:
</span><span class="cx">             log.debug(&quot;vCard data had fixable problems:\n  %s&quot; % (&quot;\n  &quot;.join(fixed),))
</span><span class="cx"> 
</span><span class="cx">         return fixed, unfixed
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def validForCardDAV(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @raise ValueError: if the given vcard data is not valid.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if self.name() != &quot;VCARD&quot;: raise InvalidVCardDataError(&quot;Not a vcard&quot;)
</del><ins>+        if self.name() != &quot;VCARD&quot;:
+            raise InvalidVCardDataError(&quot;Not a vcard&quot;)
</ins><span class="cx"> 
</span><span class="cx">         version = self.propertyValue(&quot;VERSION&quot;)
</span><span class="cx">         if version != &quot;3.0&quot;:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavxmlutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/xmlutil.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/xmlutil.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/twistedcaldav/xmlutil.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -24,17 +24,21 @@
</span><span class="cx"> except ImportError:
</span><span class="cx">     from xml.parsers.expat import ExpatError as XMLParseError
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> # Utilities for working with ElementTree
</span><span class="cx"> 
</span><span class="cx"> def readXMLString(xmldata, expectedRootTag=None):
</span><span class="cx">     io = StringIO.StringIO(xmldata)
</span><span class="cx">     return readXML(io, expectedRootTag)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def readXML(xmlfile, expectedRootTag=None):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Read in XML data from a file and parse into ElementTree. Optionally verify
</span><span class="cx">     the root node is what we expect.
</span><del>-    
</del><ins>+
</ins><span class="cx">     @param xmlfile: file to read from
</span><span class="cx">     @type xmlfile: C{File}
</span><span class="cx">     @param expectedRootTag: root tag (qname) to test or C{None}
</span><span class="lines">@@ -52,14 +56,18 @@
</span><span class="cx">         root = etree.getroot()
</span><span class="cx">         if root.tag != expectedRootTag:
</span><span class="cx">             raise ValueError(&quot;Ignoring file '%s' because it is not a %s file&quot; % (xmlfile, expectedRootTag,))
</span><del>-    
</del><ins>+
</ins><span class="cx">     return etree, etree.getroot()
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def elementToXML(element):
</span><span class="cx">     return XML.tostring(element, &quot;utf-8&quot;)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def writeXML(xmlfile, root):
</span><del>-    
</del><ins>+
</ins><span class="cx">     data = &quot;&quot;&quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
</span><span class="cx"> &lt;!DOCTYPE %s SYSTEM &quot;%s.dtd&quot;&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -69,7 +77,7 @@
</span><span class="cx"> 
</span><span class="cx">     # Generate indentation
</span><span class="cx">     def _indentNode(node, level=0):
</span><del>-        
</del><ins>+
</ins><span class="cx">         if node.text is not None and node.text.strip():
</span><span class="cx">             return
</span><span class="cx">         elif len(node):
</span><span class="lines">@@ -87,27 +95,35 @@
</span><span class="cx">     with open(xmlfile, &quot;w&quot;) as f:
</span><span class="cx">         f.write(data)
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def newElementTreeWithRoot(roottag):
</span><span class="cx"> 
</span><span class="cx">     root = createElement(roottag)
</span><span class="cx">     etree = XML.ElementTree(root)
</span><del>-    
</del><ins>+
</ins><span class="cx">     return etree, root
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def createElement(tag, text=None, **attrs):
</span><span class="cx"> 
</span><span class="cx">     child = XML.Element(tag, attrs)
</span><span class="cx">     child.text = text
</span><span class="cx">     return child
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def addSubElement(parent, tag, text=None):
</span><span class="cx"> 
</span><span class="cx">     child = XML.SubElement(parent, tag)
</span><span class="cx">     child.text = text
</span><span class="cx">     return child
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def changeSubElementText(parent, tag, text):
</span><del>-    
</del><ins>+
</ins><span class="cx">     child = parent.find(tag)
</span><span class="cx">     if child is not None:
</span><span class="cx">         child.text = text
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastorefilepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/file.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/file.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -41,8 +41,8 @@
</span><span class="cx"> from twext.web2.dav.resource import TwistedGETContentMD5
</span><span class="cx"> from twext.web2.http_headers import generateContentType, MimeType
</span><span class="cx"> 
</span><del>-from twistedcaldav import caldavxml, customxml
-from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque
</del><ins>+from twistedcaldav import caldavxml, customxml, ical
+from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque, Transparent
</ins><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.ical import InvalidICalendarDataError
</span><span class="cx"> 
</span><span class="lines">@@ -84,6 +84,14 @@
</span><span class="cx">     _topPath = &quot;calendars&quot;
</span><span class="cx">     _notifierPrefix = &quot;CalDAV&quot;
</span><span class="cx"> 
</span><ins>+    _componentCalendarName = {
+        &quot;VEVENT&quot;: &quot;calendar&quot;,
+        &quot;VTODO&quot;: &quot;tasks&quot;,
+        &quot;VJOURNAL&quot;: &quot;journals&quot;,
+        &quot;VAVAILABILITY&quot;: &quot;available&quot;,
+        &quot;VPOLL&quot;: &quot;polls&quot;,
+    }
+
</ins><span class="cx">     def __init__(self, uid, path, calendarStore, transaction):
</span><span class="cx">         super(CalendarHome, self).__init__(uid, path, calendarStore, transaction)
</span><span class="cx"> 
</span><span class="lines">@@ -177,20 +185,19 @@
</span><span class="cx"> 
</span><span class="cx">     def createdHome(self):
</span><span class="cx"> 
</span><del>-        # Default calendar
-        defaultCal = self.createCalendarWithName(&quot;calendar&quot;)
-        props = defaultCal.properties()
-        props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Opaque())
-
</del><span class="cx">         # Check whether components type must be separate
</span><span class="cx">         if config.RestrictCalendarsToOneComponentType:
</span><del>-            defaultCal.setSupportedComponents(&quot;VEVENT&quot;)
</del><ins>+            for name in ical.allowedStoreComponents:
+                cal = self.createCalendarWithName(self._componentCalendarName[name])
+                cal.setSupportedComponents(name)
+                props = cal.properties()
+                if name not in (&quot;VEVENT&quot;, &quot;VAVAILABILITY&quot;,):
+                    props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Transparent())
+                else:
+                    props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Opaque())
+        else:
+            cal = self.createCalendarWithName(&quot;calendar&quot;)
</ins><span class="cx"> 
</span><del>-            # Default tasks
-            defaultTasks = self.createCalendarWithName(&quot;tasks&quot;)
-            props = defaultTasks.properties()
-            defaultTasks.setSupportedComponents(&quot;VTODO&quot;)
-
</del><span class="cx">         self.createCalendarWithName(&quot;inbox&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreindex_filepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/index_file.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/index_file.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/index_file.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -55,9 +55,9 @@
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.memcachepool import CachePoolUserMixIn
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -341,7 +341,7 @@
</span><span class="cx">                     maxDate = maxDate.duplicate()
</span><span class="cx">                     maxDate.setDateOnly(True)
</span><span class="cx">                     if isStartDate:
</span><del>-                        maxDate += PyCalendarDuration(days=365)
</del><ins>+                        maxDate += Duration(days=365)
</ins><span class="cx">                     self.testAndUpdateIndex(maxDate)
</span><span class="cx">             else:
</span><span class="cx">                 # We cannot handle this filter in an indexed search
</span><span class="lines">@@ -671,7 +671,7 @@
</span><span class="cx">         if master is None or not calendar.isRecurring():
</span><span class="cx">             # When there is no master we have a set of overridden components - index them all.
</span><span class="cx">             # When there is one instance - index it.
</span><del>-            expand = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            expand = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">             doInstanceIndexing = True
</span><span class="cx">         else:
</span><span class="cx">             # If migrating or re-creating or config option for delayed indexing is off, always index
</span><span class="lines">@@ -682,8 +682,8 @@
</span><span class="cx">             # by default.  This is a caching parameter which affects the size of the index;
</span><span class="cx">             # it does not affect search results beyond this period, but it may affect
</span><span class="cx">             # performance of such a search.
</span><del>-            expand = (PyCalendarDateTime.getToday() +
-                      PyCalendarDuration(days=config.FreeBusyIndexExpandAheadDays))
</del><ins>+            expand = (DateTime.getToday() +
+                      Duration(days=config.FreeBusyIndexExpandAheadDays))
</ins><span class="cx"> 
</span><span class="cx">             if expand_until and expand_until &gt; expand:
</span><span class="cx">                 expand = expand_until
</span><span class="lines">@@ -700,8 +700,8 @@
</span><span class="cx">             # occurrences into some obscenely far-in-the-future date, so we cap the caching
</span><span class="cx">             # period.  Searches beyond this period will always be relatively expensive for
</span><span class="cx">             # resources with occurrences beyond this period.
</span><del>-            if expand &gt; (PyCalendarDateTime.getToday() +
-                         PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
</del><ins>+            if expand &gt; (DateTime.getToday() +
+                         Duration(days=config.FreeBusyIndexExpandMaxDays)):
</ins><span class="cx">                 raise IndexedSearchException()
</span><span class="cx"> 
</span><span class="cx">         # Always do recurrence expansion even if we do not intend to index - we need this to double-check the
</span><span class="lines">@@ -716,7 +716,7 @@
</span><span class="cx">         # Now coerce indexing to off if needed
</span><span class="cx">         if not doInstanceIndexing:
</span><span class="cx">             instances = None
</span><del>-            recurrenceLimit = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            recurrenceLimit = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx"> 
</span><span class="cx">         self._delete_from_db(name, uid, False)
</span><span class="cx"> 
</span><span class="lines">@@ -782,8 +782,8 @@
</span><span class="cx">             # Special - for unbounded recurrence we insert a value for &quot;infinity&quot;
</span><span class="cx">             # that will allow an open-ended time-range to always match it.
</span><span class="cx">             if calendar.isRecurringUnbounded():
</span><del>-                start = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-                end = PyCalendarDateTime(2100, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+                start = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+                end = DateTime(2100, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">                 float = 'N'
</span><span class="cx">                 self._db_execute(
</span><span class="cx">                     &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingcaldavtesttest_schedulerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="cx"> 
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.now = DateTime.getNowUTC()
</ins><span class="cx">         self.now.setHHMMSS(0, 0, 0)
</span><span class="cx"> 
</span><span class="cx">         self.now_12H = self.now.duplicate()
</span><span class="lines">@@ -170,9 +170,9 @@
</span><span class="cx">         scheduler = CalDAVScheduler(self.transactionUnderTest(), &quot;user01&quot;)
</span><span class="cx">         result = (yield scheduler.doSchedulingViaPOST(&quot;mailto:user01@example.com&quot;, [&quot;mailto:user01@example.com&quot;, ], Component.fromString(data_request)))
</span><span class="cx">         self.assertEqual(len(result.responses), 1)
</span><del>-        self.assertEqual(str(result.responses[0].children[0].children[0]), &quot;mailto:user01@example.com&quot;)
-        self.assertTrue(str(result.responses[0].children[1]).startswith(&quot;2&quot;))
-        self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</del><ins>+        self.assertEqual(str(result.responses[0].recipient.children[0]), &quot;mailto:user01@example.com&quot;)
+        self.assertTrue(str(result.responses[0].reqstatus).startswith(&quot;2&quot;))
+        self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -227,9 +227,9 @@
</span><span class="cx">         scheduler = CalDAVScheduler(self.transactionUnderTest(), &quot;user01&quot;)
</span><span class="cx">         result = (yield scheduler.doSchedulingViaPOST(&quot;mailto:user01@example.com&quot;, [&quot;mailto:user01@example.com&quot;, ], Component.fromString(data_request)))
</span><span class="cx">         self.assertEqual(len(result.responses), 1)
</span><del>-        self.assertEqual(str(result.responses[0].children[0].children[0]), &quot;mailto:user01@example.com&quot;)
-        self.assertTrue(str(result.responses[0].children[1]).startswith(&quot;2&quot;))
-        self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</del><ins>+        self.assertEqual(str(result.responses[0].recipient.children[0]), &quot;mailto:user01@example.com&quot;)
+        self.assertTrue(str(result.responses[0].reqstatus).startswith(&quot;2&quot;))
+        self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -294,6 +294,6 @@
</span><span class="cx">         scheduler = CalDAVScheduler(self.transactionUnderTest(), &quot;user01&quot;)
</span><span class="cx">         result = (yield scheduler.doSchedulingViaPOST(&quot;mailto:user01@example.com&quot;, [&quot;mailto:user01@example.com&quot;, ], Component.fromString(data_request)))
</span><span class="cx">         self.assertEqual(len(result.responses), 1)
</span><del>-        self.assertEqual(str(result.responses[0].children[0].children[0]), &quot;mailto:user01@example.com&quot;)
-        self.assertTrue(str(result.responses[0].children[1]).startswith(&quot;2&quot;))
-        self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</del><ins>+        self.assertEqual(str(result.responses[0].recipient.children[0]), &quot;mailto:user01@example.com&quot;)
+        self.assertTrue(str(result.responses[0].reqstatus).startswith(&quot;2&quot;))
+        self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingfreebusypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,10 +14,10 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.period import Period
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> 
</span><span class="lines">@@ -68,8 +68,8 @@
</span><span class="cx">         if entry:
</span><span class="cx"> 
</span><span class="cx">             # Offset one day at either end to account for floating
</span><del>-            cached_start = entry.timerange.start + PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
-            cached_end = entry.timerange.end - PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
</del><ins>+            cached_start = entry.timerange.start + Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_end = entry.timerange.end - Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
</ins><span class="cx"> 
</span><span class="cx">             # Verify that the requested time range lies within the cache time range
</span><span class="cx">             if compareDateTime(timerange.end, cached_end) &lt;= 0 and compareDateTime(timerange.start, cached_start) &gt;= 0:
</span><span class="lines">@@ -187,8 +187,8 @@
</span><span class="cx">                 logItems[&quot;fb-uncached&quot;] = logItems.get(&quot;fb-uncached&quot;, 0) + 1
</span><span class="cx"> 
</span><span class="cx">             # We want to cache a large range of time based on the current date
</span><del>-            cache_start = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=0 - config.FreeBusyCacheDaysBack))
-            cache_end = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=config.FreeBusyCacheDaysForward))
</del><ins>+            cache_start = normalizeToUTC(DateTime.getToday() + Duration(days=0 - config.FreeBusyCacheDaysBack))
+            cache_end = normalizeToUTC(DateTime.getToday() + Duration(days=config.FreeBusyCacheDaysForward))
</ins><span class="cx"> 
</span><span class="cx">             # If the requested time range would fit in our allowed cache range, trigger the cache creation
</span><span class="cx">             if compareDateTime(timerange.start, cache_start) &gt;= 0 and compareDateTime(timerange.end, cache_end) &lt;= 0:
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx">             logItems[&quot;fb-cached&quot;] = logItems.get(&quot;fb-cached&quot;, 0) + 1
</span><span class="cx"> 
</span><span class="cx">         # Determine appropriate timezone (UTC is the default)
</span><del>-        tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
</del><ins>+        tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
</ins><span class="cx"> 
</span><span class="cx">     # We care about separate instances for VEVENTs only
</span><span class="cx">     aggregated_resources = {}
</span><span class="lines">@@ -270,15 +270,15 @@
</span><span class="cx">                 if float == 'Y':
</span><span class="cx">                     fbstart.setTimezone(tzinfo)
</span><span class="cx">                 else:
</span><del>-                    fbstart.setTimezone(PyCalendarTimezone(utc=True))
</del><ins>+                    fbstart.setTimezone(Timezone(utc=True))
</ins><span class="cx">                 fbend = parseSQLTimestampToPyCalendar(end)
</span><span class="cx">                 if float == 'Y':
</span><span class="cx">                     fbend.setTimezone(tzinfo)
</span><span class="cx">                 else:
</span><del>-                    fbend.setTimezone(PyCalendarTimezone(utc=True))
</del><ins>+                    fbend.setTimezone(Timezone(utc=True))
</ins><span class="cx"> 
</span><span class="cx">                 # Clip instance to time range
</span><del>-                clipped = clipPeriod(PyCalendarPeriod(fbstart, duration=fbend - fbstart), PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                clipped = clipPeriod(Period(fbstart, duration=fbend - fbstart), Period(timerange.start, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">                 # Double check for overlap
</span><span class="cx">                 if clipped:
</span><span class="lines">@@ -364,7 +364,7 @@
</span><span class="cx">     @param timerange: the time-range in which to expand
</span><span class="cx">     @type timerange: L{TimeRange}
</span><span class="cx">     @param tzinfo: timezone for floating time calculations
</span><del>-    @type tzinfo: L{PyCalendarTimezone}
</del><ins>+    @type tzinfo: L{Timezone}
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     # First expand the component
</span><span class="lines">@@ -404,7 +404,7 @@
</span><span class="cx">     @param calendar: the L{Component} that is the VCALENDAR containing the VEVENT's.
</span><span class="cx">     @param fbinfo: the tuple used to store the three types of fb data.
</span><span class="cx">     @param timerange: the time range to restrict free busy data to.
</span><del>-    @param tzinfo: the L{PyCalendarTimezone} for the timezone to use for floating/all-day events.
</del><ins>+    @param tzinfo: the L{Timezone} for the timezone to use for floating/all-day events.
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     # Expand out the set of instances for the event with in the required range
</span><span class="lines">@@ -449,10 +449,10 @@
</span><span class="cx">         # Clip period for this instance - use duration for period end if that
</span><span class="cx">         # is what original component used
</span><span class="cx">         if instance.component.hasProperty(&quot;DURATION&quot;):
</span><del>-            period = PyCalendarPeriod(fbstart, duration=fbend - fbstart)
</del><ins>+            period = Period(fbstart, duration=fbend - fbstart)
</ins><span class="cx">         else:
</span><del>-            period = PyCalendarPeriod(fbstart, fbend)
-        clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+            period = Period(fbstart, fbend)
+        clipped = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">         # Double check for overlap
</span><span class="cx">         if clipped:
</span><span class="lines">@@ -490,7 +490,7 @@
</span><span class="cx">             assert isinstance(fb.value(), list), &quot;FREEBUSY property does not contain a list of values: %r&quot; % (fb,)
</span><span class="cx">             for period in fb.value():
</span><span class="cx">                 # Clip period for this instance
</span><del>-                clipped = clipPeriod(period.getValue(), PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                clipped = clipPeriod(period.getValue(), Period(timerange.start, timerange.end))
</ins><span class="cx">                 if clipped:
</span><span class="cx">                     fbinfo[fbtype_mapper.get(fbtype, 0)].append(clipped)
</span><span class="cx"> 
</span><span class="lines">@@ -509,12 +509,12 @@
</span><span class="cx">         # Get overall start/end
</span><span class="cx">         start = vav.getStartDateUTC()
</span><span class="cx">         if start is None:
</span><del>-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         end = vav.getEndDateUTC()
</span><span class="cx">         if end is None:
</span><del>-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        period = PyCalendarPeriod(start, end)
-        overall = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        period = Period(start, end)
+        overall = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx">         if overall is None:
</span><span class="cx">             continue
</span><span class="cx"> 
</span><span class="lines">@@ -526,10 +526,10 @@
</span><span class="cx">         last_end = timerange.start
</span><span class="cx">         for period in periods:
</span><span class="cx">             if last_end &lt; period.getStart():
</span><del>-                busyperiods.append(PyCalendarPeriod(last_end, period.getStart()))
</del><ins>+                busyperiods.append(Period(last_end, period.getStart()))
</ins><span class="cx">             last_end = period.getEnd()
</span><span class="cx">         if last_end &lt; timerange.end:
</span><del>-            busyperiods.append(PyCalendarPeriod(last_end, timerange.end))
</del><ins>+            busyperiods.append(Period(last_end, timerange.end))
</ins><span class="cx"> 
</span><span class="cx">         # Add to actual results mapped by busy type
</span><span class="cx">         fbtype = vav.propertyValue(&quot;BUSYTYPE&quot;)
</span><span class="lines">@@ -576,10 +576,10 @@
</span><span class="cx">             # Clip period for this instance - use duration for period end if that
</span><span class="cx">             # is what original component used
</span><span class="cx">             if instance.component.hasProperty(&quot;DURATION&quot;):
</span><del>-                period = PyCalendarPeriod(start, duration=end - start)
</del><ins>+                period = Period(start, duration=end - start)
</ins><span class="cx">             else:
</span><del>-                period = PyCalendarPeriod(start, end)
-            clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
</del><ins>+                period = Period(start, end)
+            clipped = clipPeriod(period, Period(timerange.start, timerange.end))
</ins><span class="cx">             if clipped:
</span><span class="cx">                 periods.append(clipped)
</span><span class="cx"> 
</span><span class="lines">@@ -622,7 +622,7 @@
</span><span class="cx">         fb.addProperty(attendee)
</span><span class="cx">     fb.addProperty(Property(&quot;DTSTART&quot;, timerange.start))
</span><span class="cx">     fb.addProperty(Property(&quot;DTEND&quot;, timerange.end))
</span><del>-    fb.addProperty(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+    fb.addProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx">     if len(fbinfo[0]) != 0:
</span><span class="cx">         fb.addProperty(Property(&quot;FREEBUSY&quot;, fbinfo[0], {&quot;FBTYPE&quot;: &quot;BUSY&quot;}))
</span><span class="cx">     if len(fbinfo[1]) != 0:
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingicaldiffpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,8 +16,8 @@
</span><span class="cx"> 
</span><span class="cx"> from difflib import unified_diff
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.period import PyCalendarPeriod
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.period import Period
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> 
</span><span class="lines">@@ -484,7 +484,7 @@
</span><span class="cx"> 
</span><span class="cx">             # If PARTSTAT was changed by the attendee, add a timestamp if needed
</span><span class="cx">             if config.Scheduling.Options.TimestampAttendeePartStatChanges:
</span><del>-                serverAttendee.setParameter(&quot;X-CALENDARSERVER-DTSTAMP&quot;, PyCalendarDateTime.getNowUTC().getText())
</del><ins>+                serverAttendee.setParameter(&quot;X-CALENDARSERVER-DTSTAMP&quot;, DateTime.getNowUTC().getText())
</ins><span class="cx"> 
</span><span class="cx">             replyNeeded = True
</span><span class="cx"> 
</span><span class="lines">@@ -516,6 +516,10 @@
</span><span class="cx">             if comp.name() == &quot;VALARM&quot;:
</span><span class="cx">                 serverComponent.addComponent(comp)
</span><span class="cx"> 
</span><ins>+        # VPOLL
+        if serverComponent.name() == &quot;VPOLL&quot;:
+            replyNeeded = self._transferVPOLLData(serverComponent, clientComponent)
+
</ins><span class="cx">         return True, replyNeeded
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -556,6 +560,44 @@
</span><span class="cx">             return True
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def _transferVPOLLData(self, serverComponent, clientComponent):
+
+        changed = False
+
+        # Get the VOTER properties in sub-components of the VPOLL as set by the attendee
+        poll_items = {}
+        for component in clientComponent.subcomponents():
+            poll_id = component.propertyValue(&quot;POLL-ITEM-ID&quot;)
+            if poll_id is not None:
+                poll_items[poll_id] = component.getVoterProperty((self.attendee,))
+
+        # Transfer attendee data with the master set
+        for component in serverComponent.subcomponents():
+            poll_id = component.propertyValue(&quot;POLL-ITEM-ID&quot;)
+            if poll_id is not None:
+                voter = component.getVoterProperty((self.attendee,))
+                attendee_voter = poll_items.get(poll_id)
+                if attendee_voter is None:
+                    if voter is not None:
+                        component.removeProperty(voter)
+                        changed = True
+                elif voter is None:
+                    component.addProperty(attendee_voter)
+                    changed = True
+                else:
+                    for paramname in (&quot;RESPONSE&quot;,):
+                        paramvalue = attendee_voter.parameterValue(paramname)
+                        if paramvalue is None:
+                            voter.removeParameter(paramname)
+                            changed = True
+                        else:
+                            if paramvalue != voter.parameterValue(paramname):
+                                voter.setParameter(paramname, paramvalue)
+                                changed = True
+
+        return changed
+
+
</ins><span class="cx">     def _checkInvalidChanges(self, serverComponent, clientComponent, declines):
</span><span class="cx"> 
</span><span class="cx">         # Properties we care about: DTSTART, DTEND, DURATION, RRULE, RDATE, EXDATE
</span><span class="lines">@@ -585,12 +627,12 @@
</span><span class="cx">     def _getNormalizedDateTimeProperties(self, component):
</span><span class="cx"> 
</span><span class="cx">         # Basic time properties
</span><del>-        if component.name() in (&quot;VEVENT&quot;, &quot;VJOURNAL&quot;,):
</del><ins>+        if component.name() in (&quot;VEVENT&quot;, &quot;VJOURNAL&quot;, &quot;VPOLL&quot;):
</ins><span class="cx">             dtstart = component.getProperty(&quot;DTSTART&quot;)
</span><span class="cx">             dtend = component.getProperty(&quot;DTEND&quot;)
</span><span class="cx">             duration = component.getProperty(&quot;DURATION&quot;)
</span><span class="cx"> 
</span><del>-            timeRange = PyCalendarPeriod(
</del><ins>+            timeRange = Period(
</ins><span class="cx">                 start=dtstart.value()  if dtstart  is not None else None,
</span><span class="cx">                 end=dtend.value()    if dtend    is not None else None,
</span><span class="cx">                 duration=duration.value() if duration is not None else None,
</span><span class="lines">@@ -602,16 +644,19 @@
</span><span class="cx">             duration = component.getProperty(&quot;DURATION&quot;)
</span><span class="cx"> 
</span><span class="cx">             if dtstart or duration:
</span><del>-                timeRange = PyCalendarPeriod(
</del><ins>+                timeRange = Period(
</ins><span class="cx">                     start=dtstart.value()  if dtstart  is not None else None,
</span><span class="cx">                     duration=duration.value() if duration is not None else None,
</span><span class="cx">                 )
</span><span class="cx">             else:
</span><del>-                timeRange = PyCalendarPeriod()
</del><ins>+                timeRange = Period()
</ins><span class="cx"> 
</span><span class="cx">             newdue = component.getProperty(&quot;DUE&quot;)
</span><span class="cx">             if newdue is not None:
</span><span class="cx">                 newdue = newdue.value().duplicate().adjustToUTC()
</span><ins>+        else:
+            timeRange = Period()
+            newdue = None
</ins><span class="cx"> 
</span><span class="cx">         # Recurrence rules - we need to normalize the order of the value parts
</span><span class="cx">         newrrules = set()
</span><span class="lines">@@ -627,7 +672,7 @@
</span><span class="cx">         rdates = component.properties(&quot;RDATE&quot;)
</span><span class="cx">         for rdate in rdates:
</span><span class="cx">             for value in rdate.value():
</span><del>-                if isinstance(value, PyCalendarDateTime):
</del><ins>+                if isinstance(value, DateTime):
</ins><span class="cx">                     value = value.duplicate().adjustToUTC()
</span><span class="cx">                 newrdates.add(value)
</span><span class="cx"> 
</span><span class="lines">@@ -734,6 +779,7 @@
</span><span class="cx">         comp.normalizePropertyValueLists(&quot;EXDATE&quot;)
</span><span class="cx">         comp.removePropertyParameters(&quot;ORGANIZER&quot;, (&quot;SCHEDULE-STATUS&quot;,))
</span><span class="cx">         comp.removePropertyParameters(&quot;ATTENDEE&quot;, (&quot;SCHEDULE-STATUS&quot;, &quot;SCHEDULE-FORCE-SEND&quot;,))
</span><ins>+        comp.removePropertyParameters(&quot;VOTER&quot;, (&quot;SCHEDULE-STATUS&quot;, &quot;SCHEDULE-FORCE-SEND&quot;,))
</ins><span class="cx">         comp.removeAlarms()
</span><span class="cx">         comp.normalizeAll()
</span><span class="cx">         comp.normalizeAttachments()
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingicalsplitterpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twistedcaldav.ical import Property
</span><span class="cx"> 
</span><span class="lines">@@ -34,10 +34,10 @@
</span><span class="cx"> 
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         self.threshold = threshold
</span><del>-        self.past = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.past = DateTime.getNowUTC()
</ins><span class="cx">         self.past.setHHMMSS(0, 0, 0)
</span><span class="cx">         self.past.offsetDay(-past)
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.now = DateTime.getNowUTC()
</ins><span class="cx">         self.now.setHHMMSS(0, 0, 0)
</span><span class="cx">         self.now.offsetDay(-1)
</span><span class="cx"> 
</span><span class="lines">@@ -91,7 +91,7 @@
</span><span class="cx">         @type ical: L{Component}
</span><span class="cx"> 
</span><span class="cx">         @return: recurrence-id of the split
</span><del>-        @rtype: L{PyCalendarDateTime}
</del><ins>+        @rtype: L{DateTime}
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Find the instance RECURRENCE-ID where a split is going to happen
</span><span class="lines">@@ -124,7 +124,7 @@
</span><span class="cx">         @type ical: L{Component}
</span><span class="cx"> 
</span><span class="cx">         @param rid: recurrence-id where the split should occur, or C{None} to determine it here
</span><del>-        @type rid: L{PyCalendarDateTime} or C{None}
</del><ins>+        @type rid: L{DateTime} or C{None}
</ins><span class="cx"> 
</span><span class="cx">         @param olderUID: UID to use for the split off component, or C{None} to generate one here
</span><span class="cx">         @type olderUID: C{str} or C{None}
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingimipoutboundpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -26,8 +26,8 @@
</span><span class="cx"> from email.mime.multipart import MIMEMultipart
</span><span class="cx"> from email.mime.text import MIMEText
</span><span class="cx"> import email.utils
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
</ins><span class="cx"> from twext.enterprise.dal.record import fromTable
</span><span class="cx"> from twext.enterprise.queue import WorkItem
</span><span class="cx"> from twext.python.log import Logger
</span><span class="lines">@@ -320,8 +320,8 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if onlyAfter is None:
</span><del>-            duration = PyCalendarDuration(days=self.suppressionDays)
-            onlyAfter = PyCalendarDateTime.getNowUTC() - duration
</del><ins>+            duration = Duration(days=self.suppressionDays)
+            onlyAfter = DateTime.getNowUTC() - duration
</ins><span class="cx"> 
</span><span class="cx">         icaluid = calendar.resourceUID()
</span><span class="cx">         method = calendar.propertyValue(&quot;METHOD&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_deliverypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">         yield delivery.generateSchedulingResponses()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(len(responses.responses), 1)
</span><del>-        self.assertEqual(str(responses.responses[0].children[1]), iTIPRequestStatus.SERVICE_UNAVAILABLE)
</del><ins>+        self.assertEqual(str(responses.responses[0].reqstatus), iTIPRequestStatus.SERVICE_UNAVAILABLE)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_inboundpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -300,7 +300,7 @@
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         self.assertEquals(
</span><span class="cx">             &quot;1.2;Scheduling message has been delivered&quot;,
</span><del>-            result.responses[0].children[1].toString()
</del><ins>+            result.responses[0].reqstatus.toString()
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -333,7 +333,7 @@
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         self.assertEquals(
</span><span class="cx">             &quot;3.7;Invalid Calendar User&quot;,
</span><del>-            result.responses[0].children[1].toString()
</del><ins>+            result.responses[0].reqstatus.toString()
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingimiptesttest_outboundpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx"> 
</span><span class="cx"> from cStringIO import StringIO
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, succeed
</span><span class="cx"> from twisted.trial import unittest
</span><span class="lines">@@ -275,7 +275,7 @@
</span><span class="cx">                 inputOriginator,
</span><span class="cx">                 inputRecipient,
</span><span class="cx">                 Component.fromString(inputCalendar.replace(&quot;\n&quot;, &quot;\r\n&quot;)),
</span><del>-                onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0)
</del><ins>+                onlyAfter=DateTime(2010, 1, 1, 0, 0, 0)
</ins><span class="cx">             )
</span><span class="cx">             yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -319,7 +319,7 @@
</span><span class="cx">                 inputOriginator,
</span><span class="cx">                 inputRecipient,
</span><span class="cx">                 Component.fromString(inputCalendar.replace(&quot;\n&quot;, &quot;\r\n&quot;)),
</span><del>-                onlyAfter=PyCalendarDateTime(2021, 1, 1, 0, 0, 0)
</del><ins>+                onlyAfter=DateTime(2021, 1, 1, 0, 0, 0)
</ins><span class="cx">             )
</span><span class="cx">             yield txn.commit()
</span><span class="cx">             self.assertFalse(self.sender.smtpSender.sendMessageCalled)
</span><span class="lines">@@ -381,7 +381,7 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         yield self.sender.outbound(txn, inputOriginator, inputRecipient,
</span><span class="cx">             Component.fromString(inputCalendar.replace(&quot;\n&quot;, &quot;\r\n&quot;)),
</span><del>-            onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0))
</del><ins>+            onlyAfter=DateTime(2010, 1, 1, 0, 0, 0))
</ins><span class="cx"> 
</span><span class="cx">         # Verify we didn't create a new token...
</span><span class="cx">         txn = self.store.newTransaction()
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingimplicitpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -21,7 +21,6 @@
</span><span class="cx"> from twext.web2 import responsecode
</span><span class="cx"> from twext.web2.http import HTTPError
</span><span class="cx"> 
</span><del>-from twistedcaldav import caldavxml
</del><span class="cx"> from twistedcaldav.caldavxml import caldav_namespace
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.ical import Property
</span><span class="lines">@@ -1047,17 +1046,17 @@
</span><span class="cx"> 
</span><span class="cx">         # Map each recipient in the response to a status code
</span><span class="cx">         responses = {}
</span><ins>+        propname = self.calendar.mainComponent().recipientPropertyName() if is_organizer else &quot;ORGANIZER&quot;
</ins><span class="cx">         for item in response.responses:
</span><del>-            assert isinstance(item, caldavxml.Response), &quot;Wrong element in response&quot;
-            recipient = str(item.children[0].children[0])
-            status = str(item.children[1])
</del><ins>+            recipient = str(item.recipient.children[0])
+            status = str(item.reqstatus)
</ins><span class="cx">             responses[recipient] = status
</span><span class="cx"> 
</span><span class="cx">             # Now apply to each ATTENDEE/ORGANIZER in the original data
</span><span class="cx">             self.calendar.setParameterToValueForPropertyWithValue(
</span><span class="cx">                 &quot;SCHEDULE-STATUS&quot;,
</span><span class="cx">                 status.split(&quot;;&quot;)[0],
</span><del>-                &quot;ATTENDEE&quot; if is_organizer else &quot;ORGANIZER&quot;,
</del><ins>+                propname,
</ins><span class="cx">                 recipient)
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingischeduleresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,8 +14,8 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.web2 import responsecode
</span><span class="cx"> from twext.web2.dav.http import ErrorResponse
</span><span class="lines">@@ -158,12 +158,26 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Determine min/max date-time for iSchedule
</span><del>-        now = PyCalendarDateTime.getNowUTC()
-        minDateTime = PyCalendarDateTime(now.getYear(), 1, 1, 0, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+        now = DateTime.getNowUTC()
+        minDateTime = DateTime(now.getYear(), 1, 1, 0, 0, 0, Timezone(utc=True))
</ins><span class="cx">         minDateTime.offsetYear(-1)
</span><del>-        maxDateTime = PyCalendarDateTime(now.getYear(), 1, 1, 0, 0, 0, PyCalendarTimezone(utc=True))
</del><ins>+        maxDateTime = DateTime(now.getYear(), 1, 1, 0, 0, 0, Timezone(utc=True))
</ins><span class="cx">         maxDateTime.offsetYear(10)
</span><span class="cx"> 
</span><ins>+        dataTypes = []
+        dataTypes.append(
+            ischedulexml.CalendarDataType(**{
+                &quot;content-type&quot;: &quot;text/calendar&quot;,
+                &quot;version&quot;: &quot;2.0&quot;,
+            })
+        )
+        if config.EnableJSONData:
+            dataTypes.append(
+                ischedulexml.CalendarDataType(**{
+                    &quot;content-type&quot;: &quot;application/calendar+json&quot;,
+                    &quot;version&quot;: &quot;2.0&quot;,
+                })
+            )
</ins><span class="cx">         result = ischedulexml.QueryResult(
</span><span class="cx"> 
</span><span class="cx">             ischedulexml.Capabilities(
</span><span class="lines">@@ -189,12 +203,7 @@
</span><span class="cx">                         name=&quot;VFREEBUSY&quot;
</span><span class="cx">                     ),
</span><span class="cx">                 ),
</span><del>-                ischedulexml.CalendarDataTypes(
-                    ischedulexml.CalendarDataType(**{
-                            &quot;content-type&quot;: &quot;text/calendar&quot;,
-                            &quot;version&quot;: &quot;2.0&quot;,
-                    }),
-                ),
</del><ins>+                ischedulexml.CalendarDataTypes(*dataTypes),
</ins><span class="cx">                 ischedulexml.Attachments(
</span><span class="cx">                     ischedulexml.External(),
</span><span class="cx">                 ),
</span><span class="lines">@@ -223,25 +232,49 @@
</span><span class="cx">         # This is a server-to-server scheduling operation.
</span><span class="cx">         scheduler = IScheduleScheduler(txn, None, podding=self._podding)
</span><span class="cx"> 
</span><ins>+        # Check content first
+        contentType = request.headers.getHeader(&quot;content-type&quot;)
+        format = self.determineType(contentType)
+
+        if format is None:
+            msg = &quot;MIME type %s not allowed in iSchedule request&quot; % (contentType,)
+            self.log.error(msg)
+            raise HTTPError(scheduler.errorResponse(
+                responsecode.FORBIDDEN,
+                (ischedule_namespace, &quot;invalid-calendar-data-type&quot;),
+                msg,
+            ))
+
</ins><span class="cx">         originator = self.loadOriginatorFromRequestHeaders(request)
</span><span class="cx">         recipients = self.loadRecipientsFromRequestHeaders(request)
</span><span class="cx">         body = (yield allDataFromStream(request.stream))
</span><ins>+        calendar = Component.fromString(body, format=format)
</ins><span class="cx"> 
</span><span class="cx">         # Do the POST processing treating this as a non-local schedule
</span><span class="cx">         try:
</span><del>-            result = (yield scheduler.doSchedulingViaPOST(request.remoteAddr, request.headers, body, originator, recipients))
</del><ins>+            result = (yield scheduler.doSchedulingViaPOST(request.remoteAddr, request.headers, body, calendar, originator, recipients))
</ins><span class="cx">         except Exception:
</span><span class="cx">             ex = Failure()
</span><span class="cx">             yield txn.abort()
</span><span class="cx">             ex.raiseException()
</span><span class="cx">         else:
</span><span class="cx">             yield txn.commit()
</span><del>-        response = result.response()
</del><ins>+        response = result.response(format=format)
</ins><span class="cx">         if not self._podding:
</span><span class="cx">             response.headers.addRawHeader(ISCHEDULE_CAPABILITIES, str(config.Scheduling.iSchedule.SerialNumber))
</span><span class="cx">         returnValue(response)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def determineType(self, content_type):
+        &quot;&quot;&quot;
+        Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+        &quot;&quot;&quot;
+        format = None
+        if content_type is not None:
+            format = &quot;%s/%s&quot; % (content_type.mediaType, content_type.mediaSubtype,)
+        return format if format in Component.allowedTypes() else None
+
+
</ins><span class="cx">     def loadOriginatorFromRequestHeaders(self, request):
</span><span class="cx">         # Must have Originator header
</span><span class="cx">         originator = request.headers.getRawHeaders(&quot;originator&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingischeduleschedulerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.config import config
</span><del>-from twistedcaldav.ical import normalizeCUAddress, Component
</del><ins>+from twistedcaldav.ical import normalizeCUAddress
</ins><span class="cx"> 
</span><span class="cx"> from txdav.caldav.datastore.scheduling import addressmapping
</span><span class="cx"> from txdav.caldav.datastore.scheduling.cuaddress import RemoteCalendarUser
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def doSchedulingViaPOST(self, remoteAddr, headers, body, originator, recipients):
</del><ins>+    def doSchedulingViaPOST(self, remoteAddr, headers, body, calendar, originator, recipients):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Carry out iSchedule specific processing.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -180,8 +180,6 @@
</span><span class="cx">                     msg,
</span><span class="cx">                 ))
</span><span class="cx"> 
</span><del>-        calendar = Component.fromString(body)
-
</del><span class="cx">         if self._podding and self.headers.getRawHeaders('x-calendarserver-itip-refreshonly', (&quot;F&quot;))[0] == &quot;T&quot;:
</span><span class="cx">             self.txn.doing_attendee_refresh = 1
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingischeduletesttest_resourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx">             headers=http_headers.Headers(rawHeaders={
</span><span class="cx">                 &quot;Originator&quot;: (&quot;mailto:wsanchez@example.com&quot;,),
</span><span class="cx">                 &quot;Recipient&quot;: (&quot;mailto:cdaboo@example.com&quot;,),
</span><ins>+                &quot;Content-Type&quot;: &quot;text/calendar&quot;,
</ins><span class="cx">             }),
</span><span class="cx">             content=&quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="lines">@@ -144,6 +145,7 @@
</span><span class="cx">             headers=http_headers.Headers(rawHeaders={
</span><span class="cx">                 &quot;Originator&quot;: (&quot;mailto:user01@example.org&quot;,),
</span><span class="cx">                 &quot;Recipient&quot;: (&quot;mailto:user02@example.com&quot;,),
</span><ins>+                &quot;Content-Type&quot;: (&quot;text/calendar&quot;,)
</ins><span class="cx">             }),
</span><span class="cx">             content=&quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> CALSCALE:GREGORIAN
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingitippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -33,7 +33,7 @@
</span><span class="cx"> from twistedcaldav.ical import Property, iCalendarProductID, Component, \
</span><span class="cx">     ignoredComponents
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -402,9 +402,14 @@
</span><span class="cx">     @staticmethod
</span><span class="cx">     def updateAttendeeData(from_component, to_component):
</span><span class="cx">         &quot;&quot;&quot;
</span><ins>+        Called when processing a REPLY only.
+
</ins><span class="cx">         Copy the PARTSTAT of the Attendee in the from_component to the matching ATTENDEE
</span><span class="cx">         in the to_component. Ignore if no match found. Also update the private comments.
</span><span class="cx"> 
</span><ins>+        For VPOLL we need to copy POLL-ITEM-ID response values into the actual matching
+        polled sub-components as VOTER properties.
+
</ins><span class="cx">         @param from_component: component to copy from
</span><span class="cx">         @type from_component: L{Component}
</span><span class="cx">         @param to_component: component to copy to
</span><span class="lines">@@ -423,7 +428,7 @@
</span><span class="cx">             reqstatus = &quot;2.0&quot;
</span><span class="cx"> 
</span><span class="cx">         # Get attendee in from_component - there MUST be only one
</span><del>-        attendees = tuple(from_component.properties(&quot;ATTENDEE&quot;))
</del><ins>+        attendees = tuple(from_component.properties(from_component.recipientPropertyName()))
</ins><span class="cx">         if len(attendees) != 1:
</span><span class="cx">             log.error(&quot;There must be one and only one ATTENDEE property in a REPLY\n%s&quot; % (str(from_component),))
</span><span class="cx">             return None, False, False
</span><span class="lines">@@ -484,7 +489,7 @@
</span><span class="cx">                     attendee_comment.value(),
</span><span class="cx">                     params={
</span><span class="cx">                         &quot;X-CALENDARSERVER-ATTENDEE-REF&quot;: attendee.value(),
</span><del>-                        &quot;X-CALENDARSERVER-DTSTAMP&quot;: PyCalendarDateTime.getNowUTC().getText(),
</del><ins>+                        &quot;X-CALENDARSERVER-DTSTAMP&quot;: DateTime.getNowUTC().getText(),
</ins><span class="cx">                     }
</span><span class="cx">                 )
</span><span class="cx">                 to_component.addProperty(private_comment)
</span><span class="lines">@@ -499,17 +504,60 @@
</span><span class="cx"> 
</span><span class="cx">                     # Add default parameters
</span><span class="cx">                     private_comment.setParameter(&quot;X-CALENDARSERVER-ATTENDEE-REF&quot;, attendee.value())
</span><del>-                    private_comment.setParameter(&quot;X-CALENDARSERVER-DTSTAMP&quot;, PyCalendarDateTime.getNowUTC().getText())
</del><ins>+                    private_comment.setParameter(&quot;X-CALENDARSERVER-DTSTAMP&quot;, DateTime.getNowUTC().getText())
</ins><span class="cx"> 
</span><span class="cx">                     # Set new value
</span><span class="cx">                     private_comment.setValue(attendee_comment.value())
</span><span class="cx"> 
</span><span class="cx">                     private_comment_changed = True
</span><span class="cx"> 
</span><ins>+            # Do VPOLL transfer
+            if from_component.name() == &quot;VPOLL&quot;:
+                # TODO: figure out how to report changes back
+                iTipProcessing.updateVPOLLData(from_component, to_component, attendee)
+
</ins><span class="cx">         return attendee.value(), partstat_changed, private_comment_changed
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><ins>+    def updateVPOLLData(from_component, to_component, attendee):
+        &quot;&quot;&quot;
+        Update VPOLL sub-components with voter's response.
+
+        @param from_component: component to copy from
+        @type from_component: L{Component}
+        @param to_component: component to copy to
+        @type to_component: L{Component}
+        @param attendee: attendee being processed
+        @type attendee: L{Property}
+        &quot;&quot;&quot;
+
+        responses = {}
+        for prop in from_component.properties(&quot;POLL-ITEM-ID&quot;):
+            responses[prop.value()] = prop
+
+        for component in to_component.subcomponents():
+            if component.name() in ignoredComponents:
+                continue
+            poll_item_id = component.propertyValue(&quot;POLL-ITEM-ID&quot;)
+            if poll_item_id is None:
+                continue
+            voter = component.getVoterProperty((attendee.value(),))
+
+            # If no response - remove
+            if poll_item_id not in responses or not responses[poll_item_id].hasParameter(&quot;RESPONSE&quot;):
+                if voter is not None:
+                    component.removeProperty(voter)
+                continue
+
+            # Add or update voter
+            if voter is None:
+                voter = Property(&quot;VOTER&quot;, attendee.value())
+                component.addProperty(voter)
+            voter.setParameter(&quot;RESPONSE&quot;, responses[poll_item_id].parameterValue(&quot;RESPONSE&quot;))
+
+
+    @staticmethod
</ins><span class="cx">     def transferItems(from_calendar, to_component, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, other_props, recipient, remove_matched=False):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Transfer properties from a calendar to a component by first trying to match the component in the original calendar and
</span><span class="lines">@@ -847,7 +895,7 @@
</span><span class="cx">         itip.filterComponents(changedRids)
</span><span class="cx"> 
</span><span class="cx">         # Force update to DTSTAMP everywhere so reply sequencing will work
</span><del>-        itip.replacePropertyInAllComponents(Property(&quot;DTSTAMP&quot;, PyCalendarDateTime.getNowUTC()))
</del><ins>+        itip.replacePropertyInAllComponents(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
</ins><span class="cx"> 
</span><span class="cx">         # Remove all attendees except the one we want
</span><span class="cx">         itip.removeAllButOneAttendee(attendee)
</span><span class="lines">@@ -877,6 +925,7 @@
</span><span class="cx">             &quot;EXDATE&quot;,
</span><span class="cx">             &quot;ORGANIZER&quot;,
</span><span class="cx">             &quot;ATTENDEE&quot;,
</span><ins>+            &quot;VOTER&quot;,
</ins><span class="cx">             &quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;,
</span><span class="cx">             &quot;SUMMARY&quot;,
</span><span class="cx">             &quot;LOCATION&quot;,
</span><span class="lines">@@ -896,10 +945,38 @@
</span><span class="cx">         # Strip out unwanted bits
</span><span class="cx">         iTipGenerator.prepareSchedulingMessage(itip, reply=True)
</span><span class="cx"> 
</span><ins>+        # Handle VPOLL behavior
+        for component in itip.subcomponents():
+            if component.name() == &quot;VPOLL&quot;:
+                iTipGenerator.generateVPOLLReply(component, attendee)
+
</ins><span class="cx">         return itip
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><ins>+    def generateVPOLLReply(vpoll, attendee):
+        &quot;&quot;&quot;
+        Generate the proper poll response in a reply for each component being voted on.
+
+        @param vpoll: the VPOLL component to process
+        @type vpoll: L{Component}
+        @param attendee: calendar user address of attendee replying
+        @type attendee: C{str}
+        &quot;&quot;&quot;
+
+        for component in tuple(vpoll.subcomponents()):
+            if component.name() in ignoredComponents:
+                continue
+            poll_item_id = component.propertyValue(&quot;POLL-ITEM-ID&quot;)
+            if poll_item_id is None:
+                continue
+            voter = component.getVoterProperty((attendee,))
+            if voter is not None and voter.hasParameter(&quot;RESPONSE&quot;):
+                vpoll.addProperty(Property(&quot;POLL-ITEM-ID&quot;, poll_item_id, {&quot;RESPONSE&quot;: voter.parameterValue(&quot;RESPONSE&quot;)}))
+            vpoll.removeComponent(component)
+
+
+    @staticmethod
</ins><span class="cx">     def prepareSchedulingMessage(itip, reply=False):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Remove properties and parameters that should not be sent in an iTIP message
</span><span class="lines">@@ -925,6 +1002,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Property Parameters
</span><span class="cx">         itip.removePropertyParameters(&quot;ATTENDEE&quot;, (&quot;SCHEDULE-AGENT&quot;, &quot;SCHEDULE-STATUS&quot;, &quot;SCHEDULE-FORCE-SEND&quot;, &quot;X-CALENDARSERVER-DTSTAMP&quot;,))
</span><ins>+        itip.removePropertyParameters(&quot;VOTER&quot;, (&quot;SCHEDULE-AGENT&quot;, &quot;SCHEDULE-STATUS&quot;, &quot;SCHEDULE-FORCE-SEND&quot;, &quot;X-CALENDARSERVER-DTSTAMP&quot;,))
</ins><span class="cx">         itip.removePropertyParameters(&quot;ORGANIZER&quot;, (&quot;SCHEDULE-AGENT&quot;, &quot;SCHEDULE-STATUS&quot;, &quot;SCHEDULE-FORCE-SEND&quot;,))
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingprocessingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,9 +14,9 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
</span><span class="lines">@@ -785,13 +785,13 @@
</span><span class="cx">         cuas = self.recipient.principal.calendarUserAddresses
</span><span class="cx"> 
</span><span class="cx">         # First expand current one to get instances (only go 1 year into the future)
</span><del>-        default_future_expansion_duration = PyCalendarDuration(days=config.Scheduling.Options.AutoSchedule.FutureFreeBusyDays)
-        expand_max = PyCalendarDateTime.getToday() + default_future_expansion_duration
</del><ins>+        default_future_expansion_duration = Duration(days=config.Scheduling.Options.AutoSchedule.FutureFreeBusyDays)
+        expand_max = DateTime.getToday() + default_future_expansion_duration
</ins><span class="cx">         instances = calendar.expandTimeRanges(expand_max, ignoreInvalidInstances=True)
</span><span class="cx"> 
</span><span class="cx">         # We are going to ignore auto-accept processing for anything more than a day old (actually use -2 days
</span><span class="cx">         # to add some slop to account for possible timezone offsets)
</span><del>-        min_date = PyCalendarDateTime.getToday()
</del><ins>+        min_date = DateTime.getToday()
</ins><span class="cx">         min_date.offsetDay(-2)
</span><span class="cx">         allOld = True
</span><span class="cx"> 
</span><span class="lines">@@ -824,7 +824,7 @@
</span><span class="cx">             # Get the timezone property from the collection, and store in the query filter
</span><span class="cx">             # for use during the query itself.
</span><span class="cx">             tz = testcal.getTimezone()
</span><del>-            tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
</del><ins>+            tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
</ins><span class="cx"> 
</span><span class="cx">             # Now do search for overlapping time-range and set instance.free based
</span><span class="cx">             # on whether there is an overlap or not
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingschedulerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -41,7 +41,9 @@
</span><span class="cx"> from txdav.caldav.datastore.scheduling.imip.delivery import ScheduleViaIMip
</span><span class="cx"> from txdav.caldav.datastore.scheduling.ischedule.delivery import ScheduleViaISchedule
</span><span class="cx"> from txdav.caldav.datastore.scheduling.itip import iTIPRequestStatus
</span><ins>+
</ins><span class="cx"> import hashlib
</span><ins>+from collections import namedtuple
</ins><span class="cx"> 
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> CalDAV/Server-to-Server scheduling behavior.
</span><span class="lines">@@ -654,6 +656,11 @@
</span><span class="cx">     response_description_element = davxml.ResponseDescription
</span><span class="cx">     calendar_data_element = caldavxml.CalendarData
</span><span class="cx"> 
</span><ins>+    ScheduleResonseDetails = namedtuple(
+        &quot;ScheduleResonseDetails&quot;,
+        [&quot;recipient&quot;, &quot;reqstatus&quot;, &quot;calendar&quot;, &quot;error&quot;, &quot;message&quot;, ]
+    )
+
</ins><span class="cx">     def __init__(self, method, success_response, recipient_mapper=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @param method: the name of the method generating the queue.
</span><span class="lines">@@ -703,16 +710,14 @@
</span><span class="cx">         if not suppressErrorLog and code &gt; 400: # Error codes only
</span><span class="cx">             self.log.error(&quot;Error during %s for %s: %s&quot; % (self.method, recipient, message))
</span><span class="cx"> 
</span><del>-        children = []
-        children.append(self.recipient_element(davxml.HRef.fromString(recipient)) if self.recipient_uses_href else self.recipient_element.fromString(recipient))
-        children.append(self.request_status_element(reqstatus))
-        if calendar is not None:
-            children.append(self.calendar_data_element.fromCalendar(calendar))
-        if error is not None:
-            children.append(error)
-        if message is not None:
-            children.append(self.response_description_element(message))
-        self.responses.append(self.response_element(*children))
</del><ins>+        details = ScheduleResponseQueue.ScheduleResonseDetails(
+            self.recipient_element(davxml.HRef.fromString(recipient)) if self.recipient_uses_href else self.recipient_element.fromString(recipient),
+            self.request_status_element(reqstatus),
+            calendar,
+            error,
+            self.response_description_element(message) if message is not None else None,
+        )
+        self.responses.append(details)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def errorForFailure(self, failure):
</span><span class="lines">@@ -728,19 +733,17 @@
</span><span class="cx">         @param clone: the response to clone.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        children = []
-        children.append(self.recipient_element(davxml.HRef.fromString(recipient)) if self.recipient_uses_href else self.recipient_element.fromString(recipient))
-        children.append(self.request_status_element.fromString(request_status))
-        if calendar_data is not None:
-            children.append(self.calendar_data_element.fromCalendar(calendar_data))
-        if error is not None:
-            children.append(self.error_element(*error))
-        if desc is not None:
-            children.append(self.response_description_element.fromString(desc))
-        self.responses.append(self.response_element(*children))
</del><ins>+        details = ScheduleResponseQueue.ScheduleResonseDetails(
+            self.recipient_element(davxml.HRef.fromString(recipient)) if self.recipient_uses_href else self.recipient_element.fromString(recipient),
+            self.request_status_element.fromString(request_status),
+            calendar_data,
+            self.error_element(*error) if error is not None else None,
+            self.response_description_element.fromString(desc) if desc is not None else None,
+        )
+        self.responses.append(details)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def response(self):
</del><ins>+    def response(self, format=None):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Generate a L{ScheduleResponseResponse} with the responses contained in the
</span><span class="cx">         queue or, if no such responses, return the C{success_response} provided
</span><span class="lines">@@ -748,6 +751,20 @@
</span><span class="cx">         @return: the response.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         if self.responses:
</span><del>-            return ScheduleResponseResponse(self.schedule_response_element, self.responses, self.location)
</del><ins>+            # Convert our queue to all XML elements
+            xml_responses = []
+            for response in self.responses:
+                children = []
+                children.append(response.recipient)
+                children.append(response.reqstatus)
+                if response.calendar is not None:
+                    children.append(self.calendar_data_element.fromCalendar(response.calendar, format))
+                if response.error is not None:
+                    children.append(response.error)
+                if response.message is not None:
+                    children.append(response.message)
+                xml_responses.append(self.response_element(*children))
+
+            return ScheduleResponseResponse(self.schedule_response_element, xml_responses, self.location)
</ins><span class="cx">         else:
</span><span class="cx">             return self.success_response
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_freebusypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,8 +14,8 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.period import PyCalendarPeriod
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.period import Period
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="cx"> 
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx">             (
</span><span class="cx">                 &quot;#1.3 With single busy time&quot;,
</span><span class="cx">                 [
</span><del>-                    [PyCalendarPeriod.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;), ],
</del><ins>+                    [Period.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;), ],
</ins><span class="cx">                     [],
</span><span class="cx">                     [],
</span><span class="cx">                 ],
</span><span class="lines">@@ -120,8 +120,8 @@
</span><span class="cx">                 &quot;#1.4 With multiple busy time&quot;,
</span><span class="cx">                 [
</span><span class="cx">                     [
</span><del>-                        PyCalendarPeriod.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
-                        PyCalendarPeriod.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</del><ins>+                        Period.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
+                        Period.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</ins><span class="cx">                     ],
</span><span class="cx">                     [],
</span><span class="cx">                     [],
</span><span class="lines">@@ -148,10 +148,10 @@
</span><span class="cx">                 &quot;#1.5 With multiple busy time, some overlap&quot;,
</span><span class="cx">                 [
</span><span class="cx">                     [
</span><del>-                        PyCalendarPeriod.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
-                        PyCalendarPeriod.parseText(&quot;20080601T123000Z/20080601T133000Z&quot;),
-                        PyCalendarPeriod.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
-                        PyCalendarPeriod.parseText(&quot;20080601T150000Z/20080601T160000Z&quot;),
</del><ins>+                        Period.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
+                        Period.parseText(&quot;20080601T123000Z/20080601T133000Z&quot;),
+                        Period.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
+                        Period.parseText(&quot;20080601T150000Z/20080601T160000Z&quot;),
</ins><span class="cx">                     ],
</span><span class="cx">                     [],
</span><span class="cx">                     [],
</span><span class="lines">@@ -178,14 +178,14 @@
</span><span class="cx">                 &quot;#1.6 With all busy time types&quot;,
</span><span class="cx">                 [
</span><span class="cx">                     [
</span><del>-                        PyCalendarPeriod.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
-                        PyCalendarPeriod.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</del><ins>+                        Period.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;),
+                        Period.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</ins><span class="cx">                     ],
</span><span class="cx">                     [
</span><del>-                        PyCalendarPeriod.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</del><ins>+                        Period.parseText(&quot;20080601T140000Z/20080601T150000Z&quot;),
</ins><span class="cx">                     ],
</span><span class="cx">                     [
</span><del>-                        PyCalendarPeriod.parseText(&quot;20080601T160000Z/20080601T170000Z&quot;),
</del><ins>+                        Period.parseText(&quot;20080601T160000Z/20080601T170000Z&quot;),
</ins><span class="cx">                     ],
</span><span class="cx">                 ],
</span><span class="cx">                 &quot;20080601T000000Z&quot;,
</span><span class="lines">@@ -211,7 +211,7 @@
</span><span class="cx">             (
</span><span class="cx">                 &quot;#1.7 With single busy time and event details&quot;,
</span><span class="cx">                 [
</span><del>-                    [PyCalendarPeriod.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;), ],
</del><ins>+                    [Period.parseText(&quot;20080601T120000Z/20080601T130000Z&quot;), ],
</ins><span class="cx">                     [],
</span><span class="cx">                     [],
</span><span class="cx">                 ],
</span><span class="lines">@@ -269,7 +269,7 @@
</span><span class="cx">         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.now = DateTime.getNowUTC()
</ins><span class="cx">         self.now.setHHMMSS(0, 0, 0)
</span><span class="cx"> 
</span><span class="cx">         self.now_12H = self.now.duplicate()
</span><span class="lines">@@ -368,7 +368,7 @@
</span><span class="cx">         timerange = caldavxml.TimeRange(start=self.now.getText(), end=self.now_1D.getText())
</span><span class="cx">         result = (yield generateFreeBusyInfo(calendar, fbinfo, timerange, matchtotal))
</span><span class="cx">         self.assertEqual(result, 1)
</span><del>-        self.assertEqual(fbinfo[0], [PyCalendarPeriod.parseText(&quot;%s/%s&quot; % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</del><ins>+        self.assertEqual(fbinfo[0], [Period.parseText(&quot;%s/%s&quot; % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</ins><span class="cx">         self.assertEqual(len(fbinfo[1]), 0)
</span><span class="cx">         self.assertEqual(len(fbinfo[2]), 0)
</span><span class="cx"> 
</span><span class="lines">@@ -406,7 +406,7 @@
</span><span class="cx">             event_details=event_details
</span><span class="cx">         ))
</span><span class="cx">         self.assertEqual(result, 1)
</span><del>-        self.assertEqual(fbinfo[0], [PyCalendarPeriod.parseText(&quot;%s/%s&quot; % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</del><ins>+        self.assertEqual(fbinfo[0], [Period.parseText(&quot;%s/%s&quot; % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</ins><span class="cx">         self.assertEqual(len(fbinfo[1]), 0)
</span><span class="cx">         self.assertEqual(len(fbinfo[2]), 0)
</span><span class="cx">         self.assertEqual(len(event_details), 1)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_icalsplitterpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> from twisted.trial import unittest
</span><span class="cx"> from twistedcaldav.stdconfig import config
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.subs = {}
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.now = DateTime.getNowUTC()
</ins><span class="cx">         self.now.setHHMMSS(0, 0, 0)
</span><span class="cx"> 
</span><span class="cx">         self.subs[&quot;now&quot;] = self.now
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_implicitpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -14,8 +14,8 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="cx"> from twext.web2 import responsecode
</span><span class="lines">@@ -248,9 +248,9 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -287,12 +287,12 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -330,15 +330,15 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -447,7 +447,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (&quot;mailto:user3@example.com&quot;, None),
</span><del>-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -502,7 +502,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -648,9 +648,9 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user3@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user3@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -705,7 +705,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><span class="cx">                     (&quot;mailto:user3@example.com&quot;, None),
</span><del>-                    (&quot;mailto:user4@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user4@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -751,7 +751,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user4@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user4@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">             (
</span><span class="lines">@@ -798,9 +798,9 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (
</span><del>-                    (&quot;mailto:user1@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user2@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    (&quot;mailto:user4@example.com&quot;, PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+                    (&quot;mailto:user1@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user2@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    (&quot;mailto:user4@example.com&quot;, DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
</ins><span class="cx">                 ),
</span><span class="cx">             ),
</span><span class="cx">         )
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_itippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -15,8 +15,8 @@
</span><span class="cx"> ##
</span><span class="cx"> from __future__ import print_function
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twisted.trial import unittest
</span><span class="cx"> 
</span><span class="lines">@@ -2025,7 +2025,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (&quot;mailto:user2@example.com&quot;,),
</span><del>-                (PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
</del><ins>+                (DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
</ins><span class="cx">             ),
</span><span class="cx"> 
</span><span class="cx">             # Recurring component with one instance, each with one attendee - cancel instance
</span><span class="lines">@@ -2066,7 +2066,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 (&quot;mailto:user2@example.com&quot;,),
</span><del>-                (PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
</del><ins>+                (DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
</ins><span class="cx">             ),
</span><span class="cx"> 
</span><span class="cx">             # Recurring component with one instance, each with one attendee - cancel master
</span><span class="lines">@@ -2127,7 +2127,7 @@
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 &quot;&quot;,
</span><span class="cx">                 (&quot;mailto:user2@example.com&quot;,),
</span><del>-                (PyCalendarDateTime(2008, 12, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
</del><ins>+                (DateTime(2008, 12, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
</ins><span class="cx">             ),
</span><span class="cx"> 
</span><span class="cx">         )
</span><span class="lines">@@ -2229,7 +2229,8 @@
</span><span class="cx"> DTSTART;TZID=America/Los_Angeles:20101007T113000
</span><span class="cx"> DTEND;TZID=America/Los_Angeles:20101007T120000
</span><span class="cx"> ATTENDEE;CN=Missing Attendee;CUTYPE=INDIVIDUAL;EMAIL=missing@example.com;P
</span><del>- ARTSTAT=DECLINED;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:missing@example.com
</del><ins>+ ARTSTAT=DECLINED;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:missing@example.co
+ m
</ins><span class="cx"> ORGANIZER;CN=The Organizer:mailto:organizer@example.com
</span><span class="cx"> REQUEST-STATUS:2.0;Success
</span><span class="cx"> SEQUENCE:24
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreschedulingtesttest_utilspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> Tests for calendarserver.tools.purge
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks
</span><span class="cx"> from twisted.trial import unittest
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> from txdav.common.datastore.test.util import populateCalendarsFrom, CommonCommonTests
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-now = PyCalendarDateTime.getToday().getYear()
</del><ins>+now = DateTime.getToday().getYear()
</ins><span class="cx"> 
</span><span class="cx"> ORGANIZER_ICS = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/sql.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue, succeed
</span><span class="cx"> from twisted.python import hashlib
</span><span class="cx"> 
</span><del>-from twistedcaldav import caldavxml, customxml
</del><ins>+from twistedcaldav import caldavxml, customxml, ical
</ins><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
</span><span class="cx"> from twistedcaldav.dateops import normalizeForIndex, datetimeMktime, \
</span><span class="lines">@@ -89,10 +89,10 @@
</span><span class="cx">     InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
</span><span class="cx">     InvalidResourceMove, InvalidComponentForStoreError
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.value import PyCalendarValue
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
+from pycalendar.value import Value
</ins><span class="cx"> 
</span><span class="cx"> from zope.interface.declarations import implements
</span><span class="cx"> 
</span><span class="lines">@@ -406,6 +406,26 @@
</span><span class="cx"> 
</span><span class="cx">     _cacher = Memcacher(&quot;SQL.calhome&quot;, pickle=True, key_normalization=False)
</span><span class="cx"> 
</span><ins>+    _componentCalendarName = {
+        &quot;VEVENT&quot;: &quot;calendar&quot;,
+        &quot;VTODO&quot;: &quot;tasks&quot;,
+        &quot;VJOURNAL&quot;: &quot;journals&quot;,
+        &quot;VAVAILABILITY&quot;: &quot;available&quot;,
+        &quot;VPOLL&quot;: &quot;polls&quot;,
+    }
+
+    _componentDefaultColumn = {
+        &quot;VEVENT&quot;: schema.CALENDAR_HOME_METADATA.DEFAULT_EVENTS,
+        &quot;VTODO&quot;: schema.CALENDAR_HOME_METADATA.DEFAULT_TASKS,
+        &quot;VPOLL&quot;: schema.CALENDAR_HOME_METADATA.DEFAULT_POLLS,
+    }
+
+    _componentDefaultAttribute = {
+        &quot;VEVENT&quot;: &quot;_default_events&quot;,
+        &quot;VTODO&quot;: &quot;_default_tasks&quot;,
+        &quot;VPOLL&quot;: &quot;_default_polls&quot;,
+    }
+
</ins><span class="cx">     def __init__(self, transaction, ownerUID):
</span><span class="cx"> 
</span><span class="cx">         self._childClass = Calendar
</span><span class="lines">@@ -422,9 +442,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Common behavior is to have created and modified
</span><span class="cx"> 
</span><del>-        return (
-            cls._homeMetaDataSchema.DEFAULT_EVENTS,
-            cls._homeMetaDataSchema.DEFAULT_TASKS,
</del><ins>+        default_collections = tuple([cls._componentDefaultColumn[name] for name in sorted(cls._componentDefaultColumn.keys())])
+        return default_collections + (
</ins><span class="cx">             cls._homeMetaDataSchema.ALARM_VEVENT_TIMED,
</span><span class="cx">             cls._homeMetaDataSchema.ALARM_VEVENT_ALLDAY,
</span><span class="cx">             cls._homeMetaDataSchema.ALARM_VTODO_TIMED,
</span><span class="lines">@@ -445,9 +464,8 @@
</span><span class="cx"> 
</span><span class="cx">         # Common behavior is to have created and modified
</span><span class="cx"> 
</span><del>-        return (
-            &quot;_default_events&quot;,
-            &quot;_default_tasks&quot;,
</del><ins>+        default_attributes = tuple([cls._componentDefaultAttribute[name] for name in sorted(cls._componentDefaultAttribute.keys())])
+        return default_attributes + (
</ins><span class="cx">             &quot;_alarm_vevent_timed&quot;,
</span><span class="cx">             &quot;_alarm_vevent_allday&quot;,
</span><span class="cx">             &quot;_alarm_vtodo_timed&quot;,
</span><span class="lines">@@ -624,22 +642,18 @@
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def createdHome(self):
</span><span class="cx"> 
</span><del>-        # Default calendar
-        defaultCal = yield self.createCalendarWithName(&quot;calendar&quot;)
-
</del><span class="cx">         # Check whether components type must be separate
</span><span class="cx">         if config.RestrictCalendarsToOneComponentType:
</span><del>-            yield defaultCal.setSupportedComponents(&quot;VEVENT&quot;)
-            yield self.setDefaultCalendar(defaultCal, False)
-
-            # Default tasks
-            defaultTasks = yield self.createCalendarWithName(&quot;tasks&quot;)
-            yield defaultTasks.setSupportedComponents(&quot;VTODO&quot;)
-            yield defaultTasks.setUsedForFreeBusy(False)
-            yield self.setDefaultCalendar(defaultTasks, True)
</del><ins>+            for name in ical.allowedStoreComponents:
+                cal = yield self.createCalendarWithName(self._componentCalendarName[name])
+                yield cal.setSupportedComponents(name)
+                if name not in (&quot;VEVENT&quot;, &quot;VAVAILABILITY&quot;,):
+                    yield cal.setUsedForFreeBusy(False)
+                yield self.setDefaultCalendar(cal, name)
</ins><span class="cx">         else:
</span><del>-            yield self.setDefaultCalendar(defaultCal, False)
-            yield self.setDefaultCalendar(defaultCal, True)
</del><ins>+            cal = yield self.createCalendarWithName(&quot;calendar&quot;)
+            for name in ical.allowedStoreComponents:
+                yield self.setDefaultCalendar(cal, name)
</ins><span class="cx"> 
</span><span class="cx">         inbox = yield self.createCalendarWithName(&quot;inbox&quot;)
</span><span class="cx">         yield inbox.setUsedForFreeBusy(False)
</span><span class="lines">@@ -693,55 +707,13 @@
</span><span class="cx">                     newcal = yield self.createCalendarWithName(newname)
</span><span class="cx">                     yield newcal.setSupportedComponents(support_component)
</span><span class="cx"> 
</span><del>-            yield _requireCalendarWithType(&quot;VEVENT&quot;, &quot;calendar&quot;)
-            yield _requireCalendarWithType(&quot;VTODO&quot;, &quot;tasks&quot;)
</del><ins>+            for name in ical.allowedStoreComponents:
+                yield _requireCalendarWithType(name, self._componentCalendarName[name])
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def pickNewDefaultCalendar(self, tasks=False):
</del><ins>+    def setDefaultCalendar(self, calendar, componentType):
</ins><span class="cx">         &quot;&quot;&quot;
</span><del>-        First see if default provisioned calendar exists in the calendar home and pick that. Otherwise
-        pick another from the calendar home.
-        &quot;&quot;&quot;
-
-        componentType = &quot;VTODO&quot; if tasks else &quot;VEVENT&quot;
-        test_name = &quot;tasks&quot; if tasks else &quot;calendar&quot;
-
-        defaultCalendar = (yield self.calendarWithName(test_name))
-        if defaultCalendar is None or not defaultCalendar.owned():
-
-            @inlineCallbacks
-            def _findDefault():
-                for calendarName in (yield self.listCalendars()):
-                    calendar = (yield self.calendarWithName(calendarName))
-                    if calendar.isInbox():
-                        continue
-                    if not calendar.owned():
-                        continue
-                    if not calendar.isSupportedComponent(componentType):
-                        continue
-                    break
-                else:
-                    calendar = None
-                returnValue(calendar)
-
-            defaultCalendar = yield _findDefault()
-            if defaultCalendar is None:
-                # Create a default and try and get its name again
-                yield self.ensureDefaultCalendarsExist()
-                defaultCalendar = yield _findDefault()
-                if defaultCalendar is None:
-                    # Failed to even create a default - bad news...
-                    raise RuntimeError(&quot;No valid calendars to use as a default %s calendar.&quot; % (componentType,))
-
-        yield self.setDefaultCalendar(defaultCalendar, tasks)
-
-        returnValue(defaultCalendar)
-
-
-    @inlineCallbacks
-    def setDefaultCalendar(self, calendar, tasks=False):
-        &quot;&quot;&quot;
</del><span class="cx">         Set the default calendar for a particular type of component.
</span><span class="cx"> 
</span><span class="cx">         @param calendar: the calendar being set as the default
</span><span class="lines">@@ -749,10 +721,15 @@
</span><span class="cx">         @param tasks: C{True} for VTODO, C{False} for VEVENT
</span><span class="cx">         @type componentType: C{bool}
</span><span class="cx">         &quot;&quot;&quot;
</span><ins>+
+        # We only support VEVENT and VTOTO right now
+        componentType = componentType.upper()
+        if componentType not in self._componentDefaultAttribute:
+            returnValue(None)
+
</ins><span class="cx">         chm = self._homeMetaDataSchema
</span><del>-        componentType = &quot;VTODO&quot; if tasks else &quot;VEVENT&quot;
-        attribute_to_test = &quot;_default_tasks&quot; if tasks else &quot;_default_events&quot;
-        column_to_set = chm.DEFAULT_TASKS if tasks else chm.DEFAULT_EVENTS
</del><ins>+        attribute_to_test = self._componentDefaultAttribute[componentType]
+        column_to_set = self._componentDefaultColumn[componentType]
</ins><span class="cx"> 
</span><span class="cx">         # Check validity of the default
</span><span class="cx">         if calendar.isInbox():
</span><span class="lines">@@ -794,8 +771,13 @@
</span><span class="cx">         @rtype: L{Calendar} or C{None}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+        # We only support VEVENT and VTOTO right now
+        componentType = componentType.upper()
+        if componentType not in self._componentDefaultAttribute:
+            returnValue(None)
+
</ins><span class="cx">         # Check any default calendar property first - this will create if none exists
</span><del>-        attribute_to_test = &quot;_default_tasks&quot; if componentType == &quot;VTODO&quot; else &quot;_default_events&quot;
</del><ins>+        attribute_to_test = self._componentDefaultAttribute[componentType]
</ins><span class="cx">         defaultID = getattr(self, attribute_to_test)
</span><span class="cx">         if defaultID:
</span><span class="cx">             default = (yield self.childWithID(defaultID))
</span><span class="lines">@@ -816,7 +798,8 @@
</span><span class="cx"> 
</span><span class="cx">             # Try to find a calendar supporting the required component type. If there are multiple, pick
</span><span class="cx">             # the one with the oldest created timestamp as that will likely be the initial provision.
</span><del>-            for calendarName in (yield self.listCalendars()):
</del><ins>+            existing_names = (yield self.listCalendars())
+            for calendarName in existing_names:
</ins><span class="cx">                 calendar = (yield self.calendarWithName(calendarName))
</span><span class="cx">                 if calendar.isInbox():
</span><span class="cx">                     continue
</span><span class="lines">@@ -832,12 +815,15 @@
</span><span class="cx">                 if not create:
</span><span class="cx">                     returnValue(None)
</span><span class="cx">                 else:
</span><del>-                    new_name = &quot;%ss&quot; % (componentType.lower()[1:],)
</del><ins>+                    # Try a default name mapping first, else use a UUID
+                    new_name = self._componentCalendarName[componentType]
+                    if new_name in existing_names:
+                        new_name = str(uuid.uuid4())
</ins><span class="cx">                     default = yield self.createCalendarWithName(new_name)
</span><del>-                    yield default.setSupportedComponents(componentType.upper())
</del><ins>+                    yield default.setSupportedComponents(componentType)
</ins><span class="cx"> 
</span><span class="cx">             # Update the metadata
</span><del>-            yield self.setDefaultCalendar(default, componentType == &quot;VTODO&quot;)
</del><ins>+            yield self.setDefaultCalendar(default, componentType)
</ins><span class="cx"> 
</span><span class="cx">         returnValue(default)
</span><span class="cx"> 
</span><span class="lines">@@ -847,7 +833,10 @@
</span><span class="cx">         Is the supplied calendar one of the possible default calendars.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # Not allowed to delete the default calendar
</span><del>-        return calendar._resourceID in (self._default_events, self._default_tasks)
</del><ins>+        for attr in self._componentDefaultAttribute.values():
+            if calendar._resourceID == getattr(self, attr):
+                return True
+        return False
</ins><span class="cx"> 
</span><span class="cx">     ALARM_DETAILS = {
</span><span class="cx">         (True, True): (_homeMetaDataSchema.ALARM_VEVENT_TIMED, &quot;_alarm_vevent_timed&quot;),
</span><span class="lines">@@ -2251,7 +2240,7 @@
</span><span class="cx">                 # When there is no master we have a set of overridden components -
</span><span class="cx">                 #   index them all.
</span><span class="cx">                 # When there is one instance - index it.
</span><del>-                expand = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+                expand = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">                 doInstanceIndexing = True
</span><span class="cx">             else:
</span><span class="cx"> 
</span><span class="lines">@@ -2263,8 +2252,8 @@
</span><span class="cx">                 # by default.  This is a caching parameter which affects the size of the index;
</span><span class="cx">                 # it does not affect search results beyond this period, but it may affect
</span><span class="cx">                 # performance of such a search.
</span><del>-                expand = (PyCalendarDateTime.getToday() +
-                          PyCalendarDuration(days=config.FreeBusyIndexExpandAheadDays))
</del><ins>+                expand = (DateTime.getToday() +
+                          Duration(days=config.FreeBusyIndexExpandAheadDays))
</ins><span class="cx"> 
</span><span class="cx">                 if expand_until and expand_until &gt; expand:
</span><span class="cx">                     expand = expand_until
</span><span class="lines">@@ -2281,12 +2270,12 @@
</span><span class="cx">                 # occurrences into some obscenely far-in-the-future date, so we cap the caching
</span><span class="cx">                 # period.  Searches beyond this period will always be relatively expensive for
</span><span class="cx">                 # resources with occurrences beyond this period.
</span><del>-                if expand &gt; (PyCalendarDateTime.getToday() +
-                             PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
</del><ins>+                if expand &gt; (DateTime.getToday() +
+                             Duration(days=config.FreeBusyIndexExpandMaxDays)):
</ins><span class="cx">                     raise IndexedSearchException
</span><span class="cx"> 
</span><span class="cx">             if config.FreeBusyIndexLowerLimitDays:
</span><del>-                truncateLowerLimit = PyCalendarDateTime.getToday()
</del><ins>+                truncateLowerLimit = DateTime.getToday()
</ins><span class="cx">                 truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
</span><span class="cx">             else:
</span><span class="cx">                 truncateLowerLimit = None
</span><span class="lines">@@ -2313,7 +2302,7 @@
</span><span class="cx">             if not doInstanceIndexing:
</span><span class="cx">                 instances = None
</span><span class="cx">                 recurrenceLowerLimit = None
</span><del>-                recurrenceLimit = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+                recurrenceLimit = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx"> 
</span><span class="cx">         co = schema.CALENDAR_OBJECT
</span><span class="cx">         tr = schema.TIME_RANGE
</span><span class="lines">@@ -2432,7 +2421,7 @@
</span><span class="cx">         @param instances: the set of instances to add
</span><span class="cx">         @type instances: L{InstanceList}
</span><span class="cx">         @param truncateLowerLimit: the lower limit for instances
</span><del>-        @type truncateLowerLimit: L{PyCalendarDateTime}
</del><ins>+        @type truncateLowerLimit: L{DateTime}
</ins><span class="cx">         @param isInboxItem: indicates if an inbox item
</span><span class="cx">         @type isInboxItem: C{bool}
</span><span class="cx">         @param txn: transaction to use
</span><span class="lines">@@ -2461,8 +2450,8 @@
</span><span class="cx">         # For truncated items we insert a tomb stone lower bound so that a time-range
</span><span class="cx">         # query with just an end bound will match
</span><span class="cx">         if lowerLimitApplied or instances.lowerLimit and len(instances.instances) == 0:
</span><del>-            start = PyCalendarDateTime(1901, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-            end = PyCalendarDateTime(1901, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            start = DateTime(1901, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+            end = DateTime(1901, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">             yield self._addInstanceDetails(component, None, start, end, False, True, &quot;UNKNOWN&quot;, isInboxItem, txn)
</span><span class="cx"> 
</span><span class="cx">         # Special - for unbounded recurrence we insert a value for &quot;infinity&quot;
</span><span class="lines">@@ -2470,8 +2459,8 @@
</span><span class="cx">         # We also need to add the &quot;infinity&quot; value if the event was bounded but
</span><span class="cx">         # starts after the future expansion cut-off limit.
</span><span class="cx">         if component.isRecurringUnbounded() or instances.limit and len(instances.instances) == 0:
</span><del>-            start = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-            end = PyCalendarDateTime(2100, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+            start = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+            end = DateTime(2100, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">             yield self._addInstanceDetails(component, None, start, end, False, True, &quot;UNKNOWN&quot;, isInboxItem, txn)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -2658,7 +2647,7 @@
</span><span class="cx">         Get the RECURRANCE_MIN, RECURRANCE_MAX value from the database. Occasionally we might need to do an
</span><span class="cx">         update to time-range data via a separate transaction, so we allow that to be passed in.
</span><span class="cx"> 
</span><del>-        @return: L{PyCalendarDateTime} result
</del><ins>+        @return: L{DateTime} result
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # Setup appropriate txn
</span><span class="cx">         txn = txn if txn is not None else self._txn
</span><span class="lines">@@ -4280,7 +4269,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return an iCalendar ATTACH property for this attachment.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        attach = Property(&quot;ATTACH&quot;, &quot;&quot;, valuetype=PyCalendarValue.VALUETYPE_URI)
</del><ins>+        attach = Property(&quot;ATTACH&quot;, &quot;&quot;, valuetype=Value.VALUETYPE_URI)
</ins><span class="cx">         location = (yield self.updateProperty(attach))
</span><span class="cx">         returnValue((attach, location,))
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretestcommonpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1337,7 +1337,7 @@
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_iCalendarText(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        L{ICalendarObject.iCalendarText} returns a C{str} describing the same
</del><ins>+        L{ICalendarObject._text} returns a C{str} describing the same
</ins><span class="cx">         data provided by L{ICalendarObject.component}.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         text = yield (yield self.calendarObjectUnderTest())._text()
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_attachmentspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -16,8 +16,8 @@
</span><span class="cx"> 
</span><span class="cx"> from calendarserver.tap.util import directoryFromConfig
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.value import PyCalendarValue
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.value import Value
</ins><span class="cx"> 
</span><span class="cx"> from twext.enterprise.dal.syntax import Delete
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="lines">@@ -1249,7 +1249,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-now = PyCalendarDateTime.getToday().getYear()
</del><ins>+now = DateTime.getToday().getYear()
</ins><span class="cx"> 
</span><span class="cx"> PLAIN_ICS = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -1454,7 +1454,7 @@
</span><span class="cx">         cal.mainComponent().addProperty(Property(
</span><span class="cx">             &quot;ATTACH&quot;,
</span><span class="cx">             &quot;http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s&quot; % (home.name(), dropboxid, name,),
</span><del>-            valuetype=PyCalendarValue.VALUETYPE_URI
</del><ins>+            valuetype=Value.VALUETYPE_URI
</ins><span class="cx">         ))
</span><span class="cx">         yield event.setComponent(cal)
</span><span class="cx">         yield txn.commit()
</span><span class="lines">@@ -1477,7 +1477,7 @@
</span><span class="cx">         cal.mainComponent().addProperty(Property(
</span><span class="cx">             &quot;ATTACH&quot;,
</span><span class="cx">             &quot;http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s&quot; % (owner_home, dropboxid, name,),
</span><del>-            valuetype=PyCalendarValue.VALUETYPE_URI
</del><ins>+            valuetype=Value.VALUETYPE_URI
</ins><span class="cx">         ))
</span><span class="cx">         yield event.setComponent(cal)
</span><span class="cx">         yield txn.commit()
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_filepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> from txdav.caldav.datastore.test.common import (
</span><span class="cx">     CommonTests, test_event_text, event1modified_text)
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> storePath = FilePath(__file__).parent().child(&quot;calendar_store&quot;)
</span><span class="cx"> 
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">     storePath.copyTo(calendarPath)
</span><span class="cx"> 
</span><span class="cx">     # Set year values to current year
</span><del>-    nowYear = PyCalendarDateTime.getToday().getYear()
</del><ins>+    nowYear = DateTime.getToday().getYear()
</ins><span class="cx">     for home in calendarPath.child(&quot;ho&quot;).child(&quot;me&quot;).children():
</span><span class="cx">         if not home.basename().startswith(&quot;.&quot;):
</span><span class="cx">             for calendar in home.children():
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_index_filepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> from twistedcaldav.test.util import InMemoryMemcacheProtocol
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="lines">@@ -311,7 +311,7 @@
</span><span class="cx">             else:
</span><span class="cx">                 self.assertFalse(self.db.resourceExists(name), msg=description)
</span><span class="cx"> 
</span><del>-        self.db.testAndUpdateIndex(PyCalendarDateTime(2020, 1, 1))
</del><ins>+        self.db.testAndUpdateIndex(DateTime(2020, 1, 1))
</ins><span class="cx">         for description, name, calendar_txt, reCreate, ok in data:
</span><span class="cx">             if ok:
</span><span class="cx">                 self.assertTrue(self.db.resourceExists(name), msg=description)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -27,8 +27,8 @@
</span><span class="cx"> L{txdav.caldav.datastore.test.common}.
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
</ins><span class="cx"> 
</span><span class="cx"> from twext.enterprise.dal.syntax import Select, Parameter, Insert, Delete, \
</span><span class="cx">     Update
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> from twisted.internet.task import deferLater
</span><span class="cx"> from twisted.trial import unittest
</span><span class="cx"> 
</span><del>-from twistedcaldav import caldavxml
</del><ins>+from twistedcaldav import caldavxml, ical
</ins><span class="cx"> from twistedcaldav.caldavxml import CalendarDescription
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.dateops import datetimeMktime
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx">         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><del>-        self.nowYear = {&quot;now&quot;: PyCalendarDateTime.getToday().getYear()}
</del><ins>+        self.nowYear = {&quot;now&quot;: DateTime.getToday().getYear()}
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -474,14 +474,14 @@
</span><span class="cx">             )
</span><span class="cx"> 
</span><span class="cx">         supported_components = set()
</span><del>-        self.assertEqual(len(toCalendars), 4)
</del><ins>+        self.assertEqual(len(toCalendars), 2 + len(ical.allowedStoreComponents))
</ins><span class="cx">         for calendar in toCalendars:
</span><span class="cx">             if calendar.name() == &quot;inbox&quot;:
</span><span class="cx">                 continue
</span><span class="cx">             result = yield calendar.getSupportedComponents()
</span><span class="cx">             supported_components.add(result)
</span><span class="cx"> 
</span><del>-        self.assertEqual(supported_components, set((&quot;VEVENT&quot;, &quot;VTODO&quot;,)))
</del><ins>+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -509,7 +509,7 @@
</span><span class="cx">             result = yield calendar.getSupportedComponents()
</span><span class="cx">             supported_components.add(result)
</span><span class="cx"> 
</span><del>-        self.assertEqual(supported_components, set((&quot;VEVENT&quot;, &quot;VTODO&quot;,)))
</del><ins>+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_calendarHomeVersion(self):
</span><span class="lines">@@ -1124,7 +1124,7 @@
</span><span class="cx">             result = yield calendar.getSupportedComponents()
</span><span class="cx">             supported_components.add(result)
</span><span class="cx"> 
</span><del>-        self.assertEqual(supported_components, set((&quot;VEVENT&quot;, &quot;VTODO&quot;,)))
</del><ins>+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -1190,7 +1190,7 @@
</span><span class="cx">         self.assertEqual(home._default_events, None)
</span><span class="cx">         self.assertEqual(home._default_tasks, None)
</span><span class="cx">         calendar1 = yield home.calendarWithName(&quot;calendar_1&quot;)
</span><del>-        yield home.setDefaultCalendar(calendar1, False)
</del><ins>+        yield home.setDefaultCalendar(calendar1, &quot;VEVENT&quot;)
</ins><span class="cx">         self.assertEqual(home._default_events, calendar1._resourceID)
</span><span class="cx">         self.assertEqual(home._default_tasks, None)
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -1198,7 +1198,7 @@
</span><span class="cx">         home = yield self.homeUnderTest(name=&quot;home_defaults&quot;)
</span><span class="cx">         calendar1 = yield home.calendarWithName(&quot;calendar_1&quot;)
</span><span class="cx">         calendar2 = yield home.calendarWithName(&quot;calendar_1-vtodo&quot;)
</span><del>-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, False), InvalidDefaultCalendar)
</del><ins>+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, &quot;VEVENT&quot;), InvalidDefaultCalendar)
</ins><span class="cx">         self.assertEqual(home._default_events, calendar1._resourceID)
</span><span class="cx">         self.assertEqual(home._default_tasks, None)
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -1206,20 +1206,20 @@
</span><span class="cx">         home = yield self.homeUnderTest(name=&quot;home_defaults&quot;)
</span><span class="cx">         calendar1 = yield home.calendarWithName(&quot;calendar_1&quot;)
</span><span class="cx">         calendar2 = yield home.calendarWithName(&quot;calendar_1-vtodo&quot;)
</span><del>-        yield home.setDefaultCalendar(calendar2, True)
</del><ins>+        yield home.setDefaultCalendar(calendar2, &quot;VTODO&quot;)
</ins><span class="cx">         self.assertEqual(home._default_events, calendar1._resourceID)
</span><span class="cx">         self.assertEqual(home._default_tasks, calendar2._resourceID)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         home = yield self.homeUnderTest(name=&quot;home_defaults&quot;)
</span><span class="cx">         calendar1 = yield home.calendarWithName(&quot;inbox&quot;)
</span><del>-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
</del><ins>+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, &quot;VEVENT&quot;), InvalidDefaultCalendar)
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         home = yield self.homeUnderTest(name=&quot;home_defaults&quot;)
</span><span class="cx">         home_other = yield self.homeUnderTest(name=&quot;home_splits&quot;)
</span><span class="cx">         calendar1 = yield home_other.calendarWithName(&quot;calendar_1&quot;)
</span><del>-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
</del><ins>+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, &quot;VEVENT&quot;), InvalidDefaultCalendar)
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1377,38 +1377,38 @@
</span><span class="cx">         self.assertEqual(rmax.getYear(), nowYear + 1)
</span><span class="cx"> 
</span><span class="cx">         # Fully within range
</span><del>-        testMin = PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        testMax = PyCalendarDateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMin = DateTime(nowYear, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [])
</span><span class="cx"> 
</span><span class="cx">         # Upper bound exceeded
</span><del>-        testMin = PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        testMax = PyCalendarDateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMin = DateTime(nowYear, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [&quot;indexing.ics&quot;])
</span><span class="cx"> 
</span><span class="cx">         # Lower bound exceeded
</span><del>-        testMin = PyCalendarDateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        testMax = PyCalendarDateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMin = DateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [&quot;indexing.ics&quot;])
</span><span class="cx"> 
</span><span class="cx">         # Lower and upper bounds exceeded
</span><del>-        testMin = PyCalendarDateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        testMax = PyCalendarDateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMin = DateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [&quot;indexing.ics&quot;])
</span><span class="cx"> 
</span><span class="cx">         # Lower none within range
</span><span class="cx">         testMin = None
</span><del>-        testMax = PyCalendarDateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [])
</span><span class="cx"> 
</span><span class="cx">         # Lower none and upper bounds exceeded
</span><span class="cx">         testMin = None
</span><del>-        testMax = PyCalendarDateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
</del><ins>+        testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx">         result = yield index.notExpandedWithin(testMin, testMax)
</span><span class="cx">         self.assertEqual(result, [&quot;indexing.ics&quot;])
</span><span class="cx"> 
</span><span class="lines">@@ -2154,7 +2154,7 @@
</span><span class="cx"> 
</span><span class="cx">         self.subs = {}
</span><span class="cx"> 
</span><del>-        self.now = PyCalendarDateTime.getNowUTC()
</del><ins>+        self.now = DateTime.getNowUTC()
</ins><span class="cx">         self.now.setHHMMSS(0, 0, 0)
</span><span class="cx"> 
</span><span class="cx">         self.subs[&quot;now&quot;] = self.now
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_utilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -349,7 +349,8 @@
</span><span class="cx">                 &quot;inbox&quot;: {},
</span><span class="cx">                 # XXX: implementation is configuration-sensitive regarding the
</span><span class="cx">                 # 'tasks' calendar and it shouldn't be.
</span><del>-                &quot;tasks&quot;: {}
</del><ins>+                &quot;tasks&quot;: {},
+                &quot;polls&quot;: {},
</ins><span class="cx">             }
</span><span class="cx">         }, self.storeUnderTest())
</span><span class="cx">         txn = self.transactionUnderTest()
</span><span class="lines">@@ -412,7 +413,7 @@
</span><span class="cx">             c1 = {&quot;1.ics&quot;: self.sampleEvent(&quot;uid1&quot;)}
</span><span class="cx">         if c2 is None:
</span><span class="cx">             c2 = {&quot;2.ics&quot;: self.sampleEvent(&quot;uid2&quot;)}
</span><del>-        defaults = {&quot;calendar&quot;: {}, &quot;inbox&quot;: {}, &quot;tasks&quot;: {}}
</del><ins>+        defaults = {&quot;calendar&quot;: {}, &quot;inbox&quot;: {}, &quot;tasks&quot;: {}, &quot;polls&quot;: {}}
</ins><span class="cx">         def conflicted(caldata):
</span><span class="cx">             d = defaults.copy()
</span><span class="cx">             d.update(conflicted=caldata)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoreutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/util.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/util.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/datastore/util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> from twext.python.vcomponent import InvalidICalendarDataError
</span><span class="cx"> from twext.python.vcomponent import VComponent
</span><span class="cx"> 
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> from twistedcaldav.datafilters.hiddeninstance import HiddenInstanceFilter
</span><span class="cx"> from twistedcaldav.datafilters.privateevents import PrivateEventFilter
</span><span class="cx"> from twistedcaldav.ical import PERUSER_UID
</span><span class="lines">@@ -380,9 +381,11 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     from twistedcaldav.config import config
</span><span class="cx">     if not merge:
</span><del>-        yield outHome.removeCalendarWithName(&quot;calendar&quot;)
</del><span class="cx">         if config.RestrictCalendarsToOneComponentType:
</span><del>-            yield outHome.removeCalendarWithName(&quot;tasks&quot;)
</del><ins>+            for name in ical.allowedStoreComponents:
+                yield outHome.removeCalendarWithName(outHome._componentCalendarName[name])
+        else:
+            yield outHome.removeCalendarWithName(&quot;calendar&quot;)
</ins><span class="cx">         yield outHome.removeCalendarWithName(&quot;inbox&quot;)
</span><span class="cx"> 
</span><span class="cx">     outHome.properties().update(inHome.properties())
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavicalendarstorepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/icalendarstore.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/icalendarstore.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/caldav/icalendarstore.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -363,9 +363,9 @@
</span><span class="cx">         instances that occur within the time range that begins at
</span><span class="cx">         C{start} and ends at C{end}.
</span><span class="cx"> 
</span><del>-        @param start: a L{PyCalendarDateTime}.
-        @param end: a L{PyCalendarDateTime}.
-        @param timeZone: a L{PyCalendarTimezone}.
</del><ins>+        @param start: a L{DateTime}.
+        @param end: a L{DateTime}.
+        @param timeZone: a L{Timezone}.
</ins><span class="cx">         @return: an iterable of L{ICalendarObject}s.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> from cStringIO import StringIO
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from twext.enterprise.dal.syntax import (
</span><span class="cx">     Delete, utcNowSQL, Union, Insert, Len, Max, Parameter, SavepointAction,
</span><span class="lines">@@ -1106,7 +1106,7 @@
</span><span class="cx">     def eventsOlderThan(self, cutoff, batchSize=None):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Return up to the oldest batchSize events which exist completely earlier
</span><del>-        than &quot;cutoff&quot; (PyCalendarDateTime)
</del><ins>+        than &quot;cutoff&quot; (DateTime)
</ins><span class="cx"> 
</span><span class="cx">         Returns a deferred to a list of (uid, calendarName, eventName, maxDate)
</span><span class="cx">         tuples.
</span><span class="lines">@@ -1114,7 +1114,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Make sure cut off is after any lower limit truncation in the DB
</span><span class="cx">         if config.FreeBusyIndexLowerLimitDays:
</span><del>-            truncateLowerLimit = PyCalendarDateTime.getToday()
</del><ins>+            truncateLowerLimit = DateTime.getToday()
</ins><span class="cx">             truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
</span><span class="cx">             if cutoff &lt; truncateLowerLimit:
</span><span class="cx">                 raise ValueError(&quot;Cannot query events older than %s&quot; % (truncateLowerLimit.getText(),))
</span><span class="lines">@@ -1132,7 +1132,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Make sure cut off is after any lower limit truncation in the DB
</span><span class="cx">         if config.FreeBusyIndexLowerLimitDays:
</span><del>-            truncateLowerLimit = PyCalendarDateTime.getToday()
</del><ins>+            truncateLowerLimit = DateTime.getToday()
</ins><span class="cx">             truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
</span><span class="cx">             if cutoff &lt; truncateLowerLimit:
</span><span class="cx">                 raise ValueError(&quot;Cannot query events older than %s&quot; % (truncateLowerLimit.getText(),))
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_legacypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -43,8 +43,8 @@
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
</del><ins>+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
</ins><span class="cx"> 
</span><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="lines">@@ -566,7 +566,7 @@
</span><span class="cx">             )
</span><span class="cx">             if qualifiers is not None:
</span><span class="cx"> 
</span><del>-                today = PyCalendarDateTime.getToday()
</del><ins>+                today = DateTime.getToday()
</ins><span class="cx"> 
</span><span class="cx">                 # Determine how far we need to extend the current expansion of
</span><span class="cx">                 # events. If we have an open-ended time-range we will expand
</span><span class="lines">@@ -578,11 +578,11 @@
</span><span class="cx">                     maxDate = maxDate.duplicate()
</span><span class="cx">                     maxDate.offsetDay(1)
</span><span class="cx">                     maxDate.setDateOnly(True)
</span><del>-                    upperLimit = today + PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)
</del><ins>+                    upperLimit = today + Duration(days=config.FreeBusyIndexExpandMaxDays)
</ins><span class="cx">                     if maxDate &gt; upperLimit:
</span><span class="cx">                         raise TimeRangeUpperLimit(upperLimit)
</span><span class="cx">                     if isStartDate:
</span><del>-                        maxDate += PyCalendarDuration(days=365)
</del><ins>+                        maxDate += Duration(days=365)
</ins><span class="cx"> 
</span><span class="cx">                 # Determine if the start date is too early for the restricted range we
</span><span class="cx">                 # are applying. If it is today or later we don't need to worry about truncation
</span><span class="lines">@@ -591,7 +591,7 @@
</span><span class="cx">                 if minDate &gt;= today:
</span><span class="cx">                     minDate = None
</span><span class="cx">                 if minDate is not None and config.FreeBusyIndexLowerLimitDays:
</span><del>-                    truncateLowerLimit = today - PyCalendarDuration(days=config.FreeBusyIndexLowerLimitDays)
</del><ins>+                    truncateLowerLimit = today - Duration(days=config.FreeBusyIndexLowerLimitDays)
</ins><span class="cx">                     if minDate &lt; truncateLowerLimit:
</span><span class="cx">                         raise TimeRangeLowerLimit(truncateLowerLimit)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemacurrentoracledialectsql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">     &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
</span><span class="cx">     &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
</span><span class="cx">     &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
</span><ins>+    &quot;DEFAULT_POLLS&quot; integer default null references CALENDAR on delete set null,
</ins><span class="cx">     &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
</span><span class="cx">     &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
</span><span class="cx">     &quot;ALARM_VTODO_TIMED&quot; nclob default null,
</span><span class="lines">@@ -365,7 +366,7 @@
</span><span class="cx">     &quot;VALUE&quot; nvarchar2(255)
</span><span class="cx"> );
</span><span class="cx"> 
</span><del>-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '26');
</del><ins>+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '27');
</ins><span class="cx"> insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
</span><span class="cx"> insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
</span><span class="cx"> create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
</span><span class="lines">@@ -376,6 +377,10 @@
</span><span class="cx">     DEFAULT_TASKS
</span><span class="cx"> );
</span><span class="cx"> 
</span><ins>+create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
+    DEFAULT_POLLS
+);
+
</ins><span class="cx"> create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
</span><span class="cx">     NOTIFICATION_HOME_RESOURCE_ID
</span><span class="cx"> );
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemacurrentsql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx">   QUOTA_USED_BYTES         integer     default 0 not null,
</span><span class="cx">   DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
</span><span class="cx">   DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
</span><ins>+  DEFAULT_POLLS            integer     default null references CALENDAR on delete set null,
</ins><span class="cx">   ALARM_VEVENT_TIMED       text        default null,
</span><span class="cx">   ALARM_VEVENT_ALLDAY      text        default null,
</span><span class="cx">   ALARM_VTODO_TIMED        text        default null,
</span><span class="lines">@@ -87,6 +88,8 @@
</span><span class="cx">         CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
</span><span class="cx"> create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
</span><span class="cx">         CALENDAR_HOME_METADATA(DEFAULT_TASKS);
</span><ins>+create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
+        CALENDAR_HOME_METADATA(DEFAULT_POLLS);
</ins><span class="cx"> 
</span><span class="cx"> -----------------------
</span><span class="cx"> -- Calendar Metadata --
</span><span class="lines">@@ -695,6 +698,6 @@
</span><span class="cx">   VALUE                         varchar(255)
</span><span class="cx"> );
</span><span class="cx"> 
</span><del>-insert into CALENDARSERVER values ('VERSION', '26');
</del><ins>+insert into CALENDARSERVER values ('VERSION', '27');
</ins><span class="cx"> insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
</span><span class="cx"> insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv24sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,491 +0,0 @@
</span><del>-create sequence RESOURCE_ID_SEQ;
-create sequence INSTANCE_ID_SEQ;
-create sequence ATTACHMENT_ID_SEQ;
-create sequence REVISION_SEQ;
-create sequence WORKITEM_SEQ;
-create table NODE_INFO (
-    &quot;HOSTNAME&quot; nvarchar2(255),
-    &quot;PID&quot; integer not null,
-    &quot;PORT&quot; integer not null,
-    &quot;TIME&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
-    primary key(&quot;HOSTNAME&quot;, &quot;PORT&quot;)
-);
-
-create table NAMED_LOCK (
-    &quot;LOCK_NAME&quot; nvarchar2(255) primary key
-);
-
-create table CALENDAR_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique,
-    &quot;DATAVERSION&quot; integer default 0 not null
-);
-
-create table CALENDAR (
-    &quot;RESOURCE_ID&quot; integer primary key
-);
-
-create table CALENDAR_HOME_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
-    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
-    &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
-    &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
-    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
-    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
-    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
-    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
-    &quot;AVAILABILITY&quot; nclob default null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR on delete cascade,
-    &quot;SUPPORTED_COMPONENTS&quot; nvarchar2(255) default null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table NOTIFICATION_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique
-);
-
-create table NOTIFICATION (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME,
-    &quot;NOTIFICATION_UID&quot; nvarchar2(255),
-    &quot;XML_TYPE&quot; nvarchar2(255),
-    &quot;XML_DATA&quot; nclob,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;NOTIFICATION_UID&quot;, &quot;NOTIFICATION_HOME_RESOURCE_ID&quot;)
-);
-
-create table CALENDAR_BIND (
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;CALENDAR_RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob,
-    &quot;TRANSP&quot; integer default 0 not null,
-    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
-    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
-    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
-    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
-    &quot;TIMEZONE&quot; nclob default null, 
-    primary key(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_ID&quot;), 
-    unique(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_NAME&quot;)
-);
-
-create table CALENDAR_BIND_MODE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
-create table CALENDAR_BIND_STATUS (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
-create table CALENDAR_TRANSP (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
-insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
-create table CALENDAR_OBJECT (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob,
-    &quot;ICALENDAR_UID&quot; nvarchar2(255),
-    &quot;ICALENDAR_TYPE&quot; nvarchar2(255),
-    &quot;ATTACHMENTS_MODE&quot; integer default 0 not null,
-    &quot;DROPBOX_ID&quot; nvarchar2(255),
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;RECURRANCE_MIN&quot; date,
-    &quot;RECURRANCE_MAX&quot; date,
-    &quot;ACCESS&quot; integer default 0 not null,
-    &quot;SCHEDULE_OBJECT&quot; integer default 0,
-    &quot;SCHEDULE_TAG&quot; nvarchar2(36) default null,
-    &quot;SCHEDULE_ETAGS&quot; nclob default null,
-    &quot;PRIVATE_COMMENTS&quot; integer default 0 not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;CALENDAR_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
-);
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MO (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
-create table CALENDAR_ACCESS_TYPE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(32) unique
-);
-
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
-create table TIME_RANGE (
-    &quot;INSTANCE_ID&quot; integer primary key,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade,
-    &quot;FLOATING&quot; integer not null,
-    &quot;START_DATE&quot; timestamp not null,
-    &quot;END_DATE&quot; timestamp not null,
-    &quot;FBTYPE&quot; integer not null,
-    &quot;TRANSPARENT&quot; integer not null
-);
-
-create table FREE_BUSY_TYPE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
-create table TRANSPARENCY (
-    &quot;TIME_RANGE_INSTANCE_ID&quot; integer not null references TIME_RANGE on delete cascade,
-    &quot;USER_ID&quot; nvarchar2(255),
-    &quot;TRANSPARENT&quot; integer not null
-);
-
-create table ATTACHMENT (
-    &quot;ATTACHMENT_ID&quot; integer primary key,
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;DROPBOX_ID&quot; nvarchar2(255),
-    &quot;CONTENT_TYPE&quot; nvarchar2(255),
-    &quot;SIZE&quot; integer not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;PATH&quot; nvarchar2(1024)
-);
-
-create table ATTACHMENT_CALENDAR_OBJECT (
-    &quot;ATTACHMENT_ID&quot; integer not null references ATTACHMENT on delete cascade,
-    &quot;MANAGED_ID&quot; nvarchar2(255),
-    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade, 
-    primary key(&quot;ATTACHMENT_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;), 
-    unique(&quot;MANAGED_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;)
-);
-
-create table RESOURCE_PROPERTY (
-    &quot;RESOURCE_ID&quot; integer not null,
-    &quot;NAME&quot; nvarchar2(255),
-    &quot;VALUE&quot; nclob,
-    &quot;VIEWER_UID&quot; nvarchar2(255), 
-    primary key(&quot;RESOURCE_ID&quot;, &quot;NAME&quot;, &quot;VIEWER_UID&quot;)
-);
-
-create table ADDRESSBOOK_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;ADDRESSBOOK_PROPERTY_STORE_ID&quot; integer not null,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique,
-    &quot;DATAVERSION&quot; integer default 0 not null
-);
-
-create table ADDRESSBOOK_HOME_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references ADDRESSBOOK_HOME on delete cascade,
-    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table SHARED_ADDRESSBOOK_BIND (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;OWNER_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;ADDRESSBOOK_RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob, 
-    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;OWNER_HOME_RESOURCE_ID&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;ADDRESSBOOK_RESOURCE_NAME&quot;)
-);
-
-create table ADDRESSBOOK_OBJECT (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;VCARD_TEXT&quot; nclob,
-    &quot;VCARD_UID&quot; nvarchar2(255),
-    &quot;KIND&quot; integer not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;VCARD_UID&quot;)
-);
-
-create table ADDRESSBOOK_OBJECT_KIND (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
-create table ABO_MEMBERS (
-    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;MEMBER_ID&quot; integer not null references ADDRESSBOOK_OBJECT, 
-    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ID&quot;)
-);
-
-create table ABO_FOREIGN_MEMBERS (
-    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;MEMBER_ADDRESS&quot; nvarchar2(255), 
-    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ADDRESS&quot;)
-);
-
-create table SHARED_GROUP_BIND (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;GROUP_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;GROUP_ADDRESSBOOK_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob, 
-    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_RESOURCE_ID&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_ADDRESSBOOK_NAME&quot;)
-);
-
-create table CALENDAR_OBJECT_REVISIONS (
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer references CALENDAR,
-    &quot;CALENDAR_NAME&quot; nvarchar2(255) default null,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null
-);
-
-create table ADDRESSBOOK_OBJECT_REVISIONS (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;OWNER_HOME_RESOURCE_ID&quot; integer references ADDRESSBOOK_HOME,
-    &quot;ADDRESSBOOK_NAME&quot; nvarchar2(255) default null,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null
-);
-
-create table NOTIFICATION_OBJECT_REVISIONS (
-    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null, 
-    unique(&quot;NOTIFICATION_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
-);
-
-create table APN_SUBSCRIPTIONS (
-    &quot;TOKEN&quot; nvarchar2(255),
-    &quot;RESOURCE_KEY&quot; nvarchar2(255),
-    &quot;MODIFIED&quot; integer not null,
-    &quot;SUBSCRIBER_GUID&quot; nvarchar2(255),
-    &quot;USER_AGENT&quot; nvarchar2(255) default null,
-    &quot;IP_ADDR&quot; nvarchar2(255) default null, 
-    primary key(&quot;TOKEN&quot;, &quot;RESOURCE_KEY&quot;)
-);
-
-create table IMIP_TOKENS (
-    &quot;TOKEN&quot; nvarchar2(255),
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;ATTENDEE&quot; nvarchar2(255),
-    &quot;ICALUID&quot; nvarchar2(255),
-    &quot;ACCESSED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    primary key(&quot;ORGANIZER&quot;, &quot;ATTENDEE&quot;, &quot;ICALUID&quot;)
-);
-
-create table IMIP_INVITATION_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;FROM_ADDR&quot; nvarchar2(255),
-    &quot;TO_ADDR&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob
-);
-
-create table IMIP_POLLING_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table IMIP_REPLY_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;ATTENDEE&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob
-);
-
-create table PUSH_NOTIFICATION_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;PUSH_ID&quot; nvarchar2(255)
-);
-
-create table GROUP_CACHER_POLLING_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade
-);
-
-create table CALENDARSERVER (
-    &quot;NAME&quot; nvarchar2(255) primary key,
-    &quot;VALUE&quot; nvarchar2(255)
-);
-
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '24');
-insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
-insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
-create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
-    DEFAULT_EVENTS
-);
-
-create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
-    DEFAULT_TASKS
-);
-
-create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
-    NOTIFICATION_HOME_RESOURCE_ID
-);
-
-create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
-    CALENDAR_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
-    CALENDAR_RESOURCE_ID,
-    ICALENDAR_UID
-);
-
-create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
-    CALENDAR_RESOURCE_ID,
-    RECURRANCE_MAX
-);
-
-create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
-    ICALENDAR_UID
-);
-
-create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
-    DROPBOX_ID
-);
-
-create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
-    CALENDAR_RESOURCE_ID
-);
-
-create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
-    CALENDAR_OBJECT_RESOURCE_ID
-);
-
-create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
-    TIME_RANGE_INSTANCE_ID
-);
-
-create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
-    CALENDAR_HOME_RESOURCE_ID
-);
-
-create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
-    CALENDAR_OBJECT_RESOURCE_ID
-);
-
-create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
-    OWNER_HOME_RESOURCE_ID
-);
-
-create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
-    ADDRESSBOOK_ID
-);
-
-create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
-    MEMBER_ID
-);
-
-create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
-    ADDRESSBOOK_ID
-);
-
-create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
-    GROUP_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_HOME_RESOURCE_ID,
-    CALENDAR_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_REVIS_2643d556 on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_RESOURCE_ID,
-    RESOURCE_NAME
-);
-
-create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_RESOURCE_ID,
-    REVISION
-);
-
-create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
-    ADDRESSBOOK_HOME_RESOURCE_ID,
-    OWNER_HOME_RESOURCE_ID
-);
-
-create index ADDRESSBOOK_OBJECT_RE_980b9872 on ADDRESSBOOK_OBJECT_REVISIONS (
-    OWNER_HOME_RESOURCE_ID,
-    RESOURCE_NAME
-);
-
-create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
-    OWNER_HOME_RESOURCE_ID,
-    REVISION
-);
-
-create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
-    NOTIFICATION_HOME_RESOURCE_ID,
-    REVISION
-);
-
-create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
-    RESOURCE_KEY
-);
-
-create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
-    TOKEN
-);
-
-create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
-    RESOURCE_ID
-);
-
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv24sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldoracledialectv24sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,491 @@
</span><ins>+create sequence RESOURCE_ID_SEQ;
+create sequence INSTANCE_ID_SEQ;
+create sequence ATTACHMENT_ID_SEQ;
+create sequence REVISION_SEQ;
+create sequence WORKITEM_SEQ;
+create table NODE_INFO (
+    &quot;HOSTNAME&quot; nvarchar2(255),
+    &quot;PID&quot; integer not null,
+    &quot;PORT&quot; integer not null,
+    &quot;TIME&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
+    primary key(&quot;HOSTNAME&quot;, &quot;PORT&quot;)
+);
+
+create table NAMED_LOCK (
+    &quot;LOCK_NAME&quot; nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table CALENDAR (
+    &quot;RESOURCE_ID&quot; integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
+    &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;AVAILABILITY&quot; nclob default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR on delete cascade,
+    &quot;SUPPORTED_COMPONENTS&quot; nvarchar2(255) default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME,
+    &quot;NOTIFICATION_UID&quot; nvarchar2(255),
+    &quot;XML_TYPE&quot; nvarchar2(255),
+    &quot;XML_DATA&quot; nclob,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;NOTIFICATION_UID&quot;, &quot;NOTIFICATION_HOME_RESOURCE_ID&quot;)
+);
+
+create table CALENDAR_BIND (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob,
+    &quot;TRANSP&quot; integer default 0 not null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;TIMEZONE&quot; nclob default null, 
+    primary key(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_ID&quot;), 
+    unique(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_BIND_MODE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
+create table CALENDAR_BIND_STATUS (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_TRANSP (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
+create table CALENDAR_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob,
+    &quot;ICALENDAR_UID&quot; nvarchar2(255),
+    &quot;ICALENDAR_TYPE&quot; nvarchar2(255),
+    &quot;ATTACHMENTS_MODE&quot; integer default 0 not null,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;RECURRANCE_MIN&quot; date,
+    &quot;RECURRANCE_MAX&quot; date,
+    &quot;ACCESS&quot; integer default 0 not null,
+    &quot;SCHEDULE_OBJECT&quot; integer default 0,
+    &quot;SCHEDULE_TAG&quot; nvarchar2(36) default null,
+    &quot;SCHEDULE_ETAGS&quot; nclob default null,
+    &quot;PRIVATE_COMMENTS&quot; integer default 0 not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;CALENDAR_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
+create table CALENDAR_ACCESS_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(32) unique
+);
+
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
+create table TIME_RANGE (
+    &quot;INSTANCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade,
+    &quot;FLOATING&quot; integer not null,
+    &quot;START_DATE&quot; timestamp not null,
+    &quot;END_DATE&quot; timestamp not null,
+    &quot;FBTYPE&quot; integer not null,
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table FREE_BUSY_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
+create table TRANSPARENCY (
+    &quot;TIME_RANGE_INSTANCE_ID&quot; integer not null references TIME_RANGE on delete cascade,
+    &quot;USER_ID&quot; nvarchar2(255),
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table ATTACHMENT (
+    &quot;ATTACHMENT_ID&quot; integer primary key,
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;CONTENT_TYPE&quot; nvarchar2(255),
+    &quot;SIZE&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PATH&quot; nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+    &quot;ATTACHMENT_ID&quot; integer not null references ATTACHMENT on delete cascade,
+    &quot;MANAGED_ID&quot; nvarchar2(255),
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade, 
+    primary key(&quot;ATTACHMENT_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;), 
+    unique(&quot;MANAGED_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;)
+);
+
+create table RESOURCE_PROPERTY (
+    &quot;RESOURCE_ID&quot; integer not null,
+    &quot;NAME&quot; nvarchar2(255),
+    &quot;VALUE&quot; nclob,
+    &quot;VIEWER_UID&quot; nvarchar2(255), 
+    primary key(&quot;RESOURCE_ID&quot;, &quot;NAME&quot;, &quot;VIEWER_UID&quot;)
+);
+
+create table ADDRESSBOOK_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_PROPERTY_STORE_ID&quot; integer not null,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references ADDRESSBOOK_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table SHARED_ADDRESSBOOK_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;ADDRESSBOOK_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;OWNER_HOME_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;ADDRESSBOOK_RESOURCE_NAME&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;VCARD_TEXT&quot; nclob,
+    &quot;VCARD_UID&quot; nvarchar2(255),
+    &quot;KIND&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;VCARD_UID&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
+create table ABO_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ID&quot; integer not null references ADDRESSBOOK_OBJECT, 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ID&quot;)
+);
+
+create table ABO_FOREIGN_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ADDRESS&quot; nvarchar2(255), 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ADDRESS&quot;)
+);
+
+create table SHARED_GROUP_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;GROUP_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;GROUP_ADDRESSBOOK_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_ADDRESSBOOK_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer references CALENDAR,
+    &quot;CALENDAR_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer references ADDRESSBOOK_HOME,
+    &quot;ADDRESSBOOK_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null, 
+    unique(&quot;NOTIFICATION_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table APN_SUBSCRIPTIONS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;RESOURCE_KEY&quot; nvarchar2(255),
+    &quot;MODIFIED&quot; integer not null,
+    &quot;SUBSCRIBER_GUID&quot; nvarchar2(255),
+    &quot;USER_AGENT&quot; nvarchar2(255) default null,
+    &quot;IP_ADDR&quot; nvarchar2(255) default null, 
+    primary key(&quot;TOKEN&quot;, &quot;RESOURCE_KEY&quot;)
+);
+
+create table IMIP_TOKENS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALUID&quot; nvarchar2(255),
+    &quot;ACCESSED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    primary key(&quot;ORGANIZER&quot;, &quot;ATTENDEE&quot;, &quot;ICALUID&quot;)
+);
+
+create table IMIP_INVITATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;FROM_ADDR&quot; nvarchar2(255),
+    &quot;TO_ADDR&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table IMIP_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PUSH_ID&quot; nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+    &quot;NAME&quot; nvarchar2(255) primary key,
+    &quot;VALUE&quot; nvarchar2(255)
+);
+
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '24');
+insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
+create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
+    DEFAULT_EVENTS
+);
+
+create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
+    DEFAULT_TASKS
+);
+
+create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
+    NOTIFICATION_HOME_RESOURCE_ID
+);
+
+create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    RECURRANCE_MAX
+);
+
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
+    DROPBOX_ID
+);
+
+create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
+    CALENDAR_RESOURCE_ID
+);
+
+create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
+    TIME_RANGE_INSTANCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
+    CALENDAR_HOME_RESOURCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
+    MEMBER_ID
+);
+
+create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
+    GROUP_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_HOME_RESOURCE_ID,
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_2643d556 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_HOME_RESOURCE_ID,
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_OBJECT_RE_980b9872 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
+    NOTIFICATION_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
+    RESOURCE_KEY
+);
+
+create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
+    TOKEN
+);
+
+create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
+    RESOURCE_ID
+);
+
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv25sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,491 +0,0 @@
</span><del>-create sequence RESOURCE_ID_SEQ;
-create sequence INSTANCE_ID_SEQ;
-create sequence ATTACHMENT_ID_SEQ;
-create sequence REVISION_SEQ;
-create sequence WORKITEM_SEQ;
-create table NODE_INFO (
-    &quot;HOSTNAME&quot; nvarchar2(255),
-    &quot;PID&quot; integer not null,
-    &quot;PORT&quot; integer not null,
-    &quot;TIME&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
-    primary key(&quot;HOSTNAME&quot;, &quot;PORT&quot;)
-);
-
-create table NAMED_LOCK (
-    &quot;LOCK_NAME&quot; nvarchar2(255) primary key
-);
-
-create table CALENDAR_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique,
-    &quot;DATAVERSION&quot; integer default 0 not null
-);
-
-create table CALENDAR (
-    &quot;RESOURCE_ID&quot; integer primary key
-);
-
-create table CALENDAR_HOME_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
-    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
-    &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
-    &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
-    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
-    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
-    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
-    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
-    &quot;AVAILABILITY&quot; nclob default null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR on delete cascade,
-    &quot;SUPPORTED_COMPONENTS&quot; nvarchar2(255) default null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table NOTIFICATION_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique
-);
-
-create table NOTIFICATION (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME,
-    &quot;NOTIFICATION_UID&quot; nvarchar2(255),
-    &quot;XML_TYPE&quot; nvarchar2(255),
-    &quot;XML_DATA&quot; nclob,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;NOTIFICATION_UID&quot;, &quot;NOTIFICATION_HOME_RESOURCE_ID&quot;)
-);
-
-create table CALENDAR_BIND (
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;CALENDAR_RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob,
-    &quot;TRANSP&quot; integer default 0 not null,
-    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
-    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
-    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
-    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
-    &quot;TIMEZONE&quot; nclob default null, 
-    primary key(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_ID&quot;), 
-    unique(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_NAME&quot;)
-);
-
-create table CALENDAR_BIND_MODE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
-create table CALENDAR_BIND_STATUS (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
-create table CALENDAR_TRANSP (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
-insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
-create table CALENDAR_OBJECT (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob,
-    &quot;ICALENDAR_UID&quot; nvarchar2(255),
-    &quot;ICALENDAR_TYPE&quot; nvarchar2(255),
-    &quot;ATTACHMENTS_MODE&quot; integer default 0 not null,
-    &quot;DROPBOX_ID&quot; nvarchar2(255),
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;RECURRANCE_MIN&quot; date,
-    &quot;RECURRANCE_MAX&quot; date,
-    &quot;ACCESS&quot; integer default 0 not null,
-    &quot;SCHEDULE_OBJECT&quot; integer default 0,
-    &quot;SCHEDULE_TAG&quot; nvarchar2(36) default null,
-    &quot;SCHEDULE_ETAGS&quot; nclob default null,
-    &quot;PRIVATE_COMMENTS&quot; integer default 0 not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;CALENDAR_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
-);
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MO (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
-insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
-create table CALENDAR_ACCESS_TYPE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(32) unique
-);
-
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
-insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
-create table TIME_RANGE (
-    &quot;INSTANCE_ID&quot; integer primary key,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
-    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade,
-    &quot;FLOATING&quot; integer not null,
-    &quot;START_DATE&quot; timestamp not null,
-    &quot;END_DATE&quot; timestamp not null,
-    &quot;FBTYPE&quot; integer not null,
-    &quot;TRANSPARENT&quot; integer not null
-);
-
-create table FREE_BUSY_TYPE (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
-insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
-create table TRANSPARENCY (
-    &quot;TIME_RANGE_INSTANCE_ID&quot; integer not null references TIME_RANGE on delete cascade,
-    &quot;USER_ID&quot; nvarchar2(255),
-    &quot;TRANSPARENT&quot; integer not null
-);
-
-create table ATTACHMENT (
-    &quot;ATTACHMENT_ID&quot; integer primary key,
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;DROPBOX_ID&quot; nvarchar2(255),
-    &quot;CONTENT_TYPE&quot; nvarchar2(255),
-    &quot;SIZE&quot; integer not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;PATH&quot; nvarchar2(1024)
-);
-
-create table ATTACHMENT_CALENDAR_OBJECT (
-    &quot;ATTACHMENT_ID&quot; integer not null references ATTACHMENT on delete cascade,
-    &quot;MANAGED_ID&quot; nvarchar2(255),
-    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade, 
-    primary key(&quot;ATTACHMENT_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;), 
-    unique(&quot;MANAGED_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;)
-);
-
-create table RESOURCE_PROPERTY (
-    &quot;RESOURCE_ID&quot; integer not null,
-    &quot;NAME&quot; nvarchar2(255),
-    &quot;VALUE&quot; nclob,
-    &quot;VIEWER_UID&quot; nvarchar2(255), 
-    primary key(&quot;RESOURCE_ID&quot;, &quot;NAME&quot;, &quot;VIEWER_UID&quot;)
-);
-
-create table ADDRESSBOOK_HOME (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;ADDRESSBOOK_PROPERTY_STORE_ID&quot; integer not null,
-    &quot;OWNER_UID&quot; nvarchar2(255) unique,
-    &quot;DATAVERSION&quot; integer default 0 not null
-);
-
-create table ADDRESSBOOK_HOME_METADATA (
-    &quot;RESOURCE_ID&quot; integer primary key references ADDRESSBOOK_HOME on delete cascade,
-    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table SHARED_ADDRESSBOOK_BIND (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;OWNER_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;ADDRESSBOOK_RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob, 
-    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;OWNER_HOME_RESOURCE_ID&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;ADDRESSBOOK_RESOURCE_NAME&quot;)
-);
-
-create table ADDRESSBOOK_OBJECT (
-    &quot;RESOURCE_ID&quot; integer primary key,
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;VCARD_TEXT&quot; nclob,
-    &quot;VCARD_UID&quot; nvarchar2(255),
-    &quot;KIND&quot; integer not null,
-    &quot;MD5&quot; nchar(32),
-    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;VCARD_UID&quot;)
-);
-
-create table ADDRESSBOOK_OBJECT_KIND (
-    &quot;ID&quot; integer primary key,
-    &quot;DESCRIPTION&quot; nvarchar2(16) unique
-);
-
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
-insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
-create table ABO_MEMBERS (
-    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;MEMBER_ID&quot; integer not null references ADDRESSBOOK_OBJECT, 
-    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ID&quot;)
-);
-
-create table ABO_FOREIGN_MEMBERS (
-    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
-    &quot;MEMBER_ADDRESS&quot; nvarchar2(255), 
-    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ADDRESS&quot;)
-);
-
-create table SHARED_GROUP_BIND (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;GROUP_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
-    &quot;GROUP_ADDRESSBOOK_NAME&quot; nvarchar2(255),
-    &quot;BIND_MODE&quot; integer not null,
-    &quot;BIND_STATUS&quot; integer not null,
-    &quot;BIND_REVISION&quot; integer default 0 not null,
-    &quot;MESSAGE&quot; nclob, 
-    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_RESOURCE_ID&quot;), 
-    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_ADDRESSBOOK_NAME&quot;)
-);
-
-create table CALENDAR_OBJECT_REVISIONS (
-    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
-    &quot;CALENDAR_RESOURCE_ID&quot; integer references CALENDAR,
-    &quot;CALENDAR_NAME&quot; nvarchar2(255) default null,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null
-);
-
-create table ADDRESSBOOK_OBJECT_REVISIONS (
-    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
-    &quot;OWNER_HOME_RESOURCE_ID&quot; integer references ADDRESSBOOK_HOME,
-    &quot;ADDRESSBOOK_NAME&quot; nvarchar2(255) default null,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null
-);
-
-create table NOTIFICATION_OBJECT_REVISIONS (
-    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME on delete cascade,
-    &quot;RESOURCE_NAME&quot; nvarchar2(255),
-    &quot;REVISION&quot; integer not null,
-    &quot;DELETED&quot; integer not null, 
-    unique(&quot;NOTIFICATION_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
-);
-
-create table APN_SUBSCRIPTIONS (
-    &quot;TOKEN&quot; nvarchar2(255),
-    &quot;RESOURCE_KEY&quot; nvarchar2(255),
-    &quot;MODIFIED&quot; integer not null,
-    &quot;SUBSCRIBER_GUID&quot; nvarchar2(255),
-    &quot;USER_AGENT&quot; nvarchar2(255) default null,
-    &quot;IP_ADDR&quot; nvarchar2(255) default null, 
-    primary key(&quot;TOKEN&quot;, &quot;RESOURCE_KEY&quot;)
-);
-
-create table IMIP_TOKENS (
-    &quot;TOKEN&quot; nvarchar2(255),
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;ATTENDEE&quot; nvarchar2(255),
-    &quot;ICALUID&quot; nvarchar2(255),
-    &quot;ACCESSED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
-    primary key(&quot;ORGANIZER&quot;, &quot;ATTENDEE&quot;, &quot;ICALUID&quot;)
-);
-
-create table IMIP_INVITATION_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;FROM_ADDR&quot; nvarchar2(255),
-    &quot;TO_ADDR&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob
-);
-
-create table IMIP_POLLING_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table IMIP_REPLY_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;ORGANIZER&quot; nvarchar2(255),
-    &quot;ATTENDEE&quot; nvarchar2(255),
-    &quot;ICALENDAR_TEXT&quot; nclob
-);
-
-create table PUSH_NOTIFICATION_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;PUSH_ID&quot; nvarchar2(255)
-);
-
-create table GROUP_CACHER_POLLING_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
-    &quot;WORK_ID&quot; integer primary key not null,
-    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
-    &quot;RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade
-);
-
-create table CALENDARSERVER (
-    &quot;NAME&quot; nvarchar2(255) primary key,
-    &quot;VALUE&quot; nvarchar2(255)
-);
-
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '25');
-insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
-insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
-create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
-    DEFAULT_EVENTS
-);
-
-create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
-    DEFAULT_TASKS
-);
-
-create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
-    NOTIFICATION_HOME_RESOURCE_ID
-);
-
-create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
-    CALENDAR_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
-    CALENDAR_RESOURCE_ID,
-    ICALENDAR_UID
-);
-
-create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
-    CALENDAR_RESOURCE_ID,
-    RECURRANCE_MAX
-);
-
-create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
-    ICALENDAR_UID
-);
-
-create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
-    DROPBOX_ID
-);
-
-create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
-    CALENDAR_RESOURCE_ID
-);
-
-create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
-    CALENDAR_OBJECT_RESOURCE_ID
-);
-
-create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
-    TIME_RANGE_INSTANCE_ID
-);
-
-create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
-    CALENDAR_HOME_RESOURCE_ID
-);
-
-create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
-    CALENDAR_OBJECT_RESOURCE_ID
-);
-
-create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
-    OWNER_HOME_RESOURCE_ID
-);
-
-create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
-    ADDRESSBOOK_ID
-);
-
-create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
-    MEMBER_ID
-);
-
-create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
-    ADDRESSBOOK_ID
-);
-
-create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
-    GROUP_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_HOME_RESOURCE_ID,
-    CALENDAR_RESOURCE_ID
-);
-
-create index CALENDAR_OBJECT_REVIS_2643d556 on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_RESOURCE_ID,
-    RESOURCE_NAME
-);
-
-create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_RESOURCE_ID,
-    REVISION
-);
-
-create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
-    ADDRESSBOOK_HOME_RESOURCE_ID,
-    OWNER_HOME_RESOURCE_ID
-);
-
-create index ADDRESSBOOK_OBJECT_RE_980b9872 on ADDRESSBOOK_OBJECT_REVISIONS (
-    OWNER_HOME_RESOURCE_ID,
-    RESOURCE_NAME
-);
-
-create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
-    OWNER_HOME_RESOURCE_ID,
-    REVISION
-);
-
-create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
-    NOTIFICATION_HOME_RESOURCE_ID,
-    REVISION
-);
-
-create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
-    RESOURCE_KEY
-);
-
-create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
-    TOKEN
-);
-
-create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
-    RESOURCE_ID
-);
-
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv25sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldoracledialectv25sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,491 @@
</span><ins>+create sequence RESOURCE_ID_SEQ;
+create sequence INSTANCE_ID_SEQ;
+create sequence ATTACHMENT_ID_SEQ;
+create sequence REVISION_SEQ;
+create sequence WORKITEM_SEQ;
+create table NODE_INFO (
+    &quot;HOSTNAME&quot; nvarchar2(255),
+    &quot;PID&quot; integer not null,
+    &quot;PORT&quot; integer not null,
+    &quot;TIME&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
+    primary key(&quot;HOSTNAME&quot;, &quot;PORT&quot;)
+);
+
+create table NAMED_LOCK (
+    &quot;LOCK_NAME&quot; nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table CALENDAR (
+    &quot;RESOURCE_ID&quot; integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
+    &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;AVAILABILITY&quot; nclob default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR on delete cascade,
+    &quot;SUPPORTED_COMPONENTS&quot; nvarchar2(255) default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME,
+    &quot;NOTIFICATION_UID&quot; nvarchar2(255),
+    &quot;XML_TYPE&quot; nvarchar2(255),
+    &quot;XML_DATA&quot; nclob,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;NOTIFICATION_UID&quot;, &quot;NOTIFICATION_HOME_RESOURCE_ID&quot;)
+);
+
+create table CALENDAR_BIND (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob,
+    &quot;TRANSP&quot; integer default 0 not null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;TIMEZONE&quot; nclob default null, 
+    primary key(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_ID&quot;), 
+    unique(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_BIND_MODE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
+create table CALENDAR_BIND_STATUS (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_TRANSP (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
+create table CALENDAR_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob,
+    &quot;ICALENDAR_UID&quot; nvarchar2(255),
+    &quot;ICALENDAR_TYPE&quot; nvarchar2(255),
+    &quot;ATTACHMENTS_MODE&quot; integer default 0 not null,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;RECURRANCE_MIN&quot; date,
+    &quot;RECURRANCE_MAX&quot; date,
+    &quot;ACCESS&quot; integer default 0 not null,
+    &quot;SCHEDULE_OBJECT&quot; integer default 0,
+    &quot;SCHEDULE_TAG&quot; nvarchar2(36) default null,
+    &quot;SCHEDULE_ETAGS&quot; nclob default null,
+    &quot;PRIVATE_COMMENTS&quot; integer default 0 not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;CALENDAR_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
+create table CALENDAR_ACCESS_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(32) unique
+);
+
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
+create table TIME_RANGE (
+    &quot;INSTANCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade,
+    &quot;FLOATING&quot; integer not null,
+    &quot;START_DATE&quot; timestamp not null,
+    &quot;END_DATE&quot; timestamp not null,
+    &quot;FBTYPE&quot; integer not null,
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table FREE_BUSY_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
+create table TRANSPARENCY (
+    &quot;TIME_RANGE_INSTANCE_ID&quot; integer not null references TIME_RANGE on delete cascade,
+    &quot;USER_ID&quot; nvarchar2(255),
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table ATTACHMENT (
+    &quot;ATTACHMENT_ID&quot; integer primary key,
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;CONTENT_TYPE&quot; nvarchar2(255),
+    &quot;SIZE&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PATH&quot; nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+    &quot;ATTACHMENT_ID&quot; integer not null references ATTACHMENT on delete cascade,
+    &quot;MANAGED_ID&quot; nvarchar2(255),
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade, 
+    primary key(&quot;ATTACHMENT_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;), 
+    unique(&quot;MANAGED_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;)
+);
+
+create table RESOURCE_PROPERTY (
+    &quot;RESOURCE_ID&quot; integer not null,
+    &quot;NAME&quot; nvarchar2(255),
+    &quot;VALUE&quot; nclob,
+    &quot;VIEWER_UID&quot; nvarchar2(255), 
+    primary key(&quot;RESOURCE_ID&quot;, &quot;NAME&quot;, &quot;VIEWER_UID&quot;)
+);
+
+create table ADDRESSBOOK_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_PROPERTY_STORE_ID&quot; integer not null,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references ADDRESSBOOK_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table SHARED_ADDRESSBOOK_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;ADDRESSBOOK_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;OWNER_HOME_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;ADDRESSBOOK_RESOURCE_NAME&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;VCARD_TEXT&quot; nclob,
+    &quot;VCARD_UID&quot; nvarchar2(255),
+    &quot;KIND&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;VCARD_UID&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
+create table ABO_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ID&quot; integer not null references ADDRESSBOOK_OBJECT, 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ID&quot;)
+);
+
+create table ABO_FOREIGN_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ADDRESS&quot; nvarchar2(255), 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ADDRESS&quot;)
+);
+
+create table SHARED_GROUP_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;GROUP_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;GROUP_ADDRESSBOOK_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_ADDRESSBOOK_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer references CALENDAR,
+    &quot;CALENDAR_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer references ADDRESSBOOK_HOME,
+    &quot;ADDRESSBOOK_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null, 
+    unique(&quot;NOTIFICATION_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table APN_SUBSCRIPTIONS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;RESOURCE_KEY&quot; nvarchar2(255),
+    &quot;MODIFIED&quot; integer not null,
+    &quot;SUBSCRIBER_GUID&quot; nvarchar2(255),
+    &quot;USER_AGENT&quot; nvarchar2(255) default null,
+    &quot;IP_ADDR&quot; nvarchar2(255) default null, 
+    primary key(&quot;TOKEN&quot;, &quot;RESOURCE_KEY&quot;)
+);
+
+create table IMIP_TOKENS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALUID&quot; nvarchar2(255),
+    &quot;ACCESSED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    primary key(&quot;ORGANIZER&quot;, &quot;ATTENDEE&quot;, &quot;ICALUID&quot;)
+);
+
+create table IMIP_INVITATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;FROM_ADDR&quot; nvarchar2(255),
+    &quot;TO_ADDR&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table IMIP_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PUSH_ID&quot; nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+    &quot;NAME&quot; nvarchar2(255) primary key,
+    &quot;VALUE&quot; nvarchar2(255)
+);
+
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '25');
+insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
+create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
+    DEFAULT_EVENTS
+);
+
+create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
+    DEFAULT_TASKS
+);
+
+create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
+    NOTIFICATION_HOME_RESOURCE_ID
+);
+
+create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    RECURRANCE_MAX
+);
+
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
+    DROPBOX_ID
+);
+
+create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
+    CALENDAR_RESOURCE_ID
+);
+
+create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
+    TIME_RANGE_INSTANCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
+    CALENDAR_HOME_RESOURCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
+    MEMBER_ID
+);
+
+create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
+    GROUP_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_HOME_RESOURCE_ID,
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_2643d556 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_HOME_RESOURCE_ID,
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_OBJECT_RE_980b9872 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
+    NOTIFICATION_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
+    RESOURCE_KEY
+);
+
+create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
+    TOKEN
+);
+
+create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
+    RESOURCE_ID
+);
+
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldoracledialectv26sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldoracledialectv26sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,495 @@
</span><ins>+create sequence RESOURCE_ID_SEQ;
+create sequence INSTANCE_ID_SEQ;
+create sequence ATTACHMENT_ID_SEQ;
+create sequence REVISION_SEQ;
+create sequence WORKITEM_SEQ;
+create table NODE_INFO (
+    &quot;HOSTNAME&quot; nvarchar2(255),
+    &quot;PID&quot; integer not null,
+    &quot;PORT&quot; integer not null,
+    &quot;TIME&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
+    primary key(&quot;HOSTNAME&quot;, &quot;PORT&quot;)
+);
+
+create table NAMED_LOCK (
+    &quot;LOCK_NAME&quot; nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table CALENDAR (
+    &quot;RESOURCE_ID&quot; integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
+    &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;AVAILABILITY&quot; nclob default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references CALENDAR on delete cascade,
+    &quot;SUPPORTED_COMPONENTS&quot; nvarchar2(255) default null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME,
+    &quot;NOTIFICATION_UID&quot; nvarchar2(255),
+    &quot;XML_TYPE&quot; nvarchar2(255),
+    &quot;XML_DATA&quot; nclob,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;NOTIFICATION_UID&quot;, &quot;NOTIFICATION_HOME_RESOURCE_ID&quot;)
+);
+
+create table CALENDAR_BIND (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob,
+    &quot;TRANSP&quot; integer default 0 not null,
+    &quot;ALARM_VEVENT_TIMED&quot; nclob default null,
+    &quot;ALARM_VEVENT_ALLDAY&quot; nclob default null,
+    &quot;ALARM_VTODO_TIMED&quot; nclob default null,
+    &quot;ALARM_VTODO_ALLDAY&quot; nclob default null,
+    &quot;TIMEZONE&quot; nclob default null, 
+    primary key(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_ID&quot;), 
+    unique(&quot;CALENDAR_HOME_RESOURCE_ID&quot;, &quot;CALENDAR_RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_BIND_MODE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
+create table CALENDAR_BIND_STATUS (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_TRANSP (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
+create table CALENDAR_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob,
+    &quot;ICALENDAR_UID&quot; nvarchar2(255),
+    &quot;ICALENDAR_TYPE&quot; nvarchar2(255),
+    &quot;ATTACHMENTS_MODE&quot; integer default 0 not null,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;RECURRANCE_MIN&quot; date,
+    &quot;RECURRANCE_MAX&quot; date,
+    &quot;ACCESS&quot; integer default 0 not null,
+    &quot;SCHEDULE_OBJECT&quot; integer default 0,
+    &quot;SCHEDULE_TAG&quot; nvarchar2(36) default null,
+    &quot;SCHEDULE_ETAGS&quot; nclob default null,
+    &quot;PRIVATE_COMMENTS&quot; integer default 0 not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;CALENDAR_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
+create table CALENDAR_ACCESS_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(32) unique
+);
+
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
+create table TIME_RANGE (
+    &quot;INSTANCE_ID&quot; integer primary key,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer not null references CALENDAR on delete cascade,
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade,
+    &quot;FLOATING&quot; integer not null,
+    &quot;START_DATE&quot; timestamp not null,
+    &quot;END_DATE&quot; timestamp not null,
+    &quot;FBTYPE&quot; integer not null,
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table FREE_BUSY_TYPE (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
+create table TRANSPARENCY (
+    &quot;TIME_RANGE_INSTANCE_ID&quot; integer not null references TIME_RANGE on delete cascade,
+    &quot;USER_ID&quot; nvarchar2(255),
+    &quot;TRANSPARENT&quot; integer not null
+);
+
+create table ATTACHMENT (
+    &quot;ATTACHMENT_ID&quot; integer primary key,
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;DROPBOX_ID&quot; nvarchar2(255),
+    &quot;CONTENT_TYPE&quot; nvarchar2(255),
+    &quot;SIZE&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PATH&quot; nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+    &quot;ATTACHMENT_ID&quot; integer not null references ATTACHMENT on delete cascade,
+    &quot;MANAGED_ID&quot; nvarchar2(255),
+    &quot;CALENDAR_OBJECT_RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade, 
+    primary key(&quot;ATTACHMENT_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;), 
+    unique(&quot;MANAGED_ID&quot;, &quot;CALENDAR_OBJECT_RESOURCE_ID&quot;)
+);
+
+create table RESOURCE_PROPERTY (
+    &quot;RESOURCE_ID&quot; integer not null,
+    &quot;NAME&quot; nvarchar2(255),
+    &quot;VALUE&quot; nclob,
+    &quot;VIEWER_UID&quot; nvarchar2(255), 
+    primary key(&quot;RESOURCE_ID&quot;, &quot;NAME&quot;, &quot;VIEWER_UID&quot;)
+);
+
+create table ADDRESSBOOK_HOME (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_PROPERTY_STORE_ID&quot; integer not null,
+    &quot;OWNER_UID&quot; nvarchar2(255) unique,
+    &quot;DATAVERSION&quot; integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+    &quot;RESOURCE_ID&quot; integer primary key references ADDRESSBOOK_HOME on delete cascade,
+    &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table SHARED_ADDRESSBOOK_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;ADDRESSBOOK_RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;OWNER_HOME_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;ADDRESSBOOK_RESOURCE_NAME&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT (
+    &quot;RESOURCE_ID&quot; integer primary key,
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;VCARD_TEXT&quot; nclob,
+    &quot;VCARD_UID&quot; nvarchar2(255),
+    &quot;KIND&quot; integer not null,
+    &quot;MD5&quot; nchar(32),
+    &quot;CREATED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;MODIFIED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;VCARD_UID&quot;)
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+    &quot;ID&quot; integer primary key,
+    &quot;DESCRIPTION&quot; nvarchar2(16) unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('person', 0);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('group', 1);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
+insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
+create table ABO_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ID&quot; integer not null references ADDRESSBOOK_OBJECT, 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ID&quot;)
+);
+
+create table ABO_FOREIGN_MEMBERS (
+    &quot;GROUP_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;ADDRESSBOOK_ID&quot; integer not null references ADDRESSBOOK_HOME on delete cascade,
+    &quot;MEMBER_ADDRESS&quot; nvarchar2(255), 
+    primary key(&quot;GROUP_ID&quot;, &quot;MEMBER_ADDRESS&quot;)
+);
+
+create table SHARED_GROUP_BIND (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;GROUP_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    &quot;GROUP_ADDRESSBOOK_NAME&quot; nvarchar2(255),
+    &quot;BIND_MODE&quot; integer not null,
+    &quot;BIND_STATUS&quot; integer not null,
+    &quot;BIND_REVISION&quot; integer default 0 not null,
+    &quot;MESSAGE&quot; nclob, 
+    primary key(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_RESOURCE_ID&quot;), 
+    unique(&quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot;, &quot;GROUP_ADDRESSBOOK_NAME&quot;)
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+    &quot;CALENDAR_HOME_RESOURCE_ID&quot; integer not null references CALENDAR_HOME,
+    &quot;CALENDAR_RESOURCE_ID&quot; integer references CALENDAR,
+    &quot;CALENDAR_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+    &quot;ADDRESSBOOK_HOME_RESOURCE_ID&quot; integer not null references ADDRESSBOOK_HOME,
+    &quot;OWNER_HOME_RESOURCE_ID&quot; integer references ADDRESSBOOK_HOME,
+    &quot;ADDRESSBOOK_NAME&quot; nvarchar2(255) default null,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+    &quot;NOTIFICATION_HOME_RESOURCE_ID&quot; integer not null references NOTIFICATION_HOME on delete cascade,
+    &quot;RESOURCE_NAME&quot; nvarchar2(255),
+    &quot;REVISION&quot; integer not null,
+    &quot;DELETED&quot; integer not null, 
+    unique(&quot;NOTIFICATION_HOME_RESOURCE_ID&quot;, &quot;RESOURCE_NAME&quot;)
+);
+
+create table APN_SUBSCRIPTIONS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;RESOURCE_KEY&quot; nvarchar2(255),
+    &quot;MODIFIED&quot; integer not null,
+    &quot;SUBSCRIBER_GUID&quot; nvarchar2(255),
+    &quot;USER_AGENT&quot; nvarchar2(255) default null,
+    &quot;IP_ADDR&quot; nvarchar2(255) default null, 
+    primary key(&quot;TOKEN&quot;, &quot;RESOURCE_KEY&quot;)
+);
+
+create table IMIP_TOKENS (
+    &quot;TOKEN&quot; nvarchar2(255),
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALUID&quot; nvarchar2(255),
+    &quot;ACCESSED&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    primary key(&quot;ORGANIZER&quot;, &quot;ATTENDEE&quot;, &quot;ICALUID&quot;)
+);
+
+create table IMIP_INVITATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;FROM_ADDR&quot; nvarchar2(255),
+    &quot;TO_ADDR&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table IMIP_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;ORGANIZER&quot; nvarchar2(255),
+    &quot;ATTENDEE&quot; nvarchar2(255),
+    &quot;ICALENDAR_TEXT&quot; nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;PUSH_ID&quot; nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+    &quot;WORK_ID&quot; integer primary key not null,
+    &quot;NOT_BEFORE&quot; timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    &quot;RESOURCE_ID&quot; integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+    &quot;NAME&quot; nvarchar2(255) primary key,
+    &quot;VALUE&quot; nvarchar2(255)
+);
+
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '26');
+insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
+create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
+    DEFAULT_EVENTS
+);
+
+create index CALENDAR_HOME_METADAT_d55e5548 on CALENDAR_HOME_METADATA (
+    DEFAULT_TASKS
+);
+
+create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
+    NOTIFICATION_HOME_RESOURCE_ID
+);
+
+create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    RECURRANCE_MAX
+);
+
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
+    DROPBOX_ID
+);
+
+create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
+    CALENDAR_RESOURCE_ID
+);
+
+create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
+    TIME_RANGE_INSTANCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
+    CALENDAR_HOME_RESOURCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index SHARED_ADDRESSBOOK_BI_e9a2e6d4 on SHARED_ADDRESSBOOK_BIND (
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ABO_MEMBERS_ADDRESSBO_4effa879 on ABO_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index ABO_MEMBERS_MEMBER_ID_8d66adcf on ABO_MEMBERS (
+    MEMBER_ID
+);
+
+create index ABO_FOREIGN_MEMBERS_A_1fd2c5e9 on ABO_FOREIGN_MEMBERS (
+    ADDRESSBOOK_ID
+);
+
+create index SHARED_GROUP_BIND_RES_cf52f95d on SHARED_GROUP_BIND (
+    GROUP_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_HOME_RESOURCE_ID,
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_6d9d929c on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    RESOURCE_NAME,
+    DELETED,
+    REVISION
+);
+
+create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_2bfcf757 on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_HOME_RESOURCE_ID,
+    OWNER_HOME_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_OBJECT_RE_00fe8288 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    RESOURCE_NAME,
+    DELETED,
+    REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_45004780 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
+    NOTIFICATION_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
+    RESOURCE_KEY
+);
+
+create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
+    TOKEN
+);
+
+create index CALENDAR_OBJECT_SPLIT_af71dcda on CALENDAR_OBJECT_SPLITTER_WORK (
+    RESOURCE_ID
+);
+
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv24sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,700 +0,0 @@
</span><del>--- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
-
-----
--- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
-
------------------
--- Resource ID --
------------------
-
-create sequence RESOURCE_ID_SEQ;
-
-
--------------------------
--- Cluster Bookkeeping --
--------------------------
-
--- Information about a process connected to this database.
-
--- 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),
-
-  primary key (HOSTNAME, PORT)
-);
-
--- Unique named locks.  This table should always be empty, but rows are
--- temporarily created in order to prevent undesirable concurrency.
-create table NAMED_LOCK (
-    LOCK_NAME varchar(255) primary key
-);
-
-
--------------------
--- Calendar Home --
--------------------
-
-create table CALENDAR_HOME (
-  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
-  DATAVERSION      integer      default 0 not null
-);
-
---------------
--- Calendar --
---------------
-
-create table CALENDAR (
-  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
-);
-
-----------------------------
--- Calendar Home Metadata --
-----------------------------
-
-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,
-  ALARM_VEVENT_TIMED       text        default null,
-  ALARM_VEVENT_ALLDAY      text        default null,
-  ALARM_VTODO_TIMED        text        default null,
-  ALARM_VTODO_ALLDAY       text        default null,
-  AVAILABILITY             text        default null,
-  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
-        CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
-create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
-        CALENDAR_HOME_METADATA(DEFAULT_TASKS);
-
------------------------
--- Calendar Metadata --
------------------------
-
-create table CALENDAR_METADATA (
-  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)
-);
-
-
----------------------------
--- Sharing Notifications --
----------------------------
-
-create table NOTIFICATION_HOME (
-  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID   varchar(255) not null unique                                 -- implicit index
-);
-
-create table NOTIFICATION (
-  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
-  NOTIFICATION_UID              varchar(255) not null,
-  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),
-
-  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
-);
-
-create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
-        NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
-
-
--------------------
--- Calendar Bind --
--------------------
-
--- Joins CALENDAR_HOME and CALENDAR
-
-create table CALENDAR_BIND (
-  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
-  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
-  CALENDAR_RESOURCE_NAME    varchar(255) not null,
-  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
-  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                integer      default 0 not null,
-  MESSAGE                   text,
-  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,
-  TIMEZONE                  text         default null,
-
-  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
-  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
-);
-
-create index CALENDAR_BIND_RESOURCE_ID on
-        CALENDAR_BIND(CALENDAR_RESOURCE_ID);
-
--- Enumeration of calendar bind modes
-
-create table CALENDAR_BIND_MODE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_BIND_MODE values (0, 'own'  );
-insert into CALENDAR_BIND_MODE values (1, 'read' );
-insert into CALENDAR_BIND_MODE values (2, 'write');
-insert into CALENDAR_BIND_MODE values (3, 'direct');
-
--- Enumeration of statuses
-
-create table CALENDAR_BIND_STATUS (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_BIND_STATUS values (0, 'invited' );
-insert into CALENDAR_BIND_STATUS values (1, 'accepted');
-insert into CALENDAR_BIND_STATUS values (2, 'declined');
-insert into CALENDAR_BIND_STATUS values (3, 'invalid');
-
-
--- Enumeration of transparency
-
-create table CALENDAR_TRANSP (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_TRANSP values (0, 'opaque' );
-insert into CALENDAR_TRANSP values (1, 'transparent');
-
-
----------------------
--- Calendar Object --
----------------------
-
-create table CALENDAR_OBJECT (
-  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
-  RESOURCE_NAME        varchar(255) not null,
-  ICALENDAR_TEXT       text         not null,
-  ICALENDAR_UID        varchar(255) not null,
-  ICALENDAR_TYPE       varchar(255) not null,
-  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
-  DROPBOX_ID           varchar(255),
-  ORGANIZER            varchar(255),
-  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
-  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
-  ACCESS               integer      default 0 not null,
-  SCHEDULE_OBJECT      boolean      default false,
-  SCHEDULE_TAG         varchar(36)  default null,
-  SCHEDULE_ETAGS       text         default null,
-  PRIVATE_COMMENTS     boolean      default false not null,
-  MD5                  char(32)     not null,
-  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-
-  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
-
-  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
-  -- calendar objects, this constraint has to be selectively enforced by the
-  -- application layer.
-
-  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
-);
-
-create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
-  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
-
-create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
-  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
-
-create index CALENDAR_OBJECT_ICALENDAR_UID on
-  CALENDAR_OBJECT(ICALENDAR_UID);
-
-create index CALENDAR_OBJECT_DROPBOX_ID on
-  CALENDAR_OBJECT(DROPBOX_ID);
-
--- Enumeration of attachment modes
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
-
-
--- Enumeration of calendar access types
-
-create table CALENDAR_ACCESS_TYPE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(32) not null unique
-);
-
-insert into CALENDAR_ACCESS_TYPE values (0, ''             );
-insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
-insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
-insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
-insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
-
-
------------------
--- Instance ID --
------------------
-
-create sequence INSTANCE_ID_SEQ;
-
-
-----------------
--- Time Range --
-----------------
-
-create table TIME_RANGE (
-  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
-  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
-  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
-  FLOATING                    boolean        not null,
-  START_DATE                  timestamp      not null,
-  END_DATE                    timestamp      not null,
-  FBTYPE                      integer        not null,
-  TRANSPARENT                 boolean        not null
-);
-
-create index TIME_RANGE_CALENDAR_RESOURCE_ID on
-  TIME_RANGE(CALENDAR_RESOURCE_ID);
-create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
-  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
-
-
--- Enumeration of free/busy types
-
-create table FREE_BUSY_TYPE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into FREE_BUSY_TYPE values (0, 'unknown'         );
-insert into FREE_BUSY_TYPE values (1, 'free'            );
-insert into FREE_BUSY_TYPE values (2, 'busy'            );
-insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
-insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
-
-
-------------------
--- Transparency --
-------------------
-
-create table TRANSPARENCY (
-  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
-  USER_ID                     varchar(255) not null,
-  TRANSPARENT                 boolean      not null
-);
-
-create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
-  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
-
-
-----------------
--- Attachment --
-----------------
-
-create sequence ATTACHMENT_ID_SEQ;
-
-create table ATTACHMENT (
-  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
-  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
-  DROPBOX_ID                  varchar(255),
-  CONTENT_TYPE                varchar(255)      not null,
-  SIZE                        integer           not null,
-  MD5                         char(32)          not null,
-  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  PATH                        varchar(1024)     not null
-);
-
-create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
-  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
-
--- Many-to-many relationship between attachments and calendar objects
-create table ATTACHMENT_CALENDAR_OBJECT (
-  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
-  MANAGED_ID                     varchar(255) not null,
-  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
-
-  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
-  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
-);
-
-create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
-        ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
-
------------------------
--- Resource Property --
------------------------
-
-create table RESOURCE_PROPERTY (
-  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
-  NAME        varchar(255) not null,
-  VALUE       text         not null, -- FIXME: xml?
-  VIEWER_UID  varchar(255),
-
-  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
-);
-
-
-----------------------
--- AddressBook Home --
-----------------------
-
-create table ADDRESSBOOK_HOME (
-  RESOURCE_ID                                      integer                        primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  ADDRESSBOOK_PROPERTY_STORE_ID        integer              default nextval('RESOURCE_ID_SEQ') not null,         -- implicit index
-  OWNER_UID                                        varchar(255)         not null unique,                                -- implicit index
-  DATAVERSION                                      integer              default 0 not null
-);
-
-
--------------------------------
--- AddressBook Home Metadata --
--------------------------------
-
-create table ADDRESSBOOK_HOME_METADATA (
-  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
-  QUOTA_USED_BYTES integer      default 0 not null,
-  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
------------------------------
--- Shared AddressBook Bind --
------------------------------
-
--- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
-
-create table SHARED_ADDRESSBOOK_BIND (
-  ADDRESSBOOK_HOME_RESOURCE_ID                        integer                        not null references ADDRESSBOOK_HOME,
-  OWNER_ADDRESSBOOK_HOME_RESOURCE_ID    integer              not null references ADDRESSBOOK_HOME on delete cascade,
-  ADDRESSBOOK_RESOURCE_NAME                            varchar(255)         not null,
-  BIND_MODE                                            integer              not null,        -- enum CALENDAR_BIND_MODE
-  BIND_STATUS                                          integer              not null,        -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                                           integer              default 0 not null,
-  MESSAGE                                              text,                                  -- FIXME: xml?
-
-  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_ADDRESSBOOK_HOME_RESOURCE_ID), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
-);
-
-create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
-  SHARED_ADDRESSBOOK_BIND(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID);
-
-
-------------------------
--- AddressBook Object --
-------------------------
-
-create table ADDRESSBOOK_OBJECT (
-  RESOURCE_ID                             integer                   primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
-  ADDRESSBOOK_HOME_RESOURCE_ID         integer              not null references ADDRESSBOOK_HOME on delete cascade,
-  RESOURCE_NAME                           varchar(255)         not null,
-  VCARD_TEXT                              text                 not null,
-  VCARD_UID                               varchar(255)         not null,
-  KIND                                                             integer              not null,  -- enum ADDRESSBOOK_OBJECT_KIND
-  MD5                                     char(32)             not null,
-  CREATED                                 timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                                timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
-
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID)      -- implicit index
-);
-
-
------------------------------
--- AddressBook Object kind --
------------------------------
-
-create table ADDRESSBOOK_OBJECT_KIND (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
-insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
-insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
-insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
-
-
----------------------------------
--- Address Book Object Members --
----------------------------------
-
-create table ABO_MEMBERS (
-    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
-         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
-    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,                                                -- member AddressBook Object's RESOURCE_ID
-
-    primary key (GROUP_ID, MEMBER_ID) -- implicit index
-);
-
-create index ABO_MEMBERS_ADDRESSBOOK_ID on
-        ABO_MEMBERS(ADDRESSBOOK_ID);
-create index ABO_MEMBERS_MEMBER_ID on
-        ABO_MEMBERS(MEMBER_ID);
-
-------------------------------------------
--- Address Book Object Foreign Members  --
-------------------------------------------
-
-create table ABO_FOREIGN_MEMBERS (
-    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
-         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
-    MEMBER_ADDRESS            varchar(255) not null,                                                                                                         -- member AddressBook Object's 'calendar' address
-
-    primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
-);
-
-create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
-        ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
-
------------------------
--- Shared Group Bind --
------------------------
-
--- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
-
-create table SHARED_GROUP_BIND (        
-  ADDRESSBOOK_HOME_RESOURCE_ID                 integer      not null references ADDRESSBOOK_HOME,
-  GROUP_RESOURCE_ID                              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
-  GROUP_ADDRESSBOOK_RESOURCE_NAME        varchar(255) not null,
-  BIND_MODE                                    integer      not null, -- enum CALENDAR_BIND_MODE
-  BIND_STATUS                                  integer      not null, -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                                   integer      default 0 not null,
-  MESSAGE                                      text,                  -- FIXME: xml?
-
-  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
-);
-
-create index SHARED_GROUP_BIND_RESOURCE_ID on
-  SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
-
-
----------------
--- Revisions --
----------------
-
-create sequence REVISION_SEQ;
-
-
--------------------------------
--- Calendar Object Revisions --
--------------------------------
-
-create table CALENDAR_OBJECT_REVISIONS (
-  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
-  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
-  CALENDAR_NAME             varchar(255) default null,
-  RESOURCE_NAME             varchar(255),
-  REVISION                  integer      default nextval('REVISION_SEQ') not null,
-  DELETED                   boolean      not null
-);
-
-create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
-
-create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME);
-
-create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
-
-
-----------------------------------
--- AddressBook Object Revisions --
-----------------------------------
-
-create table ADDRESSBOOK_OBJECT_REVISIONS (
-  ADDRESSBOOK_HOME_RESOURCE_ID                         integer                        not null references ADDRESSBOOK_HOME,
-  OWNER_ADDRESSBOOK_HOME_RESOURCE_ID    integer             references ADDRESSBOOK_HOME,
-  ADDRESSBOOK_NAME                                     varchar(255)         default null,
-  RESOURCE_NAME                                        varchar(255),
-  REVISION                                             integer             default nextval('REVISION_SEQ') not null,
-  DELETED                                              boolean              not null
-);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_ADDRESSBOOK_HOME_RESOURCE_ID
-  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_ADDRESSBOOK_HOME_RESOURCE_ID);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME
-  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
-  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID, REVISION);
-
-
------------------------------------
--- Notification Object Revisions --
------------------------------------
-
-create table NOTIFICATION_OBJECT_REVISIONS (
-  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
-  RESOURCE_NAME                 varchar(255),
-  REVISION                      integer      default nextval('REVISION_SEQ') not null,
-  DELETED                       boolean      not null,
-
-  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
-);
-
-create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
-  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
-
-
--------------------------------------------
--- Apple Push Notification Subscriptions --
--------------------------------------------
-
-create table APN_SUBSCRIPTIONS (
-  TOKEN                         varchar(255) not null,
-  RESOURCE_KEY                  varchar(255) not null,
-  MODIFIED                      integer      not null,
-  SUBSCRIBER_GUID               varchar(255) not null,
-  USER_AGENT                    varchar(255) default null,
-  IP_ADDR                       varchar(255) default null,
-
-  primary key (TOKEN, RESOURCE_KEY) -- implicit index
-);
-
-create index APN_SUBSCRIPTIONS_RESOURCE_KEY
-   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
-
-   
------------------
--- IMIP Tokens --
------------------
-
-create table IMIP_TOKENS (
-  TOKEN                         varchar(255) not null,
-  ORGANIZER                     varchar(255) not null,
-  ATTENDEE                      varchar(255) not null,
-  ICALUID                       varchar(255) not null,
-  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-
-  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
-);
-
-create index IMIP_TOKENS_TOKEN
-   on IMIP_TOKENS(TOKEN);
-
-   
-----------------
--- Work Items --
-----------------
-
-create sequence WORKITEM_SEQ;
-
-
----------------------------
--- IMIP Inivitation Work --
----------------------------
-
-create table IMIP_INVITATION_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  FROM_ADDR                     varchar(255) not null,
-  TO_ADDR                       varchar(255) not null,
-  ICALENDAR_TEXT                text         not null
-);
-
-
------------------------
--- IMIP Polling Work --
------------------------
-
-create table IMIP_POLLING_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
----------------------
--- IMIP Reply Work --
----------------------
-
-create table IMIP_REPLY_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  ORGANIZER                     varchar(255) not null,
-  ATTENDEE                      varchar(255) not null,
-  ICALENDAR_TEXT                text         not null
-);
-
-
-------------------------
--- Push Notifications --
-------------------------
-
-create table PUSH_NOTIFICATION_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  PUSH_ID                       varchar(255) not null
-);
-
------------------
--- GroupCacher --
------------------
-
-create table GROUP_CACHER_POLLING_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
---------------------------
--- Object Splitter Work --
---------------------------
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  RESOURCE_ID                   integer      not null references CALENDAR_OBJECT on delete cascade
-);
-
-create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
-        CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
-
---------------------
--- Schema Version --
---------------------
-
-create table CALENDARSERVER (
-  NAME                          varchar(255) primary key, -- implicit index
-  VALUE                         varchar(255)
-);
-
-insert into CALENDARSERVER values ('VERSION', '24');
-insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
-insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv24sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldpostgresdialectv24sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,700 @@
</span><ins>+-- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
+
+----
+-- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+
+-----------------
+-- Resource ID --
+-----------------
+
+create sequence RESOURCE_ID_SEQ;
+
+
+-------------------------
+-- Cluster Bookkeeping --
+-------------------------
+
+-- Information about a process connected to this database.
+
+-- 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),
+
+  primary key (HOSTNAME, PORT)
+);
+
+-- Unique named locks.  This table should always be empty, but rows are
+-- temporarily created in order to prevent undesirable concurrency.
+create table NAMED_LOCK (
+    LOCK_NAME varchar(255) primary key
+);
+
+
+-------------------
+-- Calendar Home --
+-------------------
+
+create table CALENDAR_HOME (
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  DATAVERSION      integer      default 0 not null
+);
+
+--------------
+-- Calendar --
+--------------
+
+create table CALENDAR (
+  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+----------------------------
+-- Calendar Home Metadata --
+----------------------------
+
+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,
+  ALARM_VEVENT_TIMED       text        default null,
+  ALARM_VEVENT_ALLDAY      text        default null,
+  ALARM_VTODO_TIMED        text        default null,
+  ALARM_VTODO_ALLDAY       text        default null,
+  AVAILABILITY             text        default null,
+  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
+        CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
+create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
+        CALENDAR_HOME_METADATA(DEFAULT_TASKS);
+
+-----------------------
+-- Calendar Metadata --
+-----------------------
+
+create table CALENDAR_METADATA (
+  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)
+);
+
+
+---------------------------
+-- Sharing Notifications --
+---------------------------
+
+create table NOTIFICATION_HOME (
+  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID   varchar(255) not null unique                                 -- implicit index
+);
+
+create table NOTIFICATION (
+  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
+  NOTIFICATION_UID              varchar(255) not null,
+  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),
+
+  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
+);
+
+create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
+        NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
+
+
+-------------------
+-- Calendar Bind --
+-------------------
+
+-- Joins CALENDAR_HOME and CALENDAR
+
+create table CALENDAR_BIND (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  CALENDAR_RESOURCE_NAME    varchar(255) not null,
+  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                integer      default 0 not null,
+  MESSAGE                   text,
+  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,
+  TIMEZONE                  text         default null,
+
+  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
+  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
+);
+
+create index CALENDAR_BIND_RESOURCE_ID on
+        CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+
+-- Enumeration of calendar bind modes
+
+create table CALENDAR_BIND_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_MODE values (0, 'own'  );
+insert into CALENDAR_BIND_MODE values (1, 'read' );
+insert into CALENDAR_BIND_MODE values (2, 'write');
+insert into CALENDAR_BIND_MODE values (3, 'direct');
+
+-- Enumeration of statuses
+
+create table CALENDAR_BIND_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_STATUS values (0, 'invited' );
+insert into CALENDAR_BIND_STATUS values (1, 'accepted');
+insert into CALENDAR_BIND_STATUS values (2, 'declined');
+insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+
+
+-- Enumeration of transparency
+
+create table CALENDAR_TRANSP (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
+
+---------------------
+-- Calendar Object --
+---------------------
+
+create table CALENDAR_OBJECT (
+  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
+  RESOURCE_NAME        varchar(255) not null,
+  ICALENDAR_TEXT       text         not null,
+  ICALENDAR_UID        varchar(255) not null,
+  ICALENDAR_TYPE       varchar(255) not null,
+  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  DROPBOX_ID           varchar(255),
+  ORGANIZER            varchar(255),
+  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
+  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
+  ACCESS               integer      default 0 not null,
+  SCHEDULE_OBJECT      boolean      default false,
+  SCHEDULE_TAG         varchar(36)  default null,
+  SCHEDULE_ETAGS       text         default null,
+  PRIVATE_COMMENTS     boolean      default false not null,
+  MD5                  char(32)     not null,
+  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+
+  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+  -- calendar objects, this constraint has to be selectively enforced by the
+  -- application layer.
+
+  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
+
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+  CALENDAR_OBJECT(ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_DROPBOX_ID on
+  CALENDAR_OBJECT(DROPBOX_ID);
+
+-- Enumeration of attachment modes
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
+
+
+-- Enumeration of calendar access types
+
+create table CALENDAR_ACCESS_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(32) not null unique
+);
+
+insert into CALENDAR_ACCESS_TYPE values (0, ''             );
+insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
+insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
+insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
+insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
+
+
+-----------------
+-- Instance ID --
+-----------------
+
+create sequence INSTANCE_ID_SEQ;
+
+
+----------------
+-- Time Range --
+----------------
+
+create table TIME_RANGE (
+  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
+  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
+  FLOATING                    boolean        not null,
+  START_DATE                  timestamp      not null,
+  END_DATE                    timestamp      not null,
+  FBTYPE                      integer        not null,
+  TRANSPARENT                 boolean        not null
+);
+
+create index TIME_RANGE_CALENDAR_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_RESOURCE_ID);
+create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
+
+
+-- Enumeration of free/busy types
+
+create table FREE_BUSY_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into FREE_BUSY_TYPE values (0, 'unknown'         );
+insert into FREE_BUSY_TYPE values (1, 'free'            );
+insert into FREE_BUSY_TYPE values (2, 'busy'            );
+insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
+insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
+
+
+------------------
+-- Transparency --
+------------------
+
+create table TRANSPARENCY (
+  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
+  USER_ID                     varchar(255) not null,
+  TRANSPARENT                 boolean      not null
+);
+
+create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
+  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
+
+
+----------------
+-- Attachment --
+----------------
+
+create sequence ATTACHMENT_ID_SEQ;
+
+create table ATTACHMENT (
+  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
+  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
+  DROPBOX_ID                  varchar(255),
+  CONTENT_TYPE                varchar(255)      not null,
+  SIZE                        integer           not null,
+  MD5                         char(32)          not null,
+  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  PATH                        varchar(1024)     not null
+);
+
+create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
+  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
+
+-- Many-to-many relationship between attachments and calendar objects
+create table ATTACHMENT_CALENDAR_OBJECT (
+  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
+  MANAGED_ID                     varchar(255) not null,
+  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
+
+  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
+  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
+);
+
+create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
+        ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
+
+-----------------------
+-- Resource Property --
+-----------------------
+
+create table RESOURCE_PROPERTY (
+  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
+  NAME        varchar(255) not null,
+  VALUE       text         not null, -- FIXME: xml?
+  VIEWER_UID  varchar(255),
+
+  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
+);
+
+
+----------------------
+-- AddressBook Home --
+----------------------
+
+create table ADDRESSBOOK_HOME (
+  RESOURCE_ID                                      integer                        primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  ADDRESSBOOK_PROPERTY_STORE_ID        integer              default nextval('RESOURCE_ID_SEQ') not null,         -- implicit index
+  OWNER_UID                                        varchar(255)         not null unique,                                -- implicit index
+  DATAVERSION                                      integer              default 0 not null
+);
+
+
+-------------------------------
+-- AddressBook Home Metadata --
+-------------------------------
+
+create table ADDRESSBOOK_HOME_METADATA (
+  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES integer      default 0 not null,
+  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+-----------------------------
+-- Shared AddressBook Bind --
+-----------------------------
+
+-- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
+
+create table SHARED_ADDRESSBOOK_BIND (
+  ADDRESSBOOK_HOME_RESOURCE_ID                        integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_ADDRESSBOOK_HOME_RESOURCE_ID    integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  ADDRESSBOOK_RESOURCE_NAME                            varchar(255)         not null,
+  BIND_MODE                                            integer              not null,        -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                          integer              not null,        -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                           integer              default 0 not null,
+  MESSAGE                                              text,                                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_ADDRESSBOOK_HOME_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
+);
+
+create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
+  SHARED_ADDRESSBOOK_BIND(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID);
+
+
+------------------------
+-- AddressBook Object --
+------------------------
+
+create table ADDRESSBOOK_OBJECT (
+  RESOURCE_ID                             integer                   primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
+  ADDRESSBOOK_HOME_RESOURCE_ID         integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  RESOURCE_NAME                           varchar(255)         not null,
+  VCARD_TEXT                              text                 not null,
+  VCARD_UID                               varchar(255)         not null,
+  KIND                                                             integer              not null,  -- enum ADDRESSBOOK_OBJECT_KIND
+  MD5                                     char(32)             not null,
+  CREATED                                 timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                                timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID)      -- implicit index
+);
+
+
+-----------------------------
+-- AddressBook Object kind --
+-----------------------------
+
+create table ADDRESSBOOK_OBJECT_KIND (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
+
+
+---------------------------------
+-- Address Book Object Members --
+---------------------------------
+
+create table ABO_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,                                                -- member AddressBook Object's RESOURCE_ID
+
+    primary key (GROUP_ID, MEMBER_ID) -- implicit index
+);
+
+create index ABO_MEMBERS_ADDRESSBOOK_ID on
+        ABO_MEMBERS(ADDRESSBOOK_ID);
+create index ABO_MEMBERS_MEMBER_ID on
+        ABO_MEMBERS(MEMBER_ID);
+
+------------------------------------------
+-- Address Book Object Foreign Members  --
+------------------------------------------
+
+create table ABO_FOREIGN_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ADDRESS            varchar(255) not null,                                                                                                         -- member AddressBook Object's 'calendar' address
+
+    primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
+);
+
+create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
+        ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
+
+-----------------------
+-- Shared Group Bind --
+-----------------------
+
+-- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
+
+create table SHARED_GROUP_BIND (        
+  ADDRESSBOOK_HOME_RESOURCE_ID                 integer      not null references ADDRESSBOOK_HOME,
+  GROUP_RESOURCE_ID                              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
+  GROUP_ADDRESSBOOK_RESOURCE_NAME        varchar(255) not null,
+  BIND_MODE                                    integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                  integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                   integer      default 0 not null,
+  MESSAGE                                      text,                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
+);
+
+create index SHARED_GROUP_BIND_RESOURCE_ID on
+  SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
+
+
+---------------
+-- Revisions --
+---------------
+
+create sequence REVISION_SEQ;
+
+
+-------------------------------
+-- Calendar Object Revisions --
+-------------------------------
+
+create table CALENDAR_OBJECT_REVISIONS (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
+  CALENDAR_NAME             varchar(255) default null,
+  RESOURCE_NAME             varchar(255),
+  REVISION                  integer      default nextval('REVISION_SEQ') not null,
+  DELETED                   boolean      not null
+);
+
+create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
+
+
+----------------------------------
+-- AddressBook Object Revisions --
+----------------------------------
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+  ADDRESSBOOK_HOME_RESOURCE_ID                         integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_ADDRESSBOOK_HOME_RESOURCE_ID    integer             references ADDRESSBOOK_HOME,
+  ADDRESSBOOK_NAME                                     varchar(255)         default null,
+  RESOURCE_NAME                                        varchar(255),
+  REVISION                                             integer             default nextval('REVISION_SEQ') not null,
+  DELETED                                              boolean              not null
+);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_ADDRESSBOOK_HOME_RESOURCE_ID
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_ADDRESSBOOK_HOME_RESOURCE_ID);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_ADDRESSBOOK_HOME_RESOURCE_ID, REVISION);
+
+
+-----------------------------------
+-- Notification Object Revisions --
+-----------------------------------
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
+  RESOURCE_NAME                 varchar(255),
+  REVISION                      integer      default nextval('REVISION_SEQ') not null,
+  DELETED                       boolean      not null,
+
+  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+);
+
+create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
+
+
+-------------------------------------------
+-- Apple Push Notification Subscriptions --
+-------------------------------------------
+
+create table APN_SUBSCRIPTIONS (
+  TOKEN                         varchar(255) not null,
+  RESOURCE_KEY                  varchar(255) not null,
+  MODIFIED                      integer      not null,
+  SUBSCRIBER_GUID               varchar(255) not null,
+  USER_AGENT                    varchar(255) default null,
+  IP_ADDR                       varchar(255) default null,
+
+  primary key (TOKEN, RESOURCE_KEY) -- implicit index
+);
+
+create index APN_SUBSCRIPTIONS_RESOURCE_KEY
+   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
+
+   
+-----------------
+-- IMIP Tokens --
+-----------------
+
+create table IMIP_TOKENS (
+  TOKEN                         varchar(255) not null,
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALUID                       varchar(255) not null,
+  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
+);
+
+create index IMIP_TOKENS_TOKEN
+   on IMIP_TOKENS(TOKEN);
+
+   
+----------------
+-- Work Items --
+----------------
+
+create sequence WORKITEM_SEQ;
+
+
+---------------------------
+-- IMIP Inivitation Work --
+---------------------------
+
+create table IMIP_INVITATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  FROM_ADDR                     varchar(255) not null,
+  TO_ADDR                       varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+-----------------------
+-- IMIP Polling Work --
+-----------------------
+
+create table IMIP_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------
+-- IMIP Reply Work --
+---------------------
+
+create table IMIP_REPLY_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+------------------------
+-- Push Notifications --
+------------------------
+
+create table PUSH_NOTIFICATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  PUSH_ID                       varchar(255) not null
+);
+
+-----------------
+-- GroupCacher --
+-----------------
+
+create table GROUP_CACHER_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+--------------------------
+-- Object Splitter Work --
+--------------------------
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  RESOURCE_ID                   integer      not null references CALENDAR_OBJECT on delete cascade
+);
+
+create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
+        CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
+
+--------------------
+-- Schema Version --
+--------------------
+
+create table CALENDARSERVER (
+  NAME                          varchar(255) primary key, -- implicit index
+  VALUE                         varchar(255)
+);
+
+insert into CALENDARSERVER values ('VERSION', '24');
+insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv25sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,700 +0,0 @@
</span><del>--- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
-
-----
--- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
-
------------------
--- Resource ID --
------------------
-
-create sequence RESOURCE_ID_SEQ;
-
-
--------------------------
--- Cluster Bookkeeping --
--------------------------
-
--- Information about a process connected to this database.
-
--- 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),
-
-  primary key (HOSTNAME, PORT)
-);
-
--- Unique named locks.  This table should always be empty, but rows are
--- temporarily created in order to prevent undesirable concurrency.
-create table NAMED_LOCK (
-    LOCK_NAME varchar(255) primary key
-);
-
-
--------------------
--- Calendar Home --
--------------------
-
-create table CALENDAR_HOME (
-  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
-  DATAVERSION      integer      default 0 not null
-);
-
---------------
--- Calendar --
---------------
-
-create table CALENDAR (
-  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
-);
-
-----------------------------
--- Calendar Home Metadata --
-----------------------------
-
-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,
-  ALARM_VEVENT_TIMED       text        default null,
-  ALARM_VEVENT_ALLDAY      text        default null,
-  ALARM_VTODO_TIMED        text        default null,
-  ALARM_VTODO_ALLDAY       text        default null,
-  AVAILABILITY             text        default null,
-  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
-        CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
-create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
-        CALENDAR_HOME_METADATA(DEFAULT_TASKS);
-
------------------------
--- Calendar Metadata --
------------------------
-
-create table CALENDAR_METADATA (
-  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)
-);
-
-
----------------------------
--- Sharing Notifications --
----------------------------
-
-create table NOTIFICATION_HOME (
-  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID   varchar(255) not null unique                                 -- implicit index
-);
-
-create table NOTIFICATION (
-  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
-  NOTIFICATION_UID              varchar(255) not null,
-  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),
-
-  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
-);
-
-create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
-        NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
-
-
--------------------
--- Calendar Bind --
--------------------
-
--- Joins CALENDAR_HOME and CALENDAR
-
-create table CALENDAR_BIND (
-  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
-  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
-  CALENDAR_RESOURCE_NAME    varchar(255) not null,
-  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
-  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                integer      default 0 not null,
-  MESSAGE                   text,
-  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,
-  TIMEZONE                  text         default null,
-
-  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
-  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
-);
-
-create index CALENDAR_BIND_RESOURCE_ID on
-        CALENDAR_BIND(CALENDAR_RESOURCE_ID);
-
--- Enumeration of calendar bind modes
-
-create table CALENDAR_BIND_MODE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_BIND_MODE values (0, 'own'  );
-insert into CALENDAR_BIND_MODE values (1, 'read' );
-insert into CALENDAR_BIND_MODE values (2, 'write');
-insert into CALENDAR_BIND_MODE values (3, 'direct');
-
--- Enumeration of statuses
-
-create table CALENDAR_BIND_STATUS (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_BIND_STATUS values (0, 'invited' );
-insert into CALENDAR_BIND_STATUS values (1, 'accepted');
-insert into CALENDAR_BIND_STATUS values (2, 'declined');
-insert into CALENDAR_BIND_STATUS values (3, 'invalid');
-
-
--- Enumeration of transparency
-
-create table CALENDAR_TRANSP (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_TRANSP values (0, 'opaque' );
-insert into CALENDAR_TRANSP values (1, 'transparent');
-
-
----------------------
--- Calendar Object --
----------------------
-
-create table CALENDAR_OBJECT (
-  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
-  RESOURCE_NAME        varchar(255) not null,
-  ICALENDAR_TEXT       text         not null,
-  ICALENDAR_UID        varchar(255) not null,
-  ICALENDAR_TYPE       varchar(255) not null,
-  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
-  DROPBOX_ID           varchar(255),
-  ORGANIZER            varchar(255),
-  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
-  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
-  ACCESS               integer      default 0 not null,
-  SCHEDULE_OBJECT      boolean      default false,
-  SCHEDULE_TAG         varchar(36)  default null,
-  SCHEDULE_ETAGS       text         default null,
-  PRIVATE_COMMENTS     boolean      default false not null,
-  MD5                  char(32)     not null,
-  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-
-  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
-
-  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
-  -- calendar objects, this constraint has to be selectively enforced by the
-  -- application layer.
-
-  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
-);
-
-create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
-  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
-
-create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
-  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
-
-create index CALENDAR_OBJECT_ICALENDAR_UID on
-  CALENDAR_OBJECT(ICALENDAR_UID);
-
-create index CALENDAR_OBJECT_DROPBOX_ID on
-  CALENDAR_OBJECT(DROPBOX_ID);
-
--- Enumeration of attachment modes
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
-
-
--- Enumeration of calendar access types
-
-create table CALENDAR_ACCESS_TYPE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(32) not null unique
-);
-
-insert into CALENDAR_ACCESS_TYPE values (0, ''             );
-insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
-insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
-insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
-insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
-
-
------------------
--- Instance ID --
------------------
-
-create sequence INSTANCE_ID_SEQ;
-
-
-----------------
--- Time Range --
-----------------
-
-create table TIME_RANGE (
-  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
-  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
-  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
-  FLOATING                    boolean        not null,
-  START_DATE                  timestamp      not null,
-  END_DATE                    timestamp      not null,
-  FBTYPE                      integer        not null,
-  TRANSPARENT                 boolean        not null
-);
-
-create index TIME_RANGE_CALENDAR_RESOURCE_ID on
-  TIME_RANGE(CALENDAR_RESOURCE_ID);
-create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
-  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
-
-
--- Enumeration of free/busy types
-
-create table FREE_BUSY_TYPE (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into FREE_BUSY_TYPE values (0, 'unknown'         );
-insert into FREE_BUSY_TYPE values (1, 'free'            );
-insert into FREE_BUSY_TYPE values (2, 'busy'            );
-insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
-insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
-
-
-------------------
--- Transparency --
-------------------
-
-create table TRANSPARENCY (
-  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
-  USER_ID                     varchar(255) not null,
-  TRANSPARENT                 boolean      not null
-);
-
-create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
-  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
-
-
-----------------
--- Attachment --
-----------------
-
-create sequence ATTACHMENT_ID_SEQ;
-
-create table ATTACHMENT (
-  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
-  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
-  DROPBOX_ID                  varchar(255),
-  CONTENT_TYPE                varchar(255)      not null,
-  SIZE                        integer           not null,
-  MD5                         char(32)          not null,
-  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
-  PATH                        varchar(1024)     not null
-);
-
-create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
-  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
-
--- Many-to-many relationship between attachments and calendar objects
-create table ATTACHMENT_CALENDAR_OBJECT (
-  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
-  MANAGED_ID                     varchar(255) not null,
-  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
-
-  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
-  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
-);
-
-create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
-        ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
-
------------------------
--- Resource Property --
------------------------
-
-create table RESOURCE_PROPERTY (
-  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
-  NAME        varchar(255) not null,
-  VALUE       text         not null, -- FIXME: xml?
-  VIEWER_UID  varchar(255),
-
-  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
-);
-
-
-----------------------
--- AddressBook Home --
-----------------------
-
-create table ADDRESSBOOK_HOME (
-  RESOURCE_ID                                      integer                        primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  ADDRESSBOOK_PROPERTY_STORE_ID        integer              default nextval('RESOURCE_ID_SEQ') not null,         -- implicit index
-  OWNER_UID                                        varchar(255)         not null unique,                                -- implicit index
-  DATAVERSION                                      integer              default 0 not null
-);
-
-
--------------------------------
--- AddressBook Home Metadata --
--------------------------------
-
-create table ADDRESSBOOK_HOME_METADATA (
-  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
-  QUOTA_USED_BYTES integer      default 0 not null,
-  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
------------------------------
--- Shared AddressBook Bind --
------------------------------
-
--- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
-
-create table SHARED_ADDRESSBOOK_BIND (
-  ADDRESSBOOK_HOME_RESOURCE_ID                        integer                        not null references ADDRESSBOOK_HOME,
-  OWNER_HOME_RESOURCE_ID                            integer              not null references ADDRESSBOOK_HOME on delete cascade,
-  ADDRESSBOOK_RESOURCE_NAME                            varchar(255)         not null,
-  BIND_MODE                                            integer              not null,        -- enum CALENDAR_BIND_MODE
-  BIND_STATUS                                          integer              not null,        -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                                           integer              default 0 not null,
-  MESSAGE                                              text,                                  -- FIXME: xml?
-
-  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
-);
-
-create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
-  SHARED_ADDRESSBOOK_BIND(OWNER_HOME_RESOURCE_ID);
-
-
-------------------------
--- AddressBook Object --
-------------------------
-
-create table ADDRESSBOOK_OBJECT (
-  RESOURCE_ID                             integer                   primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
-  ADDRESSBOOK_HOME_RESOURCE_ID         integer              not null references ADDRESSBOOK_HOME on delete cascade,
-  RESOURCE_NAME                           varchar(255)         not null,
-  VCARD_TEXT                              text                 not null,
-  VCARD_UID                               varchar(255)         not null,
-  KIND                                                             integer              not null,  -- enum ADDRESSBOOK_OBJECT_KIND
-  MD5                                     char(32)             not null,
-  CREATED                                 timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
-  MODIFIED                                timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
-
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID)      -- implicit index
-);
-
-
------------------------------
--- AddressBook Object kind --
------------------------------
-
-create table ADDRESSBOOK_OBJECT_KIND (
-  ID          integer     primary key,
-  DESCRIPTION varchar(16) not null unique
-);
-
-insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
-insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
-insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
-insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
-
-
----------------------------------
--- Address Book Object Members --
----------------------------------
-
-create table ABO_MEMBERS (
-    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
-         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
-    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,                                                -- member AddressBook Object's RESOURCE_ID
-
-    primary key (GROUP_ID, MEMBER_ID) -- implicit index
-);
-
-create index ABO_MEMBERS_ADDRESSBOOK_ID on
-        ABO_MEMBERS(ADDRESSBOOK_ID);
-create index ABO_MEMBERS_MEMBER_ID on
-        ABO_MEMBERS(MEMBER_ID);
-
-------------------------------------------
--- Address Book Object Foreign Members  --
-------------------------------------------
-
-create table ABO_FOREIGN_MEMBERS (
-    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
-         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
-    MEMBER_ADDRESS            varchar(255) not null,                                                                                                         -- member AddressBook Object's 'calendar' address
-
-    primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
-);
-
-create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
-        ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
-
------------------------
--- Shared Group Bind --
------------------------
-
--- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
-
-create table SHARED_GROUP_BIND (        
-  ADDRESSBOOK_HOME_RESOURCE_ID                 integer      not null references ADDRESSBOOK_HOME,
-  GROUP_RESOURCE_ID                              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
-  GROUP_ADDRESSBOOK_NAME                        varchar(255) not null,
-  BIND_MODE                                    integer      not null, -- enum CALENDAR_BIND_MODE
-  BIND_STATUS                                  integer      not null, -- enum CALENDAR_BIND_STATUS
-  BIND_REVISION                                                   integer      default 0 not null,
-  MESSAGE                                      text,                  -- FIXME: xml?
-
-  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME)     -- implicit index
-);
-
-create index SHARED_GROUP_BIND_RESOURCE_ID on
-  SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
-
-
----------------
--- Revisions --
----------------
-
-create sequence REVISION_SEQ;
-
-
--------------------------------
--- Calendar Object Revisions --
--------------------------------
-
-create table CALENDAR_OBJECT_REVISIONS (
-  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
-  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
-  CALENDAR_NAME             varchar(255) default null,
-  RESOURCE_NAME             varchar(255),
-  REVISION                  integer      default nextval('REVISION_SEQ') not null,
-  DELETED                   boolean      not null
-);
-
-create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
-
-create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME);
-
-create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
-
-
-----------------------------------
--- AddressBook Object Revisions --
-----------------------------------
-
-create table ADDRESSBOOK_OBJECT_REVISIONS (
-  ADDRESSBOOK_HOME_RESOURCE_ID                         integer                        not null references ADDRESSBOOK_HOME,
-  OWNER_HOME_RESOURCE_ID                            integer             references ADDRESSBOOK_HOME,
-  ADDRESSBOOK_NAME                                     varchar(255)         default null,
-  RESOURCE_NAME                                        varchar(255),
-  REVISION                                             integer             default nextval('REVISION_SEQ') not null,
-  DELETED                                              boolean              not null
-);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID
-  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME
-  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME);
-
-create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
-  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, REVISION);
-
-
------------------------------------
--- Notification Object Revisions --
------------------------------------
-
-create table NOTIFICATION_OBJECT_REVISIONS (
-  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
-  RESOURCE_NAME                 varchar(255),
-  REVISION                      integer      default nextval('REVISION_SEQ') not null,
-  DELETED                       boolean      not null,
-
-  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
-);
-
-create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
-  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
-
-
--------------------------------------------
--- Apple Push Notification Subscriptions --
--------------------------------------------
-
-create table APN_SUBSCRIPTIONS (
-  TOKEN                         varchar(255) not null,
-  RESOURCE_KEY                  varchar(255) not null,
-  MODIFIED                      integer      not null,
-  SUBSCRIBER_GUID               varchar(255) not null,
-  USER_AGENT                    varchar(255) default null,
-  IP_ADDR                       varchar(255) default null,
-
-  primary key (TOKEN, RESOURCE_KEY) -- implicit index
-);
-
-create index APN_SUBSCRIPTIONS_RESOURCE_KEY
-   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
-
-   
------------------
--- IMIP Tokens --
------------------
-
-create table IMIP_TOKENS (
-  TOKEN                         varchar(255) not null,
-  ORGANIZER                     varchar(255) not null,
-  ATTENDEE                      varchar(255) not null,
-  ICALUID                       varchar(255) not null,
-  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-
-  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
-);
-
-create index IMIP_TOKENS_TOKEN
-   on IMIP_TOKENS(TOKEN);
-
-   
-----------------
--- Work Items --
-----------------
-
-create sequence WORKITEM_SEQ;
-
-
----------------------------
--- IMIP Inivitation Work --
----------------------------
-
-create table IMIP_INVITATION_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  FROM_ADDR                     varchar(255) not null,
-  TO_ADDR                       varchar(255) not null,
-  ICALENDAR_TEXT                text         not null
-);
-
-
------------------------
--- IMIP Polling Work --
------------------------
-
-create table IMIP_POLLING_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
----------------------
--- IMIP Reply Work --
----------------------
-
-create table IMIP_REPLY_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  ORGANIZER                     varchar(255) not null,
-  ATTENDEE                      varchar(255) not null,
-  ICALENDAR_TEXT                text         not null
-);
-
-
-------------------------
--- Push Notifications --
-------------------------
-
-create table PUSH_NOTIFICATION_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  PUSH_ID                       varchar(255) not null
-);
-
------------------
--- GroupCacher --
------------------
-
-create table GROUP_CACHER_POLLING_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
-);
-
-
---------------------------
--- Object Splitter Work --
---------------------------
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
-  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
-  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  RESOURCE_ID                   integer      not null references CALENDAR_OBJECT on delete cascade
-);
-
-create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
-        CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
-
---------------------
--- Schema Version --
---------------------
-
-create table CALENDARSERVER (
-  NAME                          varchar(255) primary key, -- implicit index
-  VALUE                         varchar(255)
-);
-
-insert into CALENDARSERVER values ('VERSION', '25');
-insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
-insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv25sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldpostgresdialectv25sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,700 @@
</span><ins>+-- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
+
+----
+-- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+
+-----------------
+-- Resource ID --
+-----------------
+
+create sequence RESOURCE_ID_SEQ;
+
+
+-------------------------
+-- Cluster Bookkeeping --
+-------------------------
+
+-- Information about a process connected to this database.
+
+-- 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),
+
+  primary key (HOSTNAME, PORT)
+);
+
+-- Unique named locks.  This table should always be empty, but rows are
+-- temporarily created in order to prevent undesirable concurrency.
+create table NAMED_LOCK (
+    LOCK_NAME varchar(255) primary key
+);
+
+
+-------------------
+-- Calendar Home --
+-------------------
+
+create table CALENDAR_HOME (
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  DATAVERSION      integer      default 0 not null
+);
+
+--------------
+-- Calendar --
+--------------
+
+create table CALENDAR (
+  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+----------------------------
+-- Calendar Home Metadata --
+----------------------------
+
+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,
+  ALARM_VEVENT_TIMED       text        default null,
+  ALARM_VEVENT_ALLDAY      text        default null,
+  ALARM_VTODO_TIMED        text        default null,
+  ALARM_VTODO_ALLDAY       text        default null,
+  AVAILABILITY             text        default null,
+  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
+        CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
+create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
+        CALENDAR_HOME_METADATA(DEFAULT_TASKS);
+
+-----------------------
+-- Calendar Metadata --
+-----------------------
+
+create table CALENDAR_METADATA (
+  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)
+);
+
+
+---------------------------
+-- Sharing Notifications --
+---------------------------
+
+create table NOTIFICATION_HOME (
+  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID   varchar(255) not null unique                                 -- implicit index
+);
+
+create table NOTIFICATION (
+  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
+  NOTIFICATION_UID              varchar(255) not null,
+  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),
+
+  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
+);
+
+create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
+        NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
+
+
+-------------------
+-- Calendar Bind --
+-------------------
+
+-- Joins CALENDAR_HOME and CALENDAR
+
+create table CALENDAR_BIND (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  CALENDAR_RESOURCE_NAME    varchar(255) not null,
+  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                integer      default 0 not null,
+  MESSAGE                   text,
+  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,
+  TIMEZONE                  text         default null,
+
+  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
+  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
+);
+
+create index CALENDAR_BIND_RESOURCE_ID on
+        CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+
+-- Enumeration of calendar bind modes
+
+create table CALENDAR_BIND_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_MODE values (0, 'own'  );
+insert into CALENDAR_BIND_MODE values (1, 'read' );
+insert into CALENDAR_BIND_MODE values (2, 'write');
+insert into CALENDAR_BIND_MODE values (3, 'direct');
+
+-- Enumeration of statuses
+
+create table CALENDAR_BIND_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_STATUS values (0, 'invited' );
+insert into CALENDAR_BIND_STATUS values (1, 'accepted');
+insert into CALENDAR_BIND_STATUS values (2, 'declined');
+insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+
+
+-- Enumeration of transparency
+
+create table CALENDAR_TRANSP (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
+
+---------------------
+-- Calendar Object --
+---------------------
+
+create table CALENDAR_OBJECT (
+  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
+  RESOURCE_NAME        varchar(255) not null,
+  ICALENDAR_TEXT       text         not null,
+  ICALENDAR_UID        varchar(255) not null,
+  ICALENDAR_TYPE       varchar(255) not null,
+  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  DROPBOX_ID           varchar(255),
+  ORGANIZER            varchar(255),
+  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
+  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
+  ACCESS               integer      default 0 not null,
+  SCHEDULE_OBJECT      boolean      default false,
+  SCHEDULE_TAG         varchar(36)  default null,
+  SCHEDULE_ETAGS       text         default null,
+  PRIVATE_COMMENTS     boolean      default false not null,
+  MD5                  char(32)     not null,
+  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+
+  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+  -- calendar objects, this constraint has to be selectively enforced by the
+  -- application layer.
+
+  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
+
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+  CALENDAR_OBJECT(ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_DROPBOX_ID on
+  CALENDAR_OBJECT(DROPBOX_ID);
+
+-- Enumeration of attachment modes
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
+
+
+-- Enumeration of calendar access types
+
+create table CALENDAR_ACCESS_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(32) not null unique
+);
+
+insert into CALENDAR_ACCESS_TYPE values (0, ''             );
+insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
+insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
+insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
+insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
+
+
+-----------------
+-- Instance ID --
+-----------------
+
+create sequence INSTANCE_ID_SEQ;
+
+
+----------------
+-- Time Range --
+----------------
+
+create table TIME_RANGE (
+  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
+  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
+  FLOATING                    boolean        not null,
+  START_DATE                  timestamp      not null,
+  END_DATE                    timestamp      not null,
+  FBTYPE                      integer        not null,
+  TRANSPARENT                 boolean        not null
+);
+
+create index TIME_RANGE_CALENDAR_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_RESOURCE_ID);
+create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
+
+
+-- Enumeration of free/busy types
+
+create table FREE_BUSY_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into FREE_BUSY_TYPE values (0, 'unknown'         );
+insert into FREE_BUSY_TYPE values (1, 'free'            );
+insert into FREE_BUSY_TYPE values (2, 'busy'            );
+insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
+insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
+
+
+------------------
+-- Transparency --
+------------------
+
+create table TRANSPARENCY (
+  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
+  USER_ID                     varchar(255) not null,
+  TRANSPARENT                 boolean      not null
+);
+
+create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
+  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
+
+
+----------------
+-- Attachment --
+----------------
+
+create sequence ATTACHMENT_ID_SEQ;
+
+create table ATTACHMENT (
+  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
+  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
+  DROPBOX_ID                  varchar(255),
+  CONTENT_TYPE                varchar(255)      not null,
+  SIZE                        integer           not null,
+  MD5                         char(32)          not null,
+  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  PATH                        varchar(1024)     not null
+);
+
+create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
+  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
+
+-- Many-to-many relationship between attachments and calendar objects
+create table ATTACHMENT_CALENDAR_OBJECT (
+  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
+  MANAGED_ID                     varchar(255) not null,
+  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
+
+  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
+  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
+);
+
+create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
+        ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
+
+-----------------------
+-- Resource Property --
+-----------------------
+
+create table RESOURCE_PROPERTY (
+  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
+  NAME        varchar(255) not null,
+  VALUE       text         not null, -- FIXME: xml?
+  VIEWER_UID  varchar(255),
+
+  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
+);
+
+
+----------------------
+-- AddressBook Home --
+----------------------
+
+create table ADDRESSBOOK_HOME (
+  RESOURCE_ID                                      integer                        primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  ADDRESSBOOK_PROPERTY_STORE_ID        integer              default nextval('RESOURCE_ID_SEQ') not null,         -- implicit index
+  OWNER_UID                                        varchar(255)         not null unique,                                -- implicit index
+  DATAVERSION                                      integer              default 0 not null
+);
+
+
+-------------------------------
+-- AddressBook Home Metadata --
+-------------------------------
+
+create table ADDRESSBOOK_HOME_METADATA (
+  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES integer      default 0 not null,
+  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+-----------------------------
+-- Shared AddressBook Bind --
+-----------------------------
+
+-- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
+
+create table SHARED_ADDRESSBOOK_BIND (
+  ADDRESSBOOK_HOME_RESOURCE_ID                        integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_HOME_RESOURCE_ID                            integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  ADDRESSBOOK_RESOURCE_NAME                            varchar(255)         not null,
+  BIND_MODE                                            integer              not null,        -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                          integer              not null,        -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                           integer              default 0 not null,
+  MESSAGE                                              text,                                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
+);
+
+create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
+  SHARED_ADDRESSBOOK_BIND(OWNER_HOME_RESOURCE_ID);
+
+
+------------------------
+-- AddressBook Object --
+------------------------
+
+create table ADDRESSBOOK_OBJECT (
+  RESOURCE_ID                             integer                   primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
+  ADDRESSBOOK_HOME_RESOURCE_ID         integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  RESOURCE_NAME                           varchar(255)         not null,
+  VCARD_TEXT                              text                 not null,
+  VCARD_UID                               varchar(255)         not null,
+  KIND                                                             integer              not null,  -- enum ADDRESSBOOK_OBJECT_KIND
+  MD5                                     char(32)             not null,
+  CREATED                                 timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                                timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID)      -- implicit index
+);
+
+
+-----------------------------
+-- AddressBook Object kind --
+-----------------------------
+
+create table ADDRESSBOOK_OBJECT_KIND (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
+
+
+---------------------------------
+-- Address Book Object Members --
+---------------------------------
+
+create table ABO_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,                                                -- member AddressBook Object's RESOURCE_ID
+
+    primary key (GROUP_ID, MEMBER_ID) -- implicit index
+);
+
+create index ABO_MEMBERS_ADDRESSBOOK_ID on
+        ABO_MEMBERS(ADDRESSBOOK_ID);
+create index ABO_MEMBERS_MEMBER_ID on
+        ABO_MEMBERS(MEMBER_ID);
+
+------------------------------------------
+-- Address Book Object Foreign Members  --
+------------------------------------------
+
+create table ABO_FOREIGN_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ADDRESS            varchar(255) not null,                                                                                                         -- member AddressBook Object's 'calendar' address
+
+    primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
+);
+
+create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
+        ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
+
+-----------------------
+-- Shared Group Bind --
+-----------------------
+
+-- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
+
+create table SHARED_GROUP_BIND (        
+  ADDRESSBOOK_HOME_RESOURCE_ID                 integer      not null references ADDRESSBOOK_HOME,
+  GROUP_RESOURCE_ID                              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
+  GROUP_ADDRESSBOOK_NAME                        varchar(255) not null,
+  BIND_MODE                                    integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                  integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                   integer      default 0 not null,
+  MESSAGE                                      text,                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME)     -- implicit index
+);
+
+create index SHARED_GROUP_BIND_RESOURCE_ID on
+  SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
+
+
+---------------
+-- Revisions --
+---------------
+
+create sequence REVISION_SEQ;
+
+
+-------------------------------
+-- Calendar Object Revisions --
+-------------------------------
+
+create table CALENDAR_OBJECT_REVISIONS (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
+  CALENDAR_NAME             varchar(255) default null,
+  RESOURCE_NAME             varchar(255),
+  REVISION                  integer      default nextval('REVISION_SEQ') not null,
+  DELETED                   boolean      not null
+);
+
+create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
+
+
+----------------------------------
+-- AddressBook Object Revisions --
+----------------------------------
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+  ADDRESSBOOK_HOME_RESOURCE_ID                         integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_HOME_RESOURCE_ID                            integer             references ADDRESSBOOK_HOME,
+  ADDRESSBOOK_NAME                                     varchar(255)         default null,
+  RESOURCE_NAME                                        varchar(255),
+  REVISION                                             integer             default nextval('REVISION_SEQ') not null,
+  DELETED                                              boolean              not null
+);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, REVISION);
+
+
+-----------------------------------
+-- Notification Object Revisions --
+-----------------------------------
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
+  RESOURCE_NAME                 varchar(255),
+  REVISION                      integer      default nextval('REVISION_SEQ') not null,
+  DELETED                       boolean      not null,
+
+  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+);
+
+create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
+
+
+-------------------------------------------
+-- Apple Push Notification Subscriptions --
+-------------------------------------------
+
+create table APN_SUBSCRIPTIONS (
+  TOKEN                         varchar(255) not null,
+  RESOURCE_KEY                  varchar(255) not null,
+  MODIFIED                      integer      not null,
+  SUBSCRIBER_GUID               varchar(255) not null,
+  USER_AGENT                    varchar(255) default null,
+  IP_ADDR                       varchar(255) default null,
+
+  primary key (TOKEN, RESOURCE_KEY) -- implicit index
+);
+
+create index APN_SUBSCRIPTIONS_RESOURCE_KEY
+   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
+
+   
+-----------------
+-- IMIP Tokens --
+-----------------
+
+create table IMIP_TOKENS (
+  TOKEN                         varchar(255) not null,
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALUID                       varchar(255) not null,
+  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
+);
+
+create index IMIP_TOKENS_TOKEN
+   on IMIP_TOKENS(TOKEN);
+
+   
+----------------
+-- Work Items --
+----------------
+
+create sequence WORKITEM_SEQ;
+
+
+---------------------------
+-- IMIP Inivitation Work --
+---------------------------
+
+create table IMIP_INVITATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  FROM_ADDR                     varchar(255) not null,
+  TO_ADDR                       varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+-----------------------
+-- IMIP Polling Work --
+-----------------------
+
+create table IMIP_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------
+-- IMIP Reply Work --
+---------------------
+
+create table IMIP_REPLY_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+------------------------
+-- Push Notifications --
+------------------------
+
+create table PUSH_NOTIFICATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  PUSH_ID                       varchar(255) not null
+);
+
+-----------------
+-- GroupCacher --
+-----------------
+
+create table GROUP_CACHER_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+--------------------------
+-- Object Splitter Work --
+--------------------------
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  RESOURCE_ID                   integer      not null references CALENDAR_OBJECT on delete cascade
+);
+
+create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
+        CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
+
+--------------------
+-- Schema Version --
+--------------------
+
+create table CALENDARSERVER (
+  NAME                          varchar(255) primary key, -- implicit index
+  VALUE                         varchar(255)
+);
+
+insert into CALENDARSERVER values ('VERSION', '25');
+insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaoldpostgresdialectv26sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaoldpostgresdialectv26sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,700 @@
</span><ins>+-- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
+
+----
+-- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+
+-----------------
+-- Resource ID --
+-----------------
+
+create sequence RESOURCE_ID_SEQ;
+
+
+-------------------------
+-- Cluster Bookkeeping --
+-------------------------
+
+-- Information about a process connected to this database.
+
+-- 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),
+
+  primary key (HOSTNAME, PORT)
+);
+
+-- Unique named locks.  This table should always be empty, but rows are
+-- temporarily created in order to prevent undesirable concurrency.
+create table NAMED_LOCK (
+    LOCK_NAME varchar(255) primary key
+);
+
+
+-------------------
+-- Calendar Home --
+-------------------
+
+create table CALENDAR_HOME (
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  DATAVERSION      integer      default 0 not null
+);
+
+--------------
+-- Calendar --
+--------------
+
+create table CALENDAR (
+  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+----------------------------
+-- Calendar Home Metadata --
+----------------------------
+
+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,
+  ALARM_VEVENT_TIMED       text        default null,
+  ALARM_VEVENT_ALLDAY      text        default null,
+  ALARM_VTODO_TIMED        text        default null,
+  ALARM_VTODO_ALLDAY       text        default null,
+  AVAILABILITY             text        default null,
+  CREATED                  timestamp   default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
+        CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
+create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
+        CALENDAR_HOME_METADATA(DEFAULT_TASKS);
+
+-----------------------
+-- Calendar Metadata --
+-----------------------
+
+create table CALENDAR_METADATA (
+  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)
+);
+
+
+---------------------------
+-- Sharing Notifications --
+---------------------------
+
+create table NOTIFICATION_HOME (
+  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID   varchar(255) not null unique                                 -- implicit index
+);
+
+create table NOTIFICATION (
+  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
+  NOTIFICATION_UID              varchar(255) not null,
+  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),
+
+  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
+);
+
+create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
+        NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
+
+
+-------------------
+-- Calendar Bind --
+-------------------
+
+-- Joins CALENDAR_HOME and CALENDAR
+
+create table CALENDAR_BIND (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  CALENDAR_RESOURCE_NAME    varchar(255) not null,
+  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                integer      default 0 not null,
+  MESSAGE                   text,
+  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,
+  TIMEZONE                  text         default null,
+
+  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
+  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
+);
+
+create index CALENDAR_BIND_RESOURCE_ID on
+        CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+
+-- Enumeration of calendar bind modes
+
+create table CALENDAR_BIND_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_MODE values (0, 'own'  );
+insert into CALENDAR_BIND_MODE values (1, 'read' );
+insert into CALENDAR_BIND_MODE values (2, 'write');
+insert into CALENDAR_BIND_MODE values (3, 'direct');
+
+-- Enumeration of statuses
+
+create table CALENDAR_BIND_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_STATUS values (0, 'invited' );
+insert into CALENDAR_BIND_STATUS values (1, 'accepted');
+insert into CALENDAR_BIND_STATUS values (2, 'declined');
+insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+
+
+-- Enumeration of transparency
+
+create table CALENDAR_TRANSP (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
+
+---------------------
+-- Calendar Object --
+---------------------
+
+create table CALENDAR_OBJECT (
+  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
+  RESOURCE_NAME        varchar(255) not null,
+  ICALENDAR_TEXT       text         not null,
+  ICALENDAR_UID        varchar(255) not null,
+  ICALENDAR_TYPE       varchar(255) not null,
+  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  DROPBOX_ID           varchar(255),
+  ORGANIZER            varchar(255),
+  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
+  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
+  ACCESS               integer      default 0 not null,
+  SCHEDULE_OBJECT      boolean      default false,
+  SCHEDULE_TAG         varchar(36)  default null,
+  SCHEDULE_ETAGS       text         default null,
+  PRIVATE_COMMENTS     boolean      default false not null,
+  MD5                  char(32)     not null,
+  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+
+  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+  -- calendar objects, this constraint has to be selectively enforced by the
+  -- application layer.
+
+  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
+
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+  CALENDAR_OBJECT(ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_DROPBOX_ID on
+  CALENDAR_OBJECT(DROPBOX_ID);
+
+-- Enumeration of attachment modes
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
+
+
+-- Enumeration of calendar access types
+
+create table CALENDAR_ACCESS_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(32) not null unique
+);
+
+insert into CALENDAR_ACCESS_TYPE values (0, ''             );
+insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
+insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
+insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
+insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
+
+
+-----------------
+-- Instance ID --
+-----------------
+
+create sequence INSTANCE_ID_SEQ;
+
+
+----------------
+-- Time Range --
+----------------
+
+create table TIME_RANGE (
+  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
+  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
+  FLOATING                    boolean        not null,
+  START_DATE                  timestamp      not null,
+  END_DATE                    timestamp      not null,
+  FBTYPE                      integer        not null,
+  TRANSPARENT                 boolean        not null
+);
+
+create index TIME_RANGE_CALENDAR_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_RESOURCE_ID);
+create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
+
+
+-- Enumeration of free/busy types
+
+create table FREE_BUSY_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into FREE_BUSY_TYPE values (0, 'unknown'         );
+insert into FREE_BUSY_TYPE values (1, 'free'            );
+insert into FREE_BUSY_TYPE values (2, 'busy'            );
+insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
+insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
+
+
+------------------
+-- Transparency --
+------------------
+
+create table TRANSPARENCY (
+  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
+  USER_ID                     varchar(255) not null,
+  TRANSPARENT                 boolean      not null
+);
+
+create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
+  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
+
+
+----------------
+-- Attachment --
+----------------
+
+create sequence ATTACHMENT_ID_SEQ;
+
+create table ATTACHMENT (
+  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
+  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
+  DROPBOX_ID                  varchar(255),
+  CONTENT_TYPE                varchar(255)      not null,
+  SIZE                        integer           not null,
+  MD5                         char(32)          not null,
+  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  PATH                        varchar(1024)     not null
+);
+
+create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
+  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
+
+-- Many-to-many relationship between attachments and calendar objects
+create table ATTACHMENT_CALENDAR_OBJECT (
+  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
+  MANAGED_ID                     varchar(255) not null,
+  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
+
+  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
+  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
+);
+
+create index ATTACHMENT_CALENDAR_OBJECT_CALENDAR_OBJECT_RESOURCE_ID on
+        ATTACHMENT_CALENDAR_OBJECT(CALENDAR_OBJECT_RESOURCE_ID);
+
+-----------------------
+-- Resource Property --
+-----------------------
+
+create table RESOURCE_PROPERTY (
+  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
+  NAME        varchar(255) not null,
+  VALUE       text         not null, -- FIXME: xml?
+  VIEWER_UID  varchar(255),
+
+  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
+);
+
+
+----------------------
+-- AddressBook Home --
+----------------------
+
+create table ADDRESSBOOK_HOME (
+  RESOURCE_ID                                      integer                        primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  ADDRESSBOOK_PROPERTY_STORE_ID        integer              default nextval('RESOURCE_ID_SEQ') not null,         -- implicit index
+  OWNER_UID                                        varchar(255)         not null unique,                                -- implicit index
+  DATAVERSION                                      integer              default 0 not null
+);
+
+
+-------------------------------
+-- AddressBook Home Metadata --
+-------------------------------
+
+create table ADDRESSBOOK_HOME_METADATA (
+  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES integer      default 0 not null,
+  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+-----------------------------
+-- Shared AddressBook Bind --
+-----------------------------
+
+-- Joins sharee ADDRESSBOOK_HOME and owner ADDRESSBOOK_HOME
+
+create table SHARED_ADDRESSBOOK_BIND (
+  ADDRESSBOOK_HOME_RESOURCE_ID                        integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_HOME_RESOURCE_ID                            integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  ADDRESSBOOK_RESOURCE_NAME                            varchar(255)         not null,
+  BIND_MODE                                            integer              not null,        -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                          integer              not null,        -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                           integer              default 0 not null,
+  MESSAGE                                              text,                                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
+);
+
+create index SHARED_ADDRESSBOOK_BIND_RESOURCE_ID on
+  SHARED_ADDRESSBOOK_BIND(OWNER_HOME_RESOURCE_ID);
+
+
+------------------------
+-- AddressBook Object --
+------------------------
+
+create table ADDRESSBOOK_OBJECT (
+  RESOURCE_ID                             integer                   primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
+  ADDRESSBOOK_HOME_RESOURCE_ID         integer              not null references ADDRESSBOOK_HOME on delete cascade,
+  RESOURCE_NAME                           varchar(255)         not null,
+  VCARD_TEXT                              text                 not null,
+  VCARD_UID                               varchar(255)         not null,
+  KIND                                                             integer              not null,  -- enum ADDRESSBOOK_OBJECT_KIND
+  MD5                                     char(32)             not null,
+  CREATED                                 timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                                timestamp            default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, RESOURCE_NAME), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, VCARD_UID)      -- implicit index
+);
+
+
+-----------------------------
+-- AddressBook Object kind --
+-----------------------------
+
+create table ADDRESSBOOK_OBJECT_KIND (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into ADDRESSBOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESSBOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESSBOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
+
+
+---------------------------------
+-- Address Book Object Members --
+---------------------------------
+
+create table ABO_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,                                                -- member AddressBook Object's RESOURCE_ID
+
+    primary key (GROUP_ID, MEMBER_ID) -- implicit index
+);
+
+create index ABO_MEMBERS_ADDRESSBOOK_ID on
+        ABO_MEMBERS(ADDRESSBOOK_ID);
+create index ABO_MEMBERS_MEMBER_ID on
+        ABO_MEMBERS(MEMBER_ID);
+
+------------------------------------------
+-- Address Book Object Foreign Members  --
+------------------------------------------
+
+create table ABO_FOREIGN_MEMBERS (
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,        -- AddressBook Object's (kind=='group') RESOURCE_ID
+         ADDRESSBOOK_ID                  integer      not null references ADDRESSBOOK_HOME on delete cascade,
+    MEMBER_ADDRESS            varchar(255) not null,                                                                                                         -- member AddressBook Object's 'calendar' address
+
+    primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
+);
+
+create index ABO_FOREIGN_MEMBERS_ADDRESSBOOK_ID on
+        ABO_FOREIGN_MEMBERS(ADDRESSBOOK_ID);
+
+-----------------------
+-- Shared Group Bind --
+-----------------------
+
+-- Joins ADDRESSBOOK_HOME and ADDRESSBOOK_OBJECT (kind == group)
+
+create table SHARED_GROUP_BIND (        
+  ADDRESSBOOK_HOME_RESOURCE_ID                 integer      not null references ADDRESSBOOK_HOME,
+  GROUP_RESOURCE_ID                              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
+  GROUP_ADDRESSBOOK_NAME                        varchar(255) not null,
+  BIND_MODE                                    integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                                  integer      not null, -- enum CALENDAR_BIND_STATUS
+  BIND_REVISION                                                   integer      default 0 not null,
+  MESSAGE                                      text,                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME)     -- implicit index
+);
+
+create index SHARED_GROUP_BIND_RESOURCE_ID on
+  SHARED_GROUP_BIND(GROUP_RESOURCE_ID);
+
+
+---------------
+-- Revisions --
+---------------
+
+create sequence REVISION_SEQ;
+
+
+-------------------------------
+-- Calendar Object Revisions --
+-------------------------------
+
+create table CALENDAR_OBJECT_REVISIONS (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
+  CALENDAR_NAME             varchar(255) default null,
+  RESOURCE_NAME             varchar(255),
+  REVISION                  integer      default nextval('REVISION_SEQ') not null,
+  DELETED                   boolean      not null
+);
+
+create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
+
+
+----------------------------------
+-- AddressBook Object Revisions --
+----------------------------------
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+  ADDRESSBOOK_HOME_RESOURCE_ID                         integer                        not null references ADDRESSBOOK_HOME,
+  OWNER_HOME_RESOURCE_ID                            integer             references ADDRESSBOOK_HOME,
+  ADDRESSBOOK_NAME                                     varchar(255)         default null,
+  RESOURCE_NAME                                        varchar(255),
+  REVISION                                             integer             default nextval('REVISION_SEQ') not null,
+  DELETED                                              boolean              not null
+);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, OWNER_HOME_RESOURCE_ID);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, REVISION);
+
+
+-----------------------------------
+-- Notification Object Revisions --
+-----------------------------------
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
+  RESOURCE_NAME                 varchar(255),
+  REVISION                      integer      default nextval('REVISION_SEQ') not null,
+  DELETED                       boolean      not null,
+
+  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+);
+
+create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
+
+
+-------------------------------------------
+-- Apple Push Notification Subscriptions --
+-------------------------------------------
+
+create table APN_SUBSCRIPTIONS (
+  TOKEN                         varchar(255) not null,
+  RESOURCE_KEY                  varchar(255) not null,
+  MODIFIED                      integer      not null,
+  SUBSCRIBER_GUID               varchar(255) not null,
+  USER_AGENT                    varchar(255) default null,
+  IP_ADDR                       varchar(255) default null,
+
+  primary key (TOKEN, RESOURCE_KEY) -- implicit index
+);
+
+create index APN_SUBSCRIPTIONS_RESOURCE_KEY
+   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
+
+   
+-----------------
+-- IMIP Tokens --
+-----------------
+
+create table IMIP_TOKENS (
+  TOKEN                         varchar(255) not null,
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALUID                       varchar(255) not null,
+  ACCESSED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
+);
+
+create index IMIP_TOKENS_TOKEN
+   on IMIP_TOKENS(TOKEN);
+
+   
+----------------
+-- Work Items --
+----------------
+
+create sequence WORKITEM_SEQ;
+
+
+---------------------------
+-- IMIP Inivitation Work --
+---------------------------
+
+create table IMIP_INVITATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  FROM_ADDR                     varchar(255) not null,
+  TO_ADDR                       varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+-----------------------
+-- IMIP Polling Work --
+-----------------------
+
+create table IMIP_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------
+-- IMIP Reply Work --
+---------------------
+
+create table IMIP_REPLY_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+
+------------------------
+-- Push Notifications --
+------------------------
+
+create table PUSH_NOTIFICATION_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  PUSH_ID                       varchar(255) not null
+);
+
+-----------------
+-- GroupCacher --
+-----------------
+
+create table GROUP_CACHER_POLLING_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+--------------------------
+-- Object Splitter Work --
+--------------------------
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+  WORK_ID                       integer      primary key default nextval('WORKITEM_SEQ') not null, -- implicit index
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  RESOURCE_ID                   integer      not null references CALENDAR_OBJECT on delete cascade
+);
+
+create index CALENDAR_OBJECT_SPLITTER_WORK_RESOURCE_ID on
+        CALENDAR_OBJECT_SPLITTER_WORK(RESOURCE_ID);
+
+--------------------
+-- Schema Version --
+--------------------
+
+create table CALENDARSERVER (
+  NAME                          varchar(255) primary key, -- implicit index
+  VALUE                         varchar(255)
+);
+
+insert into CALENDARSERVER values ('VERSION', '26');
+insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
+insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_24_to_25sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,26 +0,0 @@
</span><del>-----
--- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
----------------------------------------------------
--- Upgrade database schema from VERSION 24 to 25 --
----------------------------------------------------
-
--- This is actually a noop for Oracle as we had some invalid names in the v20 schema that
--- were corrected in v20 (but not corrected in postgres which is being updated for v25).
-
--- Now update the version
--- No data upgrades
-update CALENDARSERVER set VALUE = '25' where NAME = 'VERSION';
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_24_to_25sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_24_to_25sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 24 to 25 --
+---------------------------------------------------
+
+-- This is actually a noop for Oracle as we had some invalid names in the v20 schema that
+-- were corrected in v20 (but not corrected in postgres which is being updated for v25).
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '25' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_25_to_26sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-----
--- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
----------------------------------------------------
--- Upgrade database schema from VERSION 25 to 26 --
----------------------------------------------------
-
--- Replace index
-
-drop index CALENDAR_OBJECT_REVIS_2643d556;
-create index CALENDAR_OBJECT_REVIS_6d9d929c on CALENDAR_OBJECT_REVISIONS (
-    CALENDAR_RESOURCE_ID,
-    RESOURCE_NAME,
-    DELETED,
-    REVISION
-);
-
-
-drop index ADDRESSBOOK_OBJECT_RE_980b9872;
-create index ADDRESSBOOK_OBJECT_RE_00fe8288 on ADDRESSBOOK_OBJECT_REVISIONS (
-    OWNER_HOME_RESOURCE_ID,
-    RESOURCE_NAME,
-    DELETED,
-    REVISION
-);
-
-
--- Now update the version
--- No data upgrades
-update CALENDARSERVER set VALUE = '26' where NAME = 'VERSION';
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_25_to_26sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_25_to_26sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 25 to 26 --
+---------------------------------------------------
+
+-- Replace index
+
+drop index CALENDAR_OBJECT_REVIS_2643d556;
+create index CALENDAR_OBJECT_REVIS_6d9d929c on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    RESOURCE_NAME,
+    DELETED,
+    REVISION
+);
+
+
+drop index ADDRESSBOOK_OBJECT_RE_980b9872;
+create index ADDRESSBOOK_OBJECT_RE_00fe8288 on ADDRESSBOOK_OBJECT_REVISIONS (
+    OWNER_HOME_RESOURCE_ID,
+    RESOURCE_NAME,
+    DELETED,
+    REVISION
+);
+
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '26' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_26_to_27sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_26_to_27sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 26 to 27 --
+---------------------------------------------------
+
+-- Calendar home related updates
+
+alter table CALENDAR_HOME_METADATA
+ add (&quot;DEFAULT_POLLS&quot; integer default null references CALENDAR on delete set null);
+
+create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
+    DEFAULT_POLLS
+);
+
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '27' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_24_to_25sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,35 +0,0 @@
</span><del>-----
--- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
----------------------------------------------------
--- Upgrade database schema from VERSION 24 to 25 --
----------------------------------------------------
-
--- Rename columns and indexes
-alter table SHARED_ADDRESSBOOK_BIND
-        rename column OWNER_ADDRESSBOOK_HOME_RESOURCE_ID to OWNER_HOME_RESOURCE_ID;
-
-alter table SHARED_GROUP_BIND
-        rename column GROUP_ADDRESSBOOK_RESOURCE_NAME to GROUP_ADDRESSBOOK_NAME;
-
-alter table ADDRESSBOOK_OBJECT_REVISIONS
-        rename column OWNER_ADDRESSBOOK_HOME_RESOURCE_ID to OWNER_HOME_RESOURCE_ID;
-
-alter index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_ADDRESSBOOK_HOME_RESOURCE_ID rename to ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID;
-
--- Now update the version
--- No data upgrades
-update CALENDARSERVER set VALUE = '25' where NAME = 'VERSION';
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_24_to_25sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_24_to_25sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 24 to 25 --
+---------------------------------------------------
+
+-- Rename columns and indexes
+alter table SHARED_ADDRESSBOOK_BIND
+        rename column OWNER_ADDRESSBOOK_HOME_RESOURCE_ID to OWNER_HOME_RESOURCE_ID;
+
+alter table SHARED_GROUP_BIND
+        rename column GROUP_ADDRESSBOOK_RESOURCE_NAME to GROUP_ADDRESSBOOK_NAME;
+
+alter table ADDRESSBOOK_OBJECT_REVISIONS
+        rename column OWNER_ADDRESSBOOK_HOME_RESOURCE_ID to OWNER_HOME_RESOURCE_ID;
+
+alter index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_ADDRESSBOOK_HOME_RESOURCE_ID rename to ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_OWNER_HOME_RESOURCE_ID;
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '25' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_25_to_26sql"></a>
<div class="delfile"><h4>Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -1,32 +0,0 @@
</span><del>-----
--- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
---
--- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-----
-
----------------------------------------------------
--- Upgrade database schema from VERSION 25 to 26 --
----------------------------------------------------
-
--- Replace index
-drop index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME;
-create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
-  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
-
-drop index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME;
-create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
-  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
-
--- Now update the version
--- No data upgrades
-update CALENDARSERVER set VALUE = '26' where NAME = 'VERSION';
</del></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_25_to_26sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_25_to_26sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 25 to 26 --
+---------------------------------------------------
+
+-- Replace index
+drop index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME;
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+drop index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME;
+create index ADDRESSBOOK_OBJECT_REVISIONS_OWNER_HOME_RESOURCE_ID_RESOURCE_NAME_DELETED_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(OWNER_HOME_RESOURCE_ID, RESOURCE_NAME, DELETED, REVISION);
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '26' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_26_to_27sqlfromrev11912CalendarServerbranchesuserscdaboojsontxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_26_to_27sql"></a>
<div class="copfile"><h4>Copied: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql (from rev 11912, CalendarServer/branches/users/cdaboo/json/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql) (0 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql                                (rev 0)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+----
+-- Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 26 to 27 --
+---------------------------------------------------
+
+-- Calendar home related updates
+
+alter table CALENDAR_HOME_METADATA
+ add column DEFAULT_POLLS integer default null references CALENDAR on delete set null;
+
+create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
+        CALENDAR_HOME_METADATA(DEFAULT_POLLS);
+
+-- Now update the version
+-- No data upgrades
+update CALENDARSERVER set VALUE = '27' where NAME = 'VERSION';
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/test/util.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> from hashlib import md5
</span><span class="cx"> 
</span><del>-from pycalendar.datetime import PyCalendarDateTime
</del><ins>+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> from random import Random
</span><span class="cx"> 
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> from twisted.internet.task import deferLater
</span><span class="cx"> from twisted.trial.unittest import TestCase
</span><span class="cx"> 
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.stdconfig import DEFAULT_CONFIG
</span><span class="cx"> from twistedcaldav.vcard import Component as ABComponent
</span><span class="lines">@@ -447,12 +448,11 @@
</span><span class="cx">             # We don't want the default calendar or inbox to appear unless it's
</span><span class="cx">             # explicitly listed.
</span><span class="cx">             try:
</span><del>-                yield home.removeCalendarWithName(&quot;calendar&quot;)
-                # FIXME: this should be an argument to the function, not a
-                # global configuration variable.  Related: this needs
-                # independent tests.
</del><span class="cx">                 if config.RestrictCalendarsToOneComponentType:
</span><del>-                    yield home.removeCalendarWithName(&quot;tasks&quot;)
</del><ins>+                    for name in ical.allowedStoreComponents:
+                        yield home.removeCalendarWithName(home._componentCalendarName[name])
+                else:
+                    yield home.removeCalendarWithName(&quot;calendar&quot;)
</ins><span class="cx">                 yield home.removeCalendarWithName(&quot;inbox&quot;)
</span><span class="cx">             except NoSuchHomeChildError:
</span><span class="cx">                 pass
</span><span class="lines">@@ -480,7 +480,7 @@
</span><span class="cx">     Update the supplied iCalendar data so that all dates are updated to the current year.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    nowYear = PyCalendarDateTime.getToday().getYear()
</del><ins>+    nowYear = DateTime.getToday().getYear()
</ins><span class="cx">     return data % {&quot;now&quot;: nowYear}
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoreupgradesqlupgradescalendar_upgrade_from_3_to_4py"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py (11915 => 11916)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py        2013-11-08 20:38:45 UTC (rev 11915)
+++ CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py        2013-11-08 20:46:55 UTC (rev 11916)
</span><span class="lines">@@ -108,8 +108,12 @@
</span><span class="cx">                     calendar = (yield home.calendarWithName(calendarName))
</span><span class="cx">                     if calendar is not None:
</span><span class="cx">                         try:
</span><ins>+                            if propname == caldavxml.ScheduleDefaultCalendarURL:
+                                ctype = &quot;VEVENT&quot;
+                            elif propname == customxml.ScheduleDefaultTasksURL:
+                                ctype = &quot;VTODO&quot;
</ins><span class="cx">                             yield home.setDefaultCalendar(
</span><del>-                                calendar, tasks=(propname == customxml.ScheduleDefaultTasksURL)
</del><ins>+                                calendar, ctype
</ins><span class="cx">                             )
</span><span class="cx">                         except InvalidDefaultCalendar:
</span><span class="cx">                             # Ignore these - the server will recover
</span></span></pre>
</div>
</div>

</body>
</html>