<!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 = "/Search"
</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 ("-h", "--help"):
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx"> directoryMap.dumpDsImports(os.path.join(destDirectory, "dsimports"))
</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 = "<?xml version='1.0' encoding='UTF-8'?>\r\n<getctag xmlns='http://calendarserver.org/ns/'>%s</getctag>\r\n" % (str(datetime.datetime.now()),)
</span><span class="cx"> xattr.setxattr(destCal, "WebDAV:{http:%2F%2Fcalendarserver.org%2Fns%2F}getctag", zlib.compress(xml))
</span><span class="cx">
</span><del>-
</del><span class="cx"> # Calendar home quota
</span><span class="cx"> xml = "<?xml version='1.0' encoding='UTF-8'?>\r\n<quota-used xmlns='http://twistedmatrix.com/xml_namespace/dav/private/'>%d</quota-used>\r\n" % (quotaUsed,)
</span><span class="cx"> xattr.setxattr(destHome, "WebDAV:{http:%2F%2Ftwistedmatrix.com%2Fxml_namespace%2Fdav%2Fprivate%2F}quota-used", zlib.compress(xml))
</span><span class="lines">@@ -280,9 +279,10 @@
</span><span class="cx"> print("")
</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("Failed to parse (%s): %s" % (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("urn:uuid:%s" % (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("Fetching records from directory: %s" % (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(" %s..." % (internalType,))
</span><span class="cx"> child = Popen(
</span><del>- args = [
</del><ins>+ args=[
</ins><span class="cx"> "/usr/bin/dscl", "-plist", node, "-readall",
</span><span class="cx"> "/%s" % (recordType,),
</span><span class="cx"> "GeneratedUID", "RecordName", "EMailAddress", "GroupMembers"
</span><span class="lines">@@ -405,6 +406,7 @@
</span><span class="cx"> print("Done.")
</span><span class="cx"> print("")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def addRecord(self, internalType="users", 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(" Principals not found in directory: %d" % (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"> """
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class DatabaseError(Exception):
</span><span class="cx"> """
</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"> """
</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 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
</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 "".join(l)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> if __name__ == "__main__":
</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"> "Start" : pyCalendarTodatetime(start),
</span><del>- "Max" : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0))
</del><ins>+ "Max" : 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"> "Start" : pyCalendarTodatetime(start),
</span><del>- "Max" : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
</del><ins>+ "Max" : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
</ins><span class="cx"> "UUID" : 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"> "Start" : pyCalendarTodatetime(start),
</span><del>- "Max" : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
</del><ins>+ "Max" : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
</ins><span class="cx"> "UUID" : 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("\r\n ", "")
</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 = "No fix bad CALENDARSERVER-OLD-CUA"
</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("\n---- Scanning calendar data ----\n")
</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["fix"]
</span><span class="cx">
</span><del>- self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
</del><ins>+ self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
</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("\n---- Scanning calendar data ----\n")
</span><span class="cx">
</span><del>- self.now = PyCalendarDateTime.getNowUTC()
- self.start = self.options["start"] if "start" in self.options else PyCalendarDateTime.getToday()
</del><ins>+ self.now = DateTime.getNowUTC()
+ self.start = self.options["start"] if "start" 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["fix"]
</span><span class="cx">
</span><del>- self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
</del><ins>+ self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
</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"> """
</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"> """
</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 = "CANCELLED"
</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("\n---- Scanning calendar data ----\n")
</span><span class="cx">
</span><del>- self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
- self.now = PyCalendarDateTime.getNowUTC()
- self.start = PyCalendarDateTime.getToday()
</del><ins>+ self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+ 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("DTSTART")
</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("SUMMARY")))
</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("\n---- Scanning calendar data ----\n")
</span><span class="cx">
</span><del>- self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
- self.now = PyCalendarDateTime.getNowUTC()
- self.start = self.options["start"] if "start" in self.options else PyCalendarDateTime.getToday()
</del><ins>+ self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+ self.now = DateTime.getNowUTC()
+ self.start = self.options["start"] if "start" 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["fix"]
</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 += "T000000Z"
</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("Invalid start value")
</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("Invalid end value")
</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, ["resources"])
</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, ["locations", "resources"])
</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"> """
</span><span class="cx"> retainDays = command.get("RetainDays", 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, "RetainDays" : 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("Converting data (version: %s) at: %s" % (tzvers, zonedir,))
</span><span class="cx"> startYear = 1800
</span><del>- endYear = PyCalendarDateTime.getToday().getYear() + 10
- PyCalendar.sProdID = "-//calendarserver.org//Zonal//EN"
</del><ins>+ endYear = DateTime.getToday().getYear() + 10
+ Calendar.sProdID = "-//calendarserver.org//Zonal//EN"
</ins><span class="cx"> zonefiles = "northamerica", "southamerica", "europe", "africa", "asia", "australasia", "antarctica", "etcetera", "backward"
</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 > 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 > 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="calendar2", home=self.uuid3))
</span><del>- yield home.setDefaultCalendar(calendar)
</del><ins>+ yield home.setDefaultCalendar(calendar, "VEVENT")
</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"> "uid": "",
</span><span class="cx"> "uuid": "",
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": "",
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": "",
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": "",
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": CalVerifyMismatchTestsBase.uuidl1,
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": CalVerifyMismatchTestsBase.uuidl1,
</span><span class="cx"> "tzid": "",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": self.uuidl1,
</span><span class="cx"> "tzid": "utc",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": 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"> "uid": "",
</span><span class="cx"> "uuid": self.uuidl1,
</span><span class="cx"> "tzid": "utc",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx"> "no-organizer": False,
</span><span class="cx"> "invalid-organizer": False,
</span><span class="cx"> "disabled-organizer": False,
</span><span class="lines">@@ -2656,7 +2656,7 @@
</span><span class="cx"> "uid": "",
</span><span class="cx"> "uuid": self.uuidl1,
</span><span class="cx"> "tzid": "utc",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx"> "no-organizer": False,
</span><span class="cx"> "invalid-organizer": False,
</span><span class="cx"> "disabled-organizer": False,
</span><span class="lines">@@ -2715,7 +2715,7 @@
</span><span class="cx"> "uid": "",
</span><span class="cx"> "uuid": self.uuidl1,
</span><span class="cx"> "tzid": "utc",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx"> "no-organizer": True,
</span><span class="cx"> "invalid-organizer": False,
</span><span class="cx"> "disabled-organizer": False,
</span><span class="lines">@@ -2774,7 +2774,7 @@
</span><span class="cx"> "uid": "",
</span><span class="cx"> "uuid": self.uuidl1,
</span><span class="cx"> "tzid": "utc",
</span><del>- "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
</del><ins>+ "start": DateTime(nowYear, 1, 1, 0, 0, 0),
</ins><span class="cx"> "no-organizer": True,
</span><span class="cx"> "invalid-organizer": True,
</span><span class="cx"> "disabled-organizer": 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"> "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
</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"> "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
</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"> "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
</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"> "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
</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"> "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
</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"> "urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66")
</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"> "urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66")
</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 = """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, ("home1",), 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("Availability request spanning multiple days (%r to %r), "
</span><span class="cx"> "dropping the end date." % (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 = "small"
</span><span class="cx"> if len(users) > 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"> """
</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("CREATED", PyCalendarDateTime.getNowUTC()))
- vevent.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+ vevent.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
</ins><span class="cx"> vevent.replaceProperty(Property("DTSTART", dtstart))
</span><span class="cx"> vevent.replaceProperty(Property("DTEND", dtend))
</span><span class="cx"> vevent.replaceProperty(Property("UID", 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("CREATED", PyCalendarDateTime.getNowUTC()))
- vevent.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+ vevent.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
</ins><span class="cx"> vevent.replaceProperty(Property("DTSTART", dtstart))
</span><span class="cx"> vevent.replaceProperty(Property("DTEND", dtend))
</span><span class="cx"> vevent.replaceProperty(Property("UID", 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("CREATED", PyCalendarDateTime.getNowUTC()))
- vtodo.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ vtodo.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+ vtodo.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
</ins><span class="cx"> vtodo.replaceProperty(Property("DUE", due))
</span><span class="cx"> vtodo.replaceProperty(Property("UID", 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 = "/calendars/__uids__/%s/outbox/" % (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"urn:uuid:user05", u"urn:uuid:user10"])
</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"> """
</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, "organizer.ics")
</span><span class="cx"> self.sessions[1].writeData(URL(path=href), ICAL % (now.getYear() + 1,), "text/calendar")
</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 = """BEGIN:VCALENDAR
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx"> Execute the actual HTTP request.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- now = PyCalendarDateTime.getNowUTC()
</del><ins>+ now = DateTime.getNowUTC()
</ins><span class="cx"> href = joinURL(self.sessions[0].calendarHref, "put.ics")
</span><span class="cx"> self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1,), "text/calendar")
</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"> """
</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 = """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, "sync-collection-%d.ics" % (i + 1,))
</span><span class="cx"> self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1, i + 1,), "text/calendar")
</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"> """
</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, "%d.ics" % (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 > 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 = "US/Eastern"
</span><span class="cx"> dist = WorkDistribution(["mon", "wed", "thu", "sat"], 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(["mon", "tue", "wed", "thu", "fri"], 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=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
</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("Path does not exist: '%s'. Ignoring." % (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"> "${pypi}/p/${n}/${p}.tar.gz";
</span><span class="cx">
</span><span class="cx"> # XXX actually PyCalendar should be imported in-place.
</span><del>- py_dependency -fe -i "src" -r 11458 \
</del><ins>+ py_dependency -fe -i "src" -r 11914 \
</ins><span class="cx"> "PyCalendar" "pycalendar" "pycalendar" \
</span><span class="cx"> "${svn_uri_base}/PyCalendar/trunk";
</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"> """
</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"> """
</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"> """
</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"> """
</span><span class="cx">
</span><del>-
</del><span class="cx"> def callFromThread(self, thunk, *a, **kw):
</span><span class="cx"> """
</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"> """
</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"> """
</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->controller->controller->worker.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def performWork(table, workID):
</del><ins>+ def performWork(table, workID): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>-
</del><span class="cx"> @classmethod
</span><span class="cx"> def forTable(cls, table):
</span><span class="cx"> """
</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"> """
</span><span class="cx"> Keep relaying data until there's no more.
</span><span class="cx"> """
</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, "bar"))
</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("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
</del><ins>+Calendar.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
+Card.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
</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("X-CALENDARSERVER-PRIVATE-COMMENT", PyCalendarValue.VALUETYPE_TEXT)
-PyCalendarProperty.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", PyCalendarValue.VALUETYPE_TEXT)
</del><ins>+Property.registerDefaultValue("X-CALENDARSERVER-PRIVATE-COMMENT", Value.VALUETYPE_TEXT)
+Property.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", 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"> """
</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"> """
</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"> """
</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>- """
</del><ins>+ """
</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 = "%s-01" % (logFilename,)
</span><span class="lines">@@ -128,7 +134,7 @@
</span><span class="cx"> log.error("Too many %s accounting files for %s" % (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"> """
</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"> """
</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("Invalid Kerberos principal: %s" % (principal,))
</span><span class="cx"> raise ValueError('Authentication System Failure: Invalid Kerberos principal: %s' % (principal,))
</span><del>-
</del><ins>+
</ins><span class="cx"> service = "%s@%s" % (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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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("Bad credentials for: %s" % (pcreds.authnURI,))
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class NegotiateCredentials(object):
</span><span class="cx"> """
</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"> """
</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"> """
</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 "http" instead of "HTTP"
</span><span class="cx"> try:
</span><del>- _ignore_result, context = kerberos.authGSSServerInit("");
</del><ins>+ _ignore_result, context = kerberos.authGSSServerInit("")
</ins><span class="cx"> except kerberos.GSSError, ex:
</span><span class="cx"> self.log.error("authGSSServerInit: %s(%s)" % (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("authGSSServerStep: %s(%s)" % (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 = ""
</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("@") != -1:
</span><span class="cx"> splits = username.split("@", 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("authGSSServerClean: %s" % (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("Bad credentials for: %s" % (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("DEBUG:", 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("FUNCLOG:", 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("%s(%s)" % (func.func_name,
</del><ins>+ funclog("%s(%s)" % (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("%s - > %s" % (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"> """
</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 "start" not in attributes and "end" not in attributes:
</span><span class="cx"> raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
</span><span class="cx">
</span><del>- self.start = PyCalendarDateTime.parseText(attributes["start"]) if "start" in attributes else None
- self.end = PyCalendarDateTime.parseText(attributes["end"]) if "end" in attributes else None
</del><ins>+ self.start = DateTime.parseText(attributes["start"]) if "start" in attributes else None
+ self.end = DateTime.parseText(attributes["end"]) if "end" 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"> """
</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"> """
</span><ins>+
+ def __init__(self, *children, **attributes):
+
+ if "content-type" in attributes:
+ self.content_type = attributes["content-type"]
+ else:
+ self.content_type = "text/calendar"
+
+ if "version" in attributes:
+ self.version = attributes["version"]
+ else:
+ self.version = "2.0"
+
+ super(CalDAVDataMixin, self).__init__(*children, **attributes)
+
+
+ def verifyTypeVersion(self):
+ """
+ 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.
+ """
+ allowedTypes = set()
+ allowedTypes.add(("text/calendar", "2.0",))
+ if config.EnableJSONData:
+ allowedTypes.add(("application/calendar+json", "2.0",))
+ 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 != "text/calendar":
+ attrs["content-type"] = format
+
+ if isinstance(calendar, str):
+ if not calendar:
+ raise ValueError("Missing calendar data")
+ return clazz(PCDATAElement(calendar), **attrs)
+ elif isinstance(calendar, iComponent):
+ assert calendar.name() == "VCALENDAR", "Not a calendar: %r" % (calendar,)
+ return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference, format=format)), **attrs)
+ else:
+ raise ValueError("Not a calendar: %s" % (calendar,))
+
+ fromTextData = fromCalendar
+ fromComponent = fromCalendar
+
</ins><span class="cx"> def calendar(self):
</span><span class="cx"> """
</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"> """
</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):
+ """
+ Returns the calendar data derived from this element.
+ """
+ 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):
+ """
+ CalDAV element containing iCalendar data with a single VTIMEZONE component.
+ """
+
</ins><span class="cx"> def gettimezone(self):
</span><span class="cx"> """
</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"> """
</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 = "calendar-timezone"
</span><span class="cx"> hidden = True
</span><span class="cx">
</span><ins>+ allowed_attributes = {
+ "content-type": False,
+ "version" : 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"> """
</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"> """
</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"> "version" : 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("Missing calendar data")
- return clazz(PCDATAElement(calendar))
- elif isinstance(calendar, iComponent):
- assert calendar.name() == "VCALENDAR", "Not a calendar: %r" % (calendar,)
- return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference)))
- else:
- raise ValueError("Not a calendar: %s" % (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 "content-type" in attributes:
- self.content_type = attributes["content-type"]
- else:
- self.content_type = "text/calendar"
</del><span class="cx">
</span><del>- if "version" in attributes:
- self.version = attributes["version"]
- else:
- self.version = "2.0"
</del><span class="cx">
</span><del>-
- def verifyTypeVersion(self, types_and_versions):
- """
- 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.
- """
- for item in types_and_versions:
- if (item[0] == self.content_type) and (item[1] == self.version):
- return True
-
- return False
-
-
- def calendar(self):
- """
- Returns a calendar component derived from this element.
- """
- data = self.calendarData()
- if data:
- return iComponent.fromString(data)
- else:
- return None
-
- generateComponent = calendar
-
-
- def calendarData(self):
- """
- Returns the calendar data derived from this element.
- """
- 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"> """
</span><span class="lines">@@ -882,8 +898,13 @@
</span><span class="cx"> """
</span><span class="cx"> name = "timezone"
</span><span class="cx">
</span><ins>+ allowed_attributes = {
+ "content-type": False,
+ "version" : 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"> """
</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"> """
</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"> """
</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"> """
</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):
+ """
+ A mixin to support accept/returning data in various formats.
+ """
+
+ def __init__(self, *children, **attributes):
+
+ if "content-type" in attributes:
+ self.content_type = attributes["content-type"]
+ else:
+ self.content_type = "text/vcard"
+
+ if "version" in attributes:
+ self.version = attributes["version"]
+ else:
+ self.version = "3.0"
+
+ super(CardDAVDataMixin, self).__init__(*children, **attributes)
+
+
+ def verifyTypeVersion(self):
+ """
+ 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.
+ """
+ allowedTypes = set()
+ allowedTypes.add(("text/vcard", "3.0",))
+ if config.EnableJSONData:
+ allowedTypes.add(("application/vcard+json", "3.0",))
+ 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 != "text/vcard":
+ attrs["content-type"] = format
+
+ if isinstance(address, str):
+ if not address:
+ raise ValueError("Missing address data")
+ return clazz(PCDATAElement(address), **attrs)
+ elif isinstance(address, Component):
+ assert address.name() == "VCARD", "Not a vCard: %r" % (address,)
+ return clazz(PCDATAElement(address.getText(format)), **attrs)
+ else:
+ raise ValueError("Not an address: %s" % (address,))
+
+ fromTextData = fromAddress
+ fromComponent = fromAddress
+
+ def address(self):
+ """
+ Returns an address component derived from this element.
+ """
+ data = self.addressData()
+ if data:
+ return Component.fromString(data, format=self.content_type)
+ else:
+ return None
+
+ generateComponent = address
+
+
+ def addressData(self):
+ """
+ Returns the address data derived from this element.
+ """
+ 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"> """
</span><span class="lines">@@ -73,9 +163,10 @@
</span><span class="cx"> name = "addressbook-home-set"
</span><span class="cx"> hidden = True
</span><span class="cx">
</span><del>- allowed_children = { (dav_namespace, "href"): (0, None) }
</del><ins>+ allowed_children = {(dav_namespace, "href"): (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"> """
</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"> """
</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, "address-data-type"): (0, None) }
</del><ins>+ allowed_children = {(carddav_namespace, "address-data-type"): (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"> """
</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"> """
</span><span class="lines">@@ -121,6 +215,7 @@
</span><span class="cx"> name = "addressbook"
</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"> """
</span><span class="lines">@@ -130,11 +225,11 @@
</span><span class="cx"> name = "addressbook-query"
</span><span class="cx">
</span><span class="cx"> allowed_children = {
</span><del>- (dav_namespace, "allprop" ): (0, None),
- (dav_namespace, "propname"): (0, None),
- (dav_namespace, "prop" ): (0, None),
- (carddav_namespace, "filter" ): (0, 1), # Actually (1, 1) unless element is empty
- (carddav_namespace, "limit" ): (0, None),
</del><ins>+ (dav_namespace, "allprop"): (0, None),
+ (dav_namespace, "propname"): (0, None),
+ (dav_namespace, "prop"): (0, None),
+ (carddav_namespace, "filter"): (0, 1), # Actually (1, 1) unless element is empty
+ (carddav_namespace, "limit"): (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, "allprop" ),
</del><ins>+ (dav_namespace, "allprop"),
</ins><span class="cx"> (dav_namespace, "propname"),
</span><del>- (dav_namespace, "prop" ),
</del><ins>+ (dav_namespace, "prop"),
</ins><span class="cx"> ):
</span><span class="cx"> if props is not None:
</span><span class="cx"> raise ValueError("Only one of CardDAV:allprop, CardDAV:propname, CardDAV:prop allowed")
</span><span class="lines">@@ -159,7 +254,7 @@
</span><span class="cx"> elif qname == (carddav_namespace, "filter"):
</span><span class="cx"> filter = child
</span><span class="cx"> elif qname == (carddav_namespace, "limit"):
</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("CARDDAV:filter required")
</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"> """
</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"> """
</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, "allprop"): (0, 1),
</span><del>- (carddav_namespace, "prop" ): (0, None),
</del><ins>+ (carddav_namespace, "prop"): (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"> "version" : False,
</span><span class="cx"> }
</span><span class="cx">
</span><del>- @classmethod
- def fromAddress(clazz, address):
- assert address.name() == "VCARD", "Not a vCard: %r" % (address,)
- return clazz(PCDATAElement(str(address)))
-
- @classmethod
- def fromAddressData(clazz, addressdata):
- """
- Return a AddressData element comprised of the supplied address data.
- @param addressdata: a string of valid address data.
- @return: a L{Addressata} element.
- """
- 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("We shouldn't be here")
</del><ins>+ else:
+ raise AssertionError("We shouldn't be here")
</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("Only one of allprop, prop (%r) or PCDATA (%r) allowed"% (properties, str(data)))
</del><ins>+ raise ValueError("Only one of allprop, prop (%r) or PCDATA (%r) allowed" % (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 "content-type" in attributes:
- self.content_type = attributes["content-type"]
- else:
- self.content_type = "text/vcard"
</del><span class="cx">
</span><del>- if "version" in attributes:
- self.version = attributes["version"]
- else:
- self.version = "3.0"
</del><span class="cx">
</span><del>- def verifyTypeVersion(self, types_and_versions):
- """
- 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.
- """
- for item in types_and_versions:
- if (item[0] == self.content_type) and (item[1] == self.version):
- return True
-
- return False
-
- def address(self):
- """
- Returns an address component derived from this element.
- """
- data = self.addressData()
- if data:
- return Component.fromString(data)
- else:
- return None
-
- generateComponent = address
-
- def addressData(self):
- """
- Returns an address component derived from this element.
- """
- 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"> """
</span><span class="lines">@@ -332,6 +365,7 @@
</span><span class="cx"> name = "allprop"
</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"> """
</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"> """
</span><span class="lines">@@ -370,10 +405,11 @@
</span><span class="cx"> """
</span><span class="cx"> name = "filter"
</span><span class="cx">
</span><del>- allowed_children = { (carddav_namespace, "prop-filter"): (0, None) }
- allowed_attributes = { "test": False }
-
</del><ins>+ allowed_children = {(carddav_namespace, "prop-filter"): (0, None)}
+ allowed_attributes = {"test": False}
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class PropertyFilter (CardDAVElement):
</span><span class="cx"> """
</span><span class="lines">@@ -383,9 +419,9 @@
</span><span class="cx"> name = "prop-filter"
</span><span class="cx">
</span><span class="cx"> allowed_children = {
</span><del>- (carddav_namespace, "is-not-defined" ): (0, 1),
- (carddav_namespace, "text-match" ): (0, None),
- (carddav_namespace, "param-filter" ): (0, None),
</del><ins>+ (carddav_namespace, "is-not-defined"): (0, 1),
+ (carddav_namespace, "text-match"): (0, None),
+ (carddav_namespace, "param-filter"): (0, None),
</ins><span class="cx"> }
</span><span class="cx"> allowed_attributes = {
</span><span class="cx"> "name": 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"> """
</span><span class="lines">@@ -402,12 +439,13 @@
</span><span class="cx"> name = "param-filter"
</span><span class="cx">
</span><span class="cx"> allowed_children = {
</span><del>- (carddav_namespace, "is-not-defined" ): (0, 1),
- (carddav_namespace, "text-match" ): (0, 1),
</del><ins>+ (carddav_namespace, "is-not-defined"): (0, 1),
+ (carddav_namespace, "text-match"): (0, 1),
</ins><span class="cx"> }
</span><del>- allowed_attributes = { "name": True }
</del><ins>+ allowed_attributes = {"name": 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"> """
</span><span class="lines">@@ -416,10 +454,11 @@
</span><span class="cx"> namespace = carddav_namespace
</span><span class="cx"> name = "limit"
</span><span class="cx"> allowed_children = {
</span><del>- (carddav_namespace, "nresults" ) : (1, 1),
</del><ins>+ (carddav_namespace, "nresults") : (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"> """
</span><span class="lines">@@ -439,6 +478,7 @@
</span><span class="cx"> name = "is-not-defined"
</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"> """
</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"> """
</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, "allprop" ): (0, 1),
</del><ins>+ (dav_namespace, "allprop"): (0, 1),
</ins><span class="cx"> (dav_namespace, "propname"): (0, 1),
</span><del>- (dav_namespace, "prop" ): (0, 1),
- (dav_namespace, "href" ): (0, None), # Actually ought to be (1, None)
</del><ins>+ (dav_namespace, "prop"): (0, 1),
+ (dav_namespace, "href"): (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, "allprop" ),
</del><ins>+ (dav_namespace, "allprop"),
</ins><span class="cx"> (dav_namespace, "propname"),
</span><del>- (dav_namespace, "prop" ),
</del><ins>+ (dav_namespace, "prop"),
</ins><span class="cx"> ):
</span><span class="cx"> if property is not None:
</span><span class="cx"> raise ValueError("Only one of DAV:allprop, DAV:propname, DAV:prop allowed")
</span><span class="lines">@@ -502,10 +543,11 @@
</span><span class="cx"> elif qname == (dav_namespace, "href"):
</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"> """
</span><span class="lines">@@ -514,9 +556,10 @@
</span><span class="cx"> """
</span><span class="cx"> name = "no-uid-conflict"
</span><span class="cx">
</span><del>- allowed_children = { (dav_namespace, "href"): (1, 1) }
-
</del><ins>+ allowed_children = {(dav_namespace, "href"): (1, 1)}
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class SupportedFilter(CardDAVElement):
</span><span class="cx"> """
</span><span class="lines">@@ -527,11 +570,12 @@
</span><span class="cx"> name = "supported-filter"
</span><span class="cx">
</span><span class="cx"> allowed_children = {
</span><del>- (carddav_namespace, "prop-filter" ): (0, None),
</del><ins>+ (carddav_namespace, "prop-filter"): (0, None),
</ins><span class="cx"> (carddav_namespace, "param-filter"): (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"> """
</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, "href"): (0, None) }
-
</del><ins>+ allowed_children = {(dav_namespace, "href"): (0, None)}
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class Directory(CardDAVEmptyElement):
</span><span class="cx"> """
</span><span class="cx"> CardDAV property on a principal to indicate where the directory resource is.
</span><span class="cx"> """
</span><span class="cx"> name = "directory"
</span><del>-
</del><span class="cx">
</span><ins>+
+
</ins><span class="cx"> @registerElement
</span><span class="cx"> class DefaultAddressBookURL (CardDAVElement):
</span><span class="cx"> """
</span><span class="lines">@@ -559,14 +605,17 @@
</span><span class="cx"> """
</span><span class="cx"> name = "default-addressbook-URL"
</span><span class="cx">
</span><del>- allowed_children = { (dav_namespace, "href"): (0, 1) }
</del><ins>+ allowed_children = {(dav_namespace, "href"): (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 = "http://calendarserver.org/ns/"
</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"> """
</span><span class="cx"> A ThreadPool that closes connections for each worker thread
</span><span class="cx"> """
</span><del>-
</del><ins>+
</ins><span class="cx"> def _worker(self):
</span><span class="cx"> log.debug("Starting ADBAPI thread: %s" % (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("Closing ADBAPI thread: %s" % (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"> """
</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"> """
</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 "<%s %r>" % (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"> """
</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("Database %s has different schema (v.%s vs. v.%s)"
</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"> """
</span><span class="cx"> @return: the schema version assigned to this DB.
</span><span class="cx"> """
</span><span class="cx"> raise NotImplementedError
</span><del>-
</del><ins>+
+
</ins><span class="cx"> def _db_type(self):
</span><span class="cx"> """
</span><span class="cx"> @return: the collection type assigned to this DB.
</span><span class="cx"> """
</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("CALDAV")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _db_init(self):
</span><span class="cx"> """
</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"> """
</span><span class="lines">@@ -310,12 +326,14 @@
</span><span class="cx"> """, (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"> """
</span><span class="cx"> Initialise the underlying database tables.
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</span><span class="cx"> Upgrade the database tables.
</span><span class="cx"> """
</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"> """
</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"> """
</span><span class="cx"> Remove all the data from an older version of the DB.
</span><span class="cx"> """
</span><span class="cx"> raise NotImplementedError("Each database must remove its own tables.")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _db_remove_schema(self):
</span><span class="cx"> """
</span><span class="lines">@@ -385,6 +408,7 @@
</span><span class="cx"> """
</span><span class="cx"> yield self._db_execute("drop table if exists CALDAV")
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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 "abstract" 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 " unique" modifier can be appended to any of those.
</span><span class="cx"> """
</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 = ""
</span><span class="cx"> splits = coltype.split()
</span><span class="cx"> if splits[0] == "integer":
</span><span class="lines">@@ -493,15 +526,16 @@
</span><span class="cx"> result = "date"
</span><span class="cx"> elif splits[0] == "serial":
</span><span class="cx"> result = "integer primary key autoincrement"
</span><del>-
</del><ins>+
</ins><span class="cx"> if len(splits) > 1 and splits[1] == "unique":
</span><span class="cx"> result += " unique"
</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 = ["%s %s" % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
</span><span class="cx"> statement = "create table %s%s (%s)" % (
</span><span class="cx"> "if not exists " if ifnotexists else "",
</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("""
</span><span class="lines">@@ -518,9 +553,10 @@
</span><span class="cx"> """ % (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 = "create index %s%s on %s (%s)" % (
</span><span class="cx"> "if not exists " if ifnotexists else "",
</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 = ""
</span><span class="cx"> splits = coltype.split()
</span><span class="cx"> if splits[0] == "integer":
</span><span class="lines">@@ -553,32 +590,34 @@
</span><span class="cx"> result = "date"
</span><span class="cx"> elif splits[0] == "serial":
</span><span class="cx"> result = "serial"
</span><del>-
</del><ins>+
</ins><span class="cx"> if len(splits) > 1 and splits[1] == "unique":
</span><span class="cx"> result += " unique"
</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 = ["%s %s" % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
</span><span class="cx"> statement = "create table %s (%s)" % (
</span><span class="cx"> name,
</span><span class="cx"> ", ".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("""
</span><span class="lines">@@ -586,27 +625,29 @@
</span><span class="cx"> where tablename = '%s'
</span><span class="cx"> """ % (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 = "create index %s on %s (%s)" % (
</span><span class="cx"> name,
</span><span class="cx"> ontable,
</span><span class="cx"> ", ".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"> """
</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"> """
</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"> ("KEY", "text unique"),
</span><span class="cx"> ("VALUE", "text unique"),
</span><span class="cx"> ), True)
</span><del>-
</del><ins>+
</ins><span class="cx"> yield self._db_execute(
</span><span class="cx"> """
</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("PostgreSQL module not available.")
</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"> "CalendarDataFilter",
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx"> for property in component.properties("FREEBUSY"):
</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"> "clipPeriod"
</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"> """
</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"> """
</span><del>- if not isinstance(dt, PyCalendarDateTime):
- raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-
</del><ins>+ if not isinstance(dt, DateTime):
+ raise TypeError("%r is not a DateTime instance" % (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"> """
</span><del>- Normalize a L{PyCalendarDateTime} object to UTC.
</del><ins>+ Normalize a L{DateTime} object to UTC.
</ins><span class="cx"> """
</span><del>- if not isinstance(dt, PyCalendarDateTime):
- raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-
</del><ins>+ if not isinstance(dt, DateTime):
+ raise TypeError("%r is not a DateTime instance" % (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"> """
</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"> """
</span><del>- if not isinstance(dt, PyCalendarDateTime):
- raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-
</del><ins>+ if not isinstance(dt, DateTime):
+ raise TypeError("%r is not a DateTime instance" % (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"> """
</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"> """
</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"> """
</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"> """
</span><del>-
</del><ins>+
</ins><span class="cx"> # First sort the list
</span><span class="cx"> def sortPeriods(p1, p2):
</span><span class="cx"> """
</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>p2, 0 if p1==p2, -1 if p1<p2
</span><span class="cx"> """
</span><span class="cx">
</span><del>- assert isinstance(p1, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p1,)
- assert isinstance(p2, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p2,)
-
-
</del><ins>+ assert isinstance(p1, Period), "Period is not a Period: %r" % (p1,)
+ assert isinstance(p2, Period), "Period is not a Period: %r" % (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 >= periods[i].getStart()):
</span><span class="cx"> if ie > 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"> """
</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 < clipStart:
</span><span class="cx"> start = clipStart
</span><del>-
</del><ins>+
</ins><span class="cx"> if end > clipEnd:
</span><span class="cx"> end = clipEnd
</span><del>-
</del><ins>+
</ins><span class="cx"> if start >= 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"> """
</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"> """
</span><del>-
</del><ins>+
</ins><span class="cx"> # Format is "%Y-%m-%d %H:%M:%S"
</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"> """
</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"> """
</span><del>-
</del><ins>+
</ins><span class="cx"> # Format is "%Y-%m-%d", 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("httpd", "unix-directory")
</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"> """
</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"> """
</span><span class="cx"> def __init__(self, directory, url, store):
</span><span class="cx"> """
</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 "addressbooks"
</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"> """
</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("BDAY", PyCalendarDateTime.parseText(birthdate, fullISO=True)))
</del><ins>+ vcard.addProperty(Property("BDAY", 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("REV", PyCalendarDateTime.parseText(revDate, fullISO=True)))
</del><ins>+ vcard.addProperty(Property("REV", DateTime.parseText(revDate, fullISO=True)))
</ins><span class="cx">
</span><span class="cx"> """
</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"> """
</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"> """
</span><span class="cx"> setRealm gets propagated to nested services
</span><span class="lines">@@ -82,4 +84,3 @@
</span><span class="cx"> aggregatedService.setRealm("foo.example.com")
</span><span class="cx"> for service in aggregatedService._recordTypes.values():
</span><span class="cx"> self.assertEquals("foo.example.com", 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("guid"),
- shortNames = record.get("shortname"),
- authIDs = record.get("authid"),
- fullName = record.get("fullName"),
- firstName = "",
- lastName = "",
- emailAddresses = record.get("email"),
- )
-
</del><ins>+ service=self,
+ recordType=recordType,
+ guid=record.get("guid"),
+ shortNames=record.get("shortname"),
+ authIDs=record.get("authid"),
+ fullName=record.get("fullName"),
+ firstName="",
+ lastName="",
+ emailAddresses=record.get("email"),
+ )
+
</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 = ("%s@example.com" % (shortNames[0],),)
</span><del>-
</del><ins>+
</ins><span class="cx"> attrs = {
</span><span class="cx"> "fullName": fullName,
</span><span class="cx"> "guid": guid,
</span><span class="lines">@@ -126,35 +132,38 @@
</span><span class="cx"> "cua": tuple(["mailto:%s" % email for email in emails]),
</span><span class="cx"> "authid": tuple(["Kerberos:%s" % email for email in emails])
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> if members:
</span><span class="cx"> attrs["members"] = members
</span><del>-
</del><ins>+
</ins><span class="cx"> if resourceInfo:
</span><span class="cx"> attrs["resourceInfo"] = 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(" ", "")
</span><del>-
</del><ins>+
+
</ins><span class="cx"> def guidForShortName(self, shortName, recordType=""):
</span><span class="cx"> return uuidFromName(self.baseGUID, "%s%s" % (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("User %02d" % x, DirectoryService.recordType_users, multinames=(x>5)) for x in range(1,SIZE+1)
</del><ins>+ self.fakeRecord("User %02d" % x, DirectoryService.recordType_users, multinames=(x > 5)) for x in range(1, SIZE + 1)
</ins><span class="cx"> ],
</span><span class="cx"> DirectoryService.recordType_groups: [
</span><del>- self.fakeRecord("Group %02d" % x, DirectoryService.recordType_groups) for x in range(1,SIZE+1)
</del><ins>+ self.fakeRecord("Group %02d" % 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("Resource %02d" % x, DirectoryService.recordType_resources) for x in range(1,SIZE+1)
</del><ins>+ self.fakeRecord("Resource %02d" % 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("Location %02d" % x, DirectoryService.recordType_locations) for x in range(1,SIZE+1)
</del><ins>+ self.fakeRecord("Location %02d" % 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("user01", 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("missing")), 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("missing")), 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"> """
</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"> "Duplicate")
</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"> """
</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 = "29fc54aa1641c6fa0e151419361c8f23"
</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"> """
</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"> """
</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"> """
</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("nonce"))
</del><ins>+ self.assertTrue("nonce" 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("nonce"))
</del><ins>+ self.assertTrue("nonce" 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"> """
</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, "00000001"),
</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"> """
</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, "00000001"),
</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, "00000002"),
</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"> """
</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, "00000001"),
</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"> """
</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), "Invalid response, no username given.")
</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), "Invalid response, no username given.")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def test_noNonce(self):
</span><span class="cx"> """
</span><span class="lines">@@ -308,6 +317,7 @@
</span><span class="cx"> _trivial_GET()))
</span><span class="cx"> self.assertEquals(str(e), "Invalid response, no nonce given.")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def test_emptyAttribute(self):
</span><span class="cx"> """
</span><span class="lines">@@ -323,6 +333,7 @@
</span><span class="cx"> _trivial_GET()))
</span><span class="cx"> self.assertEquals(str(e), "Invalid response, no username given.")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def test_checkHash(self):
</span><span class="cx"> """
</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, "00000001"),
</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"> """
</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, "00000001"),
</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, "00000002"),
</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"> """
</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'] = "noNoncense"
</span><del>-
</del><ins>+
</ins><span class="cx"> clientResponse = authRequest1[ctr] % (
</span><span class="cx"> challenge['nonce'],
</span><span class="cx"> self.getDigestResponse(challenge, "00000001"),
</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>- {"Digest":factory},
</del><ins>+ {"Digest": factory},
</ins><span class="cx"> request.remoteAddr
</span><span class="cx"> ))
</span><span class="cx"> response.headers.getHeader("www-authenticate")[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"> """
</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, "00000001"),
</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>- {"Digest":factory},
</del><ins>+ {"Digest": factory},
</ins><span class="cx"> request.remoteAddr,
</span><span class="cx"> ))
</span><span class="cx"> wwwhdrs = response.headers.getHeader("www-authenticate")[0][1]
</span><span class="cx"> self.assertTrue('stale' in wwwhdrs, msg="No stale parameter in Digest WWW-Authenticate headers: %s" % (wwwhdrs,))
</span><span class="cx"> self.assertEquals(wwwhdrs['stale'], 'true', msg="stale parameter not set to true in Digest WWW-Authenticate headers: %s" % (wwwhdrs,))
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def test_incompatibleCalcHA1Options(self):
</span><span class="cx"> """
</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"> """
</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, "00000001"),
</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"> """
</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, "time", newtime())
</del><ins>+ from twistedcaldav.directory import digest as ddigest
+ self.patch(ddigest, "time", 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, "00000001"),
</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("Invalid exception from nonce timeout: %s" % e)
</span><span class="cx"> challenge = (yield factory.getChallenge(request.remoteAddr))
</span><span class="cx"> self.assertTrue(challenge.get("stale") == "true")
</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"> """
</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"> # "Corrupt" the snapshot and verify it is regenerated properly
</span><span class="cx"> snapshotFile.setContent("xyzzy")
</span><span class="cx"> cache.delete("group-cacher-populated")
</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"> """
</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"> """
</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 = "Fix WorkProposal to track delayed calls and cancel them"
</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 = "38D8AC00-5490-4425-BE3A-05FFB9862444"
</span><span class="cx">
</span><span class="cx"> homeResource = "/calendars/users/cdaboo/"
</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("/principals/__uids__/" + newUID + "/"), 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("/principals/__uids__/" + oldUID + "/"), 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("users", "odtestcarlene")
</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, "augments.xml")
</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("location01")
</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("location01")
</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("location01")
</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("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
</span><span class="cx"> self.assertRaises(DirectoryError, directory.createRecord, "resources", guid="resource01", shortNames=("resource01",), uid="resource01")
</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], "resource01")
</span><span class="cx"> self.assertEquals(record.fullName, "Resource #1")
</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("TEL")])
</span><span class="lines">@@ -30,6 +43,7 @@
</span><span class="cx"> self.assertEquals(properties, set(["amanda@example.com", "second@example.com"]))
</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"> """
</span><span class="cx"> Directory service provisioned principals.
</span><span class="cx"> """
</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"> """
</span><span class="cx"> @return: the schema version assigned to this index.
</span><span class="cx"> """
</span><span class="cx"> return "3"
</span><del>-
</del><ins>+
</ins><span class="cx"> def _db_init_data_tables(self):
</span><span class="cx"> """
</span><span class="cx"> Initialise the underlying database tables.
</span><span class="cx"> @param q: a database cursor to use.
</span><span class="cx"> """
</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"> """
</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"> """
</span><span class="cx"> @return: the schema version assigned to this index.
</span><span class="cx"> """
</span><span class="cx"> return "11"
</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"> """
</span><span class="cx"> @return: the schema version assigned to this index.
</span><span class="cx"> """
</span><span class="cx"> return "51"
</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("A", ("B", "C", "D",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</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 = "Test \xe4\xbd\x90\xe8\x97\xa4"
</span><span class="cx"> yield db.setGroupMembers(principalID, ("B", "C", "D",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers(principalID)
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</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("PRAGMA index_list(GROUPS)"))]), set(("GROUPNAMES", "MEMBERS")))
</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("PRAGMA index_list(GROUPS)"))]), 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("PRAGMA index_list(GROUPS)"))]), 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("A")
</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("PRAGMA index_list(GROUPS)"))]), 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("A")
</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("PRAGMA index_list(GROUPS)"))]), set(("GROUPNAMES", "MEMBERS")))
</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("A")
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><span class="cx"> membershipsE = yield db.getMemberships("E")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</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("A", ("B", "C", "E",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><span class="cx"> membershipsE = yield db.getMemberships("E")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "E",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A",)))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membersX = yield db.getMembers("X")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield db.removeGroup("A")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membersX = yield db.getMembers("X")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set())
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set("X",))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield db.removeGroup("A")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membersX = yield db.getMembers("X")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set())
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set("X",))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membersX = yield db.getMembers("X")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield db.removePrincipal("B")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield db.getMembers("A")
</span><span class="cx"> membersX = yield db.getMembers("X")
</span><span class="cx"> membershipsB = yield db.getMemberships("B")
</span><span class="cx"> membershipsC = yield db.getMemberships("C")
</span><span class="cx"> membershipsD = yield db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("C",)))
</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 ("Single", "Combined",):
</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("AA", ("BB", "CC", "DD",))
</span><span class="cx"> yield db.getMemberships("DD")
</span><del>-
</del><ins>+
</ins><span class="cx"> # Change and check the result
</span><span class="cx"> yield db.setGroupMembers("AA", ("BB", "CC", "EE",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersAA = yield db.getMembers("AA")
</span><span class="cx"> membershipsBB = yield db.getMemberships("BB")
</span><span class="cx"> membershipsCC = yield db.getMemberships("CC")
</span><span class="cx"> membershipsDD = yield db.getMemberships("DD")
</span><span class="cx"> membershipsEE = yield db.getMemberships("EE")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersAA, set(("BB", "CC", "EE",)))
</span><span class="cx"> self.assertEqual(membershipsBB, set(("AA",)))
</span><span class="cx"> self.assertEqual(membershipsCC, set(("AA",)))
</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"> """
</span><span class="cx"> Directory service provisioned principals.
</span><span class="cx"> """
</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="localhost", database="proxies")
</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("/Volumes/Data/Users/cyrusdaboo/Documents/Development/Apple/eclipse/CalendarServer-3/conf/auth/proxies-test.xml")
</span><span class="cx"> yield loader.updateProxyDB()
</span><span class="cx">
</span><span class="cx"> yield self.db.setGroupMembers("A", ("B", "C", "D",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</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("select hasindexes from pg_tables where tablename = 'groups'")))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><span class="cx"> membershipsE = yield self.db.getMemberships("E")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</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("A", ("B", "C", "E",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><span class="cx"> membershipsE = yield self.db.getMemberships("E")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "E",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A",)))
</span><span class="cx"> self.assertEqual(membershipsD, set())
</span><span class="cx"> self.assertEqual(membershipsE, set(("A",)))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield self.db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membersX = yield self.db.getMembers("X")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield self.db.removeGroup("A")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membersX = yield self.db.getMembers("X")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set())
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set("X",))
</span><span class="cx"> self.assertEqual(membershipsC, set("X",))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield self.db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield self.db.removeGroup("A")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membersX = yield self.db.getMembers("X")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set())
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set("X",))
</span><span class="cx"> self.assertEqual(membershipsC, set("X",))
</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 ("Single", "Combined",):
</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("A", ("B", "C", "D",))
</span><span class="cx"> yield self.db.setGroupMembers("X", ("B", "C",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membersX = yield self.db.getMembers("X")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("B", "C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("B", "C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsC, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",)))
</span><del>-
</del><ins>+
</ins><span class="cx"> # Remove and check the result
</span><span class="cx"> yield self.db.removePrincipal("B")
</span><del>-
</del><ins>+
</ins><span class="cx"> membersA = yield self.db.getMembers("A")
</span><span class="cx"> membersX = yield self.db.getMembers("X")
</span><span class="cx"> membershipsB = yield self.db.getMemberships("B")
</span><span class="cx"> membershipsC = yield self.db.getMemberships("C")
</span><span class="cx"> membershipsD = yield self.db.getMemberships("D")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersA, set(("C", "D",)))
</span><span class="cx"> self.assertEqual(membersX, set(("C",)))
</span><span class="cx"> self.assertEqual(membershipsB, set())
</span><span class="cx"> self.assertEqual(membershipsC, set(("A", "X",)))
</span><span class="cx"> self.assertEqual(membershipsD, set(("A",),))
</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 ("Single", "Combined",):
</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("AA", ("BB", "CC", "DD",))
</span><span class="cx"> yield self.db.getMemberships("DD")
</span><del>-
</del><ins>+
</ins><span class="cx"> # Change and check the result
</span><span class="cx"> yield self.db.setGroupMembers("AA", ("BB", "CC", "EE",))
</span><del>-
</del><ins>+
</ins><span class="cx"> membersAA = yield self.db.getMembers("AA")
</span><span class="cx"> membershipsBB = yield self.db.getMemberships("BB")
</span><span class="cx"> membershipsCC = yield self.db.getMemberships("CC")
</span><span class="cx"> membershipsDD = yield self.db.getMemberships("DD")
</span><span class="cx"> membershipsEE = yield self.db.getMemberships("EE")
</span><del>-
</del><ins>+
</ins><span class="cx"> self.assertEqual(membersAA, set(("BB", "CC", "EE",)))
</span><span class="cx"> self.assertEqual(membershipsBB, set(("AA",)))
</span><span class="cx"> self.assertEqual(membershipsCC, set(("AA",)))
</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("user01")
</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("resource01")
</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>- "admin" : { "password": "nimda", "guid": "D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "addresses": () },
- "wsanchez" : { "password": "zehcnasw", "guid": "6423F94A-6B76-4A3A-815B-D52CFD77935D", "addresses": ("mailto:wsanchez@example.com",) },
- "cdaboo" : { "password": "oobadc", "guid": "5A985493-EE2C-4665-94CF-4DFEA3A89500", "addresses": ("mailto:cdaboo@example.com",) },
- "lecroy" : { "password": "yorcel", "guid": "8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "addresses": ("mailto:lecroy@example.com",) },
- "dreid" : { "password": "dierd", "guid": "5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "addresses": ("mailto:dreid@example.com",) },
- "nocalendar" : { "password": "radnelacon", "guid": "543D28BA-F74F-4D5F-9243-B3E3A61171E5", "addresses": () },
- "user01" : { "password": "01user", "guid": None , "addresses": ("mailto:c4ca4238a0@example.com",) },
- "user02" : { "password": "02user", "guid": None , "addresses": ("mailto:c81e728d9d@example.com",) },
- }
</del><ins>+ "admin" : {"password": "nimda", "guid": "D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "addresses": ()},
+ "wsanchez" : {"password": "zehcnasw", "guid": "6423F94A-6B76-4A3A-815B-D52CFD77935D", "addresses": ("mailto:wsanchez@example.com",)},
+ "cdaboo" : {"password": "oobadc", "guid": "5A985493-EE2C-4665-94CF-4DFEA3A89500", "addresses": ("mailto:cdaboo@example.com",) },
+ "lecroy" : {"password": "yorcel", "guid": "8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "addresses": ("mailto:lecroy@example.com",) },
+ "dreid" : {"password": "dierd", "guid": "5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "addresses": ("mailto:dreid@example.com",) },
+ "nocalendar" : {"password": "radnelacon", "guid": "543D28BA-F74F-4D5F-9243-B3E3A61171E5", "addresses": ()},
+ "user01" : {"password": "01user", "guid": None, "addresses": ("mailto:c4ca4238a0@example.com",)},
+ "user02" : {"password": "02user", "guid": None, "addresses": ("mailto:c81e728d9d@example.com",)},
+ }
</ins><span class="cx">
</span><span class="cx"> groups = {
</span><del>- "admin" : { "password": "admin", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "managers"),)},
- "managers" : { "password": "managers", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "lecroy"),)},
- "grunts" : { "password": "grunts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "wsanchez"),
</del><ins>+ "admin" : {"password": "admin", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "managers"),)},
+ "managers" : {"password": "managers", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "lecroy"),)},
+ "grunts" : {"password": "grunts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "wsanchez"),
</ins><span class="cx"> (DirectoryService.recordType_users , "cdaboo"),
</span><span class="cx"> (DirectoryService.recordType_users , "dreid"))},
</span><del>- "right_coast": { "password": "right_coast", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),)},
- "left_coast" : { "password": "left_coast", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "wsanchez"),
</del><ins>+ "right_coast": {"password": "right_coast", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),)},
+ "left_coast" : {"password": "left_coast", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "wsanchez"),
</ins><span class="cx"> (DirectoryService.recordType_users , "dreid"),
</span><span class="cx"> (DirectoryService.recordType_users , "lecroy"))},
</span><del>- "both_coasts": { "password": "both_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "right_coast"),
</del><ins>+ "both_coasts": {"password": "both_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "right_coast"),
</ins><span class="cx"> (DirectoryService.recordType_groups, "left_coast"))},
</span><del>- "recursive1_coasts": { "password": "recursive1_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive2_coasts"),
</del><ins>+ "recursive1_coasts": {"password": "recursive1_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive2_coasts"),
</ins><span class="cx"> (DirectoryService.recordType_users, "wsanchez"))},
</span><del>- "recursive2_coasts": { "password": "recursive2_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive1_coasts"),
</del><ins>+ "recursive2_coasts": {"password": "recursive2_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive1_coasts"),
</ins><span class="cx"> (DirectoryService.recordType_users, "cdaboo"))},
</span><del>- "non_calendar_group": { "password": "non_calendar_group", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),
</del><ins>+ "non_calendar_group": {"password": "non_calendar_group", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),
</ins><span class="cx"> (DirectoryService.recordType_users , "lecroy"))},
</span><del>- }
</del><ins>+ }
</ins><span class="cx">
</span><span class="cx"> locations = {
</span><del>- "mercury": { "password": "mercury", "guid": None, "addresses": ("mailto:mercury@example.com",) },
- "gemini" : { "password": "gemini", "guid": None, "addresses": ("mailto:gemini@example.com",) },
- "apollo" : { "password": "apollo", "guid": None, "addresses": ("mailto:apollo@example.com",) },
- "orion" : { "password": "orion", "guid": None, "addresses": ("mailto:orion@example.com",) },
- }
</del><ins>+ "mercury": {"password": "mercury", "guid": None, "addresses": ("mailto:mercury@example.com",)},
+ "gemini" : {"password": "gemini", "guid": None, "addresses": ("mailto:gemini@example.com",)},
+ "apollo" : {"password": "apollo", "guid": None, "addresses": ("mailto:apollo@example.com",)},
+ "orion" : {"password": "orion", "guid": None, "addresses": ("mailto:orion@example.com",)},
+ }
</ins><span class="cx">
</span><span class="cx"> resources = {
</span><del>- "transporter" : { "password": "transporter", "guid": None, "addresses": ("mailto:transporter@example.com",) },
- "ftlcpu" : { "password": "ftlcpu", "guid": None, "addresses": ("mailto:ftlcpu@example.com",) },
- "non_calendar_proxy" : { "password": "non_calendar_proxy", "guid": "non_calendar_proxy", "addresses": ("mailto:non_calendar_proxy@example.com",) },
- }
</del><ins>+ "transporter" : {"password": "transporter", "guid": None, "addresses": ("mailto:transporter@example.com",) },
+ "ftlcpu" : {"password": "ftlcpu", "guid": None, "addresses": ("mailto:ftlcpu@example.com",) },
+ "non_calendar_proxy" : {"password": "non_calendar_proxy", "guid": "non_calendar_proxy", "addresses": ("mailto:non_calendar_proxy@example.com",)},
+ }
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def xmlFile(self):
</span><span class="cx"> """
</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"> """
</span><span class="cx"> )
</span><span class="cx"> for recordType, expectedRecords in (
</span><del>- ( DirectoryService.recordType_users , ("admin",) ),
- ( DirectoryService.recordType_groups , () ),
- ( DirectoryService.recordType_locations , () ),
- ( DirectoryService.recordType_resources , () ),
</del><ins>+ (DirectoryService.recordType_users , ("admin",)),
+ (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 , ("my office",) ),
- ( DirectoryService.recordType_resources , () ),
</del><ins>+ (DirectoryService.recordType_users , ()),
+ (DirectoryService.recordType_groups , ()),
+ (DirectoryService.recordType_locations , ("my office",)),
+ (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"> </accounts>
</span><span class="cx"> """
</span><span class="cx"> )
</span><del>-
</del><ins>+
</ins><span class="cx"> for recordType, expectedRecords in (
</span><del>- ( DirectoryService.recordType_users , () ),
- ( DirectoryService.recordType_groups , ("enabled", "disabled") ),
- ( DirectoryService.recordType_locations , () ),
- ( DirectoryService.recordType_resources , () ),
</del><ins>+ (DirectoryService.recordType_users , ()),
+ (DirectoryService.recordType_groups , ("enabled", "disabled")),
+ (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"> </accounts>
</span><span class="cx"> """
</span><span class="cx"> )
</span><del>-
</del><ins>+
</ins><span class="cx"> record = service.recordWithShortName(
</span><span class="cx"> DirectoryService.recordType_locations, "my office")
</span><span class="cx"> self.assertEquals(record.guid, "myoffice")
</span><span class="cx"> self.assertEquals(record.extras["comment"], "This is the comment")
</span><span class="cx"> self.assertEquals(record.extras["capacity"], "40")
</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["comment"], "Test comment")
</span><span class="cx"> self.assertEquals(record.extras["capacity"], "10")
</span><span class="cx">
</span><del>-
</del><span class="cx"> service.updateRecord(DirectoryService.recordType_locations, "newguid",
</span><span class="cx"> shortNames=("New office",),
</span><span class="cx"> fullName="My Newer Office",
</span><span class="lines">@@ -333,6 +335,7 @@
</span><span class="cx"> self.assertNotEquals(None, service._lookupInIndex(service.recordType_locations, service.INDEX_TYPE_SHORTNAME, "orion"))
</span><span class="cx"> self.assertEquals(None, service._lookupInIndex(service.recordType_users, service.INDEX_TYPE_CUA, "mailto:nobody@example.com"))
</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, "c4ca4238a User 01")
</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"> """
</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(("users", "groups")), 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 = ("",)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def test_realm(self):
</span><span class="cx"> """
</span><span class="cx"> IDirectoryService.realm
</span><span class="cx"> """
</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"> """
</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"> """
</span><span class="cx"> IDirectoryService.recordWithShortName()
</span><span class="cx"> """
</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("No %s" % (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("No GUIDs provided to test")
</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("No calendar user addresses provided to test")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def test_groupMembers(self):
</span><span class="cx"> """
</span><span class="cx"> IDirectoryRecord.members()
</span><span class="lines">@@ -138,6 +144,7 @@
</span><span class="cx"> "Wrong membership for group %r: %s != %s" % (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"> """
</span><span class="cx"> IDirectoryRecord.groups()
</span><span class="lines">@@ -148,8 +155,8 @@
</span><span class="cx"> raise SkipTest("No groups")
</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"> "Wrong groups for %s %r: %s != %s" % (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("name"):
</span><span class="cx"> self.assertEquals(record.fullName, value("name"))
</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, "recordTypePrefix"):
</span><span class="lines">@@ -224,6 +235,8 @@
</span><span class="cx"> else:
</span><span class="cx"> return ""
</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"> """
</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"> """
</span><span class="cx"> IDirectoryService.listRecords("locations")
</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"> """
</span><span class="cx"> IDirectoryService.listRecords("resources")
</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"> """
</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]["password"])))
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> # authRequest = {
</span><span class="cx"> # username="username",
</span><span class="cx"> # realm="test realm",
</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"> """
</span><span class="lines">@@ -57,7 +60,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</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 > start
</span><span class="cx"> if self.end <= 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"> "tzexpand",
</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 = "-//CALENDARSERVER.ORG//NONSGML Version 1//EN"
</span><span class="cx">
</span><del>-allowedComponents = (
- "VEVENT",
- "VTODO",
- "VTIMEZONE",
- # "VJOURNAL",
- "VFREEBUSY",
- # "VAVAILABILITY",
-)
</del><ins>+allowedStoreComponents = ("VEVENT", "VTODO", "VPOLL",)
+allowedSchedulingComponents = allowedStoreComponents + ("VFREEBUSY",)
+allowedComponents = allowedSchedulingComponents + ("VTIMEZONE",)
</ins><span class="cx">
</span><ins>+def _updateAllowedComponents(allowed):
+ global allowedStoreComponents, allowedSchedulingComponents, allowedComponents
+ allowedStoreComponents = allowed
+ allowedSchedulingComponents = allowedStoreComponents + ("VFREEBUSY",)
+ allowedComponents = allowedSchedulingComponents + ("VTIMEZONE",)
+
+
</ins><span class="cx"> # Additional per-user data components - see datafilters.peruserdata.py for details
</span><span class="cx"> PERUSER_COMPONENT = "X-CALENDARSERVER-PERUSER"
</span><span class="cx"> PERUSER_UID = "X-CALENDARSERVER-PERUSER-UID"
</span><span class="lines">@@ -134,19 +136,28 @@
</span><span class="cx"> "LAST-MODIFIED": (None, {"VALUE": "DATE-TIME"}),
</span><span class="cx"> "SEQUENCE": (0, {"VALUE": "INTEGER"}),
</span><span class="cx"> "REQUEST-STATUS": (None, {"VALUE": "TEXT"}),
</span><ins>+
+ "VOTER": (None, {
+ "VALUE": "CAL-ADDRESS",
+ "CUTYPE": "INDIVIDUAL",
+ "ROLE": "REQ-PARTICIPANT",
+ "RSVP": "FALSE",
+ "SCHEDULE-AGENT": "SERVER",
+ }),
</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"> "ATTENDEE": normalizeCUAddr,
</span><span class="cx"> "ORGANIZER": normalizeCUAddr,
</span><ins>+ "VOTER": normalizeCUAddr,
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ignoredComponents = ("VTIMEZONE", 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["pycalendar"]
</span><span class="cx">
</span><del>- if not isinstance(pyobj, PyCalendarProperty):
- raise TypeError("Not a PyCalendarProperty: %r" % (property,))
</del><ins>+ if not isinstance(pyobj, PyProperty):
+ raise TypeError("Not a Property: %r" % (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("valuetype")
</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"> """
</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"> """
</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), "Not a date/date-time value: %r" % (self,)
</del><ins>+ assert isinstance(dt, DateTime), "Not a date/date-time value: %r" % (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 = "X-CALENDARSERVER-HIDDEN-INSTANCE"
</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 = ["text/calendar"]
+ if config.EnableJSONData:
+ cls.allowedTypesList.append("application/calendar+json")
+ return cls.allowedTypesList
+
+
+ @classmethod
+ def allFromString(clazz, string, format=None):
</ins><span class="cx"> """
</span><span class="cx"> Just default to reading a single VCALENDAR
</span><span class="cx"> """
</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"> """
</span><span class="cx"> Just default to reading a single VCALENDAR
</span><span class="cx"> """
</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"> """
</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"> """
</span><del>- if type(string) is unicode:
- string = string.encode("utf-8")
- else:
- # Valid utf-8 please
- string.decode("utf-8")
</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):
+ """
+ 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}.
+ """
+ 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"> """
</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"> """
</span><del>- cal = PyCalendar()
</del><ins>+
+ if isstream:
+ pass
+ else:
+ if type(data) is unicode:
+ data = data.encode("utf-8")
+ else:
+ # Valid utf-8 please
+ data.decode("utf-8")
+
+ # No BOMs please
+ if data[:3] == codecs.BOM_UTF8:
+ data = data[3:]
+
</ins><span class="cx"> errmsg = "Unknown"
</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 = "%s: %s" % (e.mReason, e.mData,)
</span><span class="cx"> result = None
</span><span class="cx"> if not result:
</span><del>- stream.seek(0)
- raise InvalidICalendarDataError("%s\n%s" % (errmsg, stream.read(),))
- return clazz(None, pycalendar=cal)
</del><ins>+ if isstream:
+ data.seek(0)
+ data = data.read()
+ raise InvalidICalendarDataError("%s\n%s" % (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"> """
</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["pycalendar"]
</span><span class="cx">
</span><span class="cx"> if pyobj is not None:
</span><del>- if not isinstance(pyobj, PyCalendarComponentBase):
- raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
</del><ins>+ if not isinstance(pyobj, ComponentBase):
+ raise TypeError("Not a ComponentBase: %r" % (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 == "VCALENDAR" else PyCalendar.makeComponent(name, None)
</del><ins>+ self._pycalendar = Calendar(add_defaults=False) if name == "VCALENDAR" 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"> """
</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"> """
</span><span class="cx"> assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (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("Unknown format requested for calendar data.")
+ 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"> """
</span><span class="cx"> assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (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"> """
</span><span class="cx"> dtstart = self.propertyValue("DTSTART")
</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"> """
</span><span class="cx"> dtend = self.propertyValue("DTEND")
</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"> """
</span><span class="cx"> due = self.propertyValue("DUE")
</span><span class="cx"> if due is None:
</span><span class="lines">@@ -827,7 +874,7 @@
</span><span class="cx"> """
</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"> """
</span><span class="cx"> rid = self.propertyValue("RECURRENCE-ID")
</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"> """
</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"> """
</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("DTSTART"),
</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"> """
</span><span class="cx">
</span><span class="cx"> if timezone is not None and isinstance(timezone, Component):
</span><del>- pytz = PyCalendarTimezone(tzid=timezone.propertyValue("TZID"))
</del><ins>+ pytz = Timezone(tzid=timezone.propertyValue("TZID"))
</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("TZID")
</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"> """
</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"> """
</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"> """
</span><span class="lines">@@ -1984,12 +2031,12 @@
</span><span class="cx">
</span><span class="cx"> def gettimezone(self):
</span><span class="cx"> """
</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"> """
</span><span class="cx"> if self.name() == "VTIMEZONE":
</span><del>- return PyCalendarTimezone(tzid=self._pycalendar.getID())
</del><ins>+ return Timezone(tzid=self._pycalendar.getID())
</ins><span class="cx"> elif self.name() == "VCALENDAR":
</span><span class="cx"> for component in self.subcomponents():
</span><span class="cx"> if component.name() == "VTIMEZONE":
</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 "VOTER" if self.name() == "VPOLL" else "ATTENDEE"
+
+
</ins><span class="cx"> def getAttendees(self):
</span><span class="cx"> """
</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("ATTENDEE")]
</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("ATTENDEE")):
</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("SCHEDULE-AGENT"):
</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):
+ """
+ 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
+ """
+
+ # 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("VOTER"):
+ if normalizeCUAddr(voter.value()) in test:
+ return voter
+
+ return None
+
+
</ins><span class="cx"> def getAttendeeProperty(self, match):
</span><span class="cx"> """
</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("ATTENDEE"):
</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("ATTENDEE"):
</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("ATTENDEE")) 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("ATTENDEE")) 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("SEQUENCE", newseq))
</span><span class="cx">
</span><del>- self.replacePropertyInAllComponents(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ self.replacePropertyInAllComponents(Property("DTSTAMP", 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("DTEND")
</span><span class="cx"> duration = self.getProperty("DURATION")
</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("ORGANIZER"),
</span><del>- component.properties("ATTENDEE")
</del><ins>+ component.properties("ATTENDEE"),
+ component.properties("VOTER")
</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("EMAIL")
</span><span class="cx">
</span><ins>+ # For VPOLL also do immediate children
+ if component.name() == "VPOLL":
+ 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"> """
</span><span class="cx"> CalDAV resource.
</span><span class="cx"> """
</span><del>- def isCalendarCollection():
</del><ins>+ def isCalendarCollection(): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def isSpecialCollection(collectiontype):
</del><ins>+ def isSpecialCollection(collectiontype): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def isPseudoCalendarCollection():
</del><ins>+ def isPseudoCalendarCollection(): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def findCalendarCollections(depth):
</del><ins>+ def findCalendarCollections(depth): #@NoSelf
</ins><span class="cx"> """
</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 "0", "1", or "infinity")
</span><span class="cx"> @return: an iterable of tuples C{(resource, uri)}.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def createCalendar(request):
</del><ins>+ def createCalendar(request): #@NoSelf
</ins><span class="cx"> """
</span><span class="cx"> Create a calendar collection for this resource.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def iCalendar():
</del><ins>+ def iCalendar(): #@NoSelf
</ins><span class="cx"> """
</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{"VCALENDAR"}.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def iCalendarText():
- """
- 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{"VCALENDAR"}.
- """
</del><span class="cx">
</span><span class="cx"> class ICalendarPrincipalResource(IDAVResource):
</span><span class="cx"> """
</span><span class="cx"> CalDAV principle resource.
</span><span class="cx"> """
</span><del>- def principalUID():
</del><ins>+ def principalUID(): #@NoSelf
</ins><span class="cx"> """
</span><span class="cx"> @return: the user id for this principal.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def calendarHomeURLs():
</del><ins>+ def calendarHomeURLs(): #@NoSelf
</ins><span class="cx"> """
</span><span class="cx"> @return: a list of calendar home URLs for this principal's calendar user.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def calendarUserAddresses():
</del><ins>+ def calendarUserAddresses(): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def calendarFreeBusyURIs(self, request):
</del><ins>+ def calendarFreeBusyURIs(request): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def scheduleInboxURL():
</del><ins>+ def scheduleInboxURL(): #@NoSelf
</ins><span class="cx"> """
</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"> """
</span><span class="cx">
</span><del>- def scheduleOutboxURL():
</del><ins>+ def scheduleOutboxURL(): #@NoSelf
</ins><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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, "_linkedResource"):
</span><span class="cx"> if self.linkURL in self.loopDetect:
</span><span class="cx"> raise HTTPError(StatusResponse(responsecode.LOOP_DETECTED, "Recursive link target: %s" % (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, "Missing link target: %s" % (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, "_linkedResource") 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, "_linkedResource") 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, "Link resource with missing target: %s" % (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, "_linkedResource") 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("DTSTART")
</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"> """
</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 ""
</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(_("1 day"))
</span><span class="cx"> elif days > 1:
</span><span class="cx"> parts.append(_("%(dayCount)d days") %
</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(_("1 hour"))
</span><span class="cx"> elif hours > 1:
</span><span class="cx"> parts.append(_("%(hourCount)d hours") %
</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(_("1 minute"))
</span><span class="cx"> elif minutes > 1:
</span><span class="cx"> parts.append(_("%(minuteCount)d minutes") %
</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(_("1 second"))
</span><span class="cx"> elif seconds > 1:
</span><span class="cx"> parts.append(_("%(secondCount)d seconds") %
</span><del>- { 'secondCount' : seconds })
</del><ins>+ {'secondCount' : seconds})
</ins><span class="cx">
</span><span class="cx"> return " ".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("%s is up to date" % (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"> "Iiiiiii",
</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("i", keyDescriptors).tostring()
</span><span class="cx"> result += array.array("i", 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"> """
</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"> """
</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("No implementation of shared locking without memcached")
</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, "Lock already acquired."
</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, "1", 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("Got lock after waiting on %s" % (self._locktoken,))
</span><span class="cx"> break
</span><del>-
</del><ins>+
</ins><span class="cx"> if self._timeout and time.time() < timeout_at:
</span><span class="cx"> waiting = True
</span><span class="cx"> self.log.debug("Waiting for lock on %s" % (self._locktoken,))
</span><span class="lines">@@ -80,13 +82,14 @@
</span><span class="cx"> else:
</span><span class="cx"> self.log.debug("Timed out lock after waiting on %s" % (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, "Lock not acquired."
</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"> """
</span><span class="cx"> Test if the lock is currently being held.
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</span><del>- self.log.debug("Initating new client connection to: %r" % (
</del><ins>+ self.log.debug("Initiating new client connection to: %r" % (
</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("accept"), Component.allowedTypes())
+ if accepted_type is None:
+ raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
+
</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("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
</del><ins>+ response.stream = MemoryStream(caldata.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference, format=accepted_type))
+ response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (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 = "names"
</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("Unexpected element type in %s: %s"
</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, "calendar-timezone"), 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, "calendar-timezone"), 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, "calendar-timezone"), 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, "calendar-timezone"), 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([("text/calendar", "2.0")]):
</del><ins>+ if not property.verifyTypeVersion():
</ins><span class="cx"> result = False
</span><span class="cx"> message = "Calendar-data element type/version not supported: content-type: %s, version: %s" % (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([("text/vcard", "3.0")]):
</del><ins>+ if not property.verifyTypeVersion():
</ins><span class="cx"> result = False
</span><span class="cx"> message = "Address-data element type/version not supported: content-type: %s, version: %s" % (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) <= 0 and compareDateTime(timerange.start, cached_start) >= 0:
</span><span class="lines">@@ -515,9 +515,9 @@
</span><span class="cx"> useruid = ""
</span><span class="cx">
</span><span class="cx"> # Get the timezone property from the collection.
</span><del>- has_prop = (yield calresource.hasProperty((caldav_namespace, "calendar-timezone"), 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, "calendar-timezone"), 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["fb-uncached"] = request.extendedLogItems.get("fb-uncached", 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) >= 0 and compareDateTime(timerange.end, cache_end) <= 0:
</span><span class="lines">@@ -602,7 +602,7 @@
</span><span class="cx"> request.extendedLogItems["fb-cached"] = request.extendedLogItems.get("fb-cached", 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"> """
</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"> """
</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("DURATION"):
</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), "FREEBUSY property does not contain a list of values: %r" % (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 < 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 < 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("BUSYTYPE")
</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("DURATION"):
</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("DTSTART", timerange.start))
</span><span class="cx"> fb.addProperty(Property("DTEND", timerange.end))
</span><del>- fb.addProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ fb.addProperty(Property("DTSTAMP", DateTime.getNowUTC()))
</ins><span class="cx"> if len(fbinfo[0]) != 0:
</span><span class="cx"> fb.addProperty(Property("FREEBUSY", fbinfo[0], {"FBTYPE": "BUSY"}))
</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("accept"), Component.allowedTypes())
+ if accepted_type is None:
+ raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
+
+
</ins><span class="cx"> def generateFreeBusyInfo(calresource, uri): #@UnusedVariable
</span><span class="cx"> """
</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("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
</del><ins>+ response.stream = MemoryStream(fbcalendar.getText(accepted_type))
+ response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (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"> """
</span><span class="cx"> name = "mkcol"
</span><span class="cx">
</span><del>- allowed_children = { (davxml.dav_namespace, "set"): (0, 1) }
</del><ins>+ allowed_children = {(davxml.dav_namespace, "set"): (0, 1)}
</ins><span class="cx">
</span><del>- child_types = { "WebDAVUnknownElement": (0, None) }
</del><ins>+ child_types = {"WebDAVUnknownElement": (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"> """
</span><span class="lines">@@ -58,4 +59,4 @@
</span><span class="cx"> """
</span><span class="cx"> name = "mkcol-response"
</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, "_notificationsDB"):
</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 + ".xml"
</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("select * from NOTIFICATIONS")
</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("select * from NOTIFICATIONS where UID = :1", 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("""insert or replace into NOTIFICATIONS (UID, NAME, TYPE)
</span><span class="cx"> values (:1, :2, :3)
</span><span class="cx"> """, 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"> """
</span><span class="cx"> insert or replace into REVISIONS (NAME, REVISION, DELETED)
</span><span class="cx"> values (:1, :2, :3)
</span><span class="cx"> """, 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("delete from NOTIFICATIONS where NAME = :1", rname)
</span><span class="lines">@@ -192,12 +210,13 @@
</span><span class="cx"> where NAME = :3
</span><span class="cx"> """, 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("utf-8"), deleted) for name, deleted in self._db_execute("select NAME, DELETED from REVISIONS where REVISION > :1", 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"> "select REVISION from REVISION_SEQUENCE"
</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"> """
</span><span class="lines">@@ -230,18 +251,21 @@
</span><span class="cx"> """,
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _db_version(self):
</span><span class="cx"> """
</span><span class="cx"> @return: the schema version assigned to this index.
</span><span class="cx"> """
</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"> """
</span><span class="cx"> @return: the collection type assigned to this index.
</span><span class="cx"> """
</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"> """
</span><span class="cx"> Initialise the underlying database tables.
</span><span class="lines">@@ -302,6 +326,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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 "start" not in xml_element.attributes and "end" not in xml_element.attributes:
</span><span class="cx"> raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
</span><span class="cx">
</span><del>- self.start = PyCalendarDateTime.parseText(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
- self.end = PyCalendarDateTime.parseText(xml_element.attributes["end"]) if "end" in xml_element.attributes else None
</del><ins>+ self.start = DateTime.parseText(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
+ self.end = DateTime.parseText(xml_element.attributes["end"]) if "end" 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"> """
</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"> """
</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="America/New_York"))
</del><ins>+ filter.child.settzinfo(Timezone(tzid="America/New_York"))
</ins><span class="cx">
</span><span class="cx"> sql, args = sqlcalendarquery(filter)
</span><span class="cx"> self.assertTrue(sql.find("RESOURCE") != -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="America/New_York"))
</del><ins>+ filter.child.settzinfo(Timezone(tzid="America/New_York"))
</ins><span class="cx">
</span><span class="cx"> sql, args = sqlcalendarquery(filter)
</span><span class="cx"> self.assertTrue(sql.find("RESOURCE") != -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="America/New_York"))
</del><ins>+ filter.child.settzinfo(Timezone(tzid="America/New_York"))
</ins><span class="cx">
</span><span class="cx"> sql, args = sqlcalendarquery(filter)
</span><span class="cx"> self.assertTrue(sql.find("RESOURCE") != -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="America/New_York"))
</del><ins>+ filter.child.settzinfo(Timezone(tzid="America/New_York"))
</ins><span class="cx">
</span><span class="cx"> sql, args = sqlcalendarquery(filter)
</span><span class="cx"> self.assertTrue(sql.find("RESOURCE") != -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"> """))
</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("content-type", MimeType.fromString("text/calendar"))
</del><ins>+ response.stream = MemoryStream(data.getText(accepted_type))
+ response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (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"> """
</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"> """
</span><del>- raise NotImplementedError("%s does not implement storeStream" %
- (self,))
</del><ins>+ raise NotImplementedError("%s does not implement storeStream" % (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"> "content-type": "text/calendar",
</span><span class="cx"> "version" : "2.0",
</span><span class="cx"> }),
</span><del>- ))
</del><ins>+ )
+ if config.EnableJSONData:
+ dataTypes.append(
+ caldavxml.CalendarData(**{
+ "content-type": "application/calendar+json",
+ "version" : "2.0",
+ }),
+ )
+ 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"> "content-type": "text/vcard",
</span><span class="cx"> "version" : "3.0",
</span><span class="cx"> }),
</span><del>- ))
</del><ins>+ )
+ if config.EnableJSONData:
+ dataTypes.append(
+ carddavxml.AddressDataType(**{
+ "content-type": "application/vcard+json",
+ "version" : "3.0",
+ }),
+ )
+ 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="VEVENT",
</del><ins>+ name=name,
</ins><span class="cx"> ),
</span><del>- ),
- caldavxml.SupportedCalendarComponentSet(
- caldavxml.CalendarComponent(
- name="VTODO",
- ),
- ),
- )
</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"> """
</span><span class="cx"> Write either the default VEVENT or VTODO calendar property, validating and canonicalizing the value
</span><span class="cx"> """
</span><del>- tasks = property.qname() == customxml.ScheduleDefaultTasksURL
- error_element = (calendarserver_namespace, "valid-schedule-default-tasks-URL") if tasks else (caldav_namespace, "valid-schedule-default-calendar-URL")
</del><ins>+ if property.qname() == caldavxml.ScheduleDefaultCalendarURL.qname():
+ ctype = "VEVENT"
+ error_element = (caldav_namespace, "valid-schedule-default-calendar-URL")
+ elif property.qname() == customxml.ScheduleDefaultTasksURL.qname():
+ ctype = "VTODO"
+ error_element = (calendarserver_namespace, "valid-schedule-default-tasks-URL")
+ 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):
+ """
+ Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+ """
+ format = None
+ if content_type is not None:
+ format = "%s/%s" % (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("content-type")
</span><del>- if contentType is not None and (contentType.mediaType, contentType.mediaSubtype) != ("text", "calendar"):
</del><ins>+ format = self.determineType(contentType)
+ if format is None:
</ins><span class="cx"> self.log.error("MIME type %s not allowed in calendar collection" % (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("Error while handling POST: %s" % (Failure(),))
</span><span class="lines">@@ -458,7 +475,7 @@
</span><span class="cx"> description="Can't parse calendar data"
</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"> """
</span><span class="cx">
</span><del>-__all__ = [
</del><ins>+__all__ = [
</ins><span class="cx"> "db_prefix",
</span><span class="cx"> "DatabaseError",
</span><span class="cx"> "AbstractSQLDatabase",
</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"> """
</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 "<%s %r>" % (self.__class__.__name__, self.dbpath)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _db_version(self):
</span><span class="cx"> """
</span><span class="cx"> @return: the schema version assigned to this index.
</span><span class="cx"> """
</span><span class="cx"> raise NotImplementedError
</span><del>-
</del><ins>+
+
</ins><span class="cx"> def _db_type(self):
</span><span class="cx"> """
</span><span class="cx"> @return: the collection type assigned to this index.
</span><span class="cx"> """
</span><span class="cx"> raise NotImplementedError
</span><del>-
</del><ins>+
+
</ins><span class="cx"> def _db(self):
</span><span class="cx"> """
</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("Database %s has different schema (v.%s vs. v.%s)"
</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("""
</span><span class="cx"> select (1) from SQLITE_MASTER
</span><span class="lines">@@ -149,6 +155,7 @@
</span><span class="cx"> """)
</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"> """
</span><span class="lines">@@ -157,7 +164,8 @@
</span><span class="cx"> """)
</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"> """
</span><span class="lines">@@ -166,10 +174,12 @@
</span><span class="cx"> """)
</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"> """
</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("begin exclusive transaction")
</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"> """
</span><span class="cx"> Initialise the underlying database tables.
</span><span class="lines">@@ -229,6 +240,7 @@
</span><span class="cx"> """, [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"> """
</span><span class="cx"> Initialise the underlying database tables.
</span><span class="lines">@@ -237,6 +249,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</span><span class="cx"> Upgrade the database tables.
</span><span class="cx"> """
</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"> """
</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("Persistent databases MUST support an upgrade method.")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _db_upgrade_schema(self, q):
</span><span class="cx"> """
</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"> """, [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, "_db_connection"):
</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"> """
</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"> """
</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"> """
</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"> """
</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"> "EnableManagedAttachments" : False, # Support Managed Attachments
</span><span class="cx">
</span><span class="cx"> #
</span><ins>+ # Generic CalDAV/CardDAV extensions
+ #
+ "EnableJSONData" : 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"> "EnableDropBox" : 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>+ "SupportedComponents" : [ # Set of supported iCalendar components
+ "VEVENT",
+ "VTODO",
+ #"VPOLL",
+ ],
+
</ins><span class="cx"> "ParallelUpgrades" : False, # Perform upgrades - currently only the
</span><span class="cx"> # database -> 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):
+ """
+ Updated support iCalendar components.
+ """
+ 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"> """
</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("content-type")
+ if format:
+ format = "%s/%s" % (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, "Could not parse valid data from request body"))
</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"> """
</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"> """
</span><span class="cx"> generate one xmlresponse for bulk create
</span><span class="cx"> """
</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(",")
</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(",")
</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[("text", "calendar")] = _CommonHomeChildCollectionMixin.simpleBatchPOST
</span><ins>+ if config.EnableJSONData:
+ self._postHandlers[("application", "calendar+json")] = _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("accept"), Component.allowedTypes())
+ if accepted_type is None:
+ raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
+
</ins><span class="cx"> # Generate a monolithic calendar
</span><span class="cx"> calendar = VCalendar("VCALENDAR")
</span><span class="cx"> calendar.addProperty(VProperty("VERSION", "2.0"))
</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()) + "\r\n" + 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"> """
</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):
+ """
+ Return a dict of allowed MIME types for storing, mapped to equivalent PyCalendar types.
+ """
+ raise NotImplementedError
+
+
+ def determineType(self, content_type):
+ """
+ Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+ """
+ format = None
+ if content_type is not None:
+ format = "%s/%s" % (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("Resource not found: %s" % (self,))
</span><span class="cx"> raise HTTPError(NOT_FOUND)
</span><span class="cx">
</span><ins>+ # Accept header handling
+ accepted_type = bestAcceptType(request.headers.getHeader("accept"), self.allowedTypes())
+ if accepted_type is None:
+ raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
+
</ins><span class="cx"> output = yield self.component()
</span><span class="cx">
</span><del>- response = Response(OK, {}, str(output))
- response.headers.setHeader("content-type", self.contentType())
</del><ins>+ response = Response(OK, {}, output.getText(accepted_type))
+ response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (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):
+ """
+ Return a tuple of allowed MIME types for storing.
+ """
+ return Component.allowedTypes()
+
+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def inNewTransaction(self, request, label=""):
</span><span class="cx"> """
</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("content-type")
</span><del>- if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "calendar"):
</del><ins>+ format = self.determineType(content_type)
+ if format is None:
</ins><span class="cx"> log.error("MIME type %s not allowed in calendar collection" % (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, "valid-calendar-data"),
</span><del>- "Can't parse calendar data"
</del><ins>+ "Can't parse calendar data: %s" % (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(",")
</span><span class="cx"> try:
</span><del>- rids = [PyCalendarDateTime.parseText(rid) if rid != "M" else None for rid in rids]
</del><ins>+ rids = [DateTime.parseText(rid) if rid != "M" 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[("text", "vcard")] = AddressBookCollectionResource.simpleBatchPOST
</span><ins>+ if config.EnableJSONData:
+ self._postHandlers[("application", "vcard+json")] = _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"> """
</span><span class="cx"> bulk create allowing groups to contain member UIDs added during the same bulk create
</span><span class="cx"> """
</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["coaddedUIDs"] = 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):
+ """
+ Return a tuple of allowed MIME types for storing.
+ """
+ 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("content-type")
</span><del>- if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "vcard"):
</del><ins>+ format = self.determineType(content_type)
+ if format is None:
</ins><span class="cx"> log.error("MIME type %s not allowed in vcard collection" % (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"> """
</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, "PUT", joinURL(addressbook_uri, filename + ".vcf"), authid="wsanchez")
</del><ins>+ request = SimpleStoreRequest(
+ self,
+ "PUT",
+ joinURL(addressbook_uri, filename + ".vcf"),
+ headers=Headers({"content-type": MimeType.fromString("text/vcard")}),
+ authid="wsanchez"
+ )
</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] != ".vcf":
</span><span class="cx"> continue
</span><del>- request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, child.basename()), authid="wsanchez")
</del><ins>+ request = SimpleStoreRequest(
+ self,
+ "PUT",
+ joinURL(addressbook_uri, child.basename()),
+ headers=Headers({"content-type": MimeType.fromString("text/vcard")}),
+ authid="wsanchez"
+ )
</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 "".join(map(str.strip, j.splitlines())).replace(", ", ",").replace(": ", ":")
+
+
+
</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="20110201T120000Z", end="20110202")
</span><span class="cx"> self.assertFalse(tr.valid())
</span><ins>+
+
+ def test_CalendarDataTextAndJSON(self):
+ """
+ Text that we can both parse and generate CalendarData elements with both text and json formats.
+ """
+ dataText = """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
+""".replace("\n", "\r\n")
+
+ dataXML = """<?xml version='1.0' encoding='UTF-8'?>
+<calendar-data xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % (dataText,)
+
+ jsonText = """[
+ "vcalendar",
+ [
+ ["version", {}, "text", "2.0"],
+ ["prodid", {}, "text", "-//CALENDARSERVER.ORG//NONSGML Version 1//EN"]
+ ],
+ [
+ ["vevent",
+ [
+ ["uid", {}, "text", "12345-67890"],
+ ["dtstart", {}, "date-time", "2008-06-01T12:00:00Z"],
+ ["dtend", {}, "date-time", "2008-06-01T13:00:00Z"],
+ ["attendee", {}, "cal-address", "mailto:user1@example.com"],
+ ["attendee", {}, "cal-address", "mailto:user2@example.com"],
+ ["dtstamp", {}, "date-time", "2008-06-01T12:00:00Z"],
+ ["exdate", {}, "date-time", "2008-06-02T12:00:00Z"],
+ ["exdate", {}, "date-time", "2008-06-03T12:00:00Z"],
+ ["organizer", {"cn": "User 01"}, "cal-address", "mailto:user1@example.com"],
+ ["rrule", {}, "recur", {"count": 400, "freq": "DAILY"}],
+ ["summary", {}, "text", "Test"]
+ ],
+ [
+ ]
+ ]
+ ]
+]
+"""
+
+ jsonXML = """<?xml version='1.0' encoding='UTF-8'?>
+<calendar-data content-type='application/calendar+json' xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % (jsonText,)
+
+ cd = CalendarData.fromTextData(dataText)
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "text/calendar")
+ self.assertEqual(cd.toxml(), dataXML)
+
+ comp = Component.fromString(dataText)
+ cd = CalendarData.fromCalendar(comp)
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "text/calendar")
+ self.assertEqual(cd.toxml(), dataXML)
+
+ cd = CalendarData.fromCalendar(comp, format="application/calendar+json")
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "application/calendar+json")
+ self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML))
+
+ cd = CalendarData.fromTextData(jsonText, format="application/calendar+json")
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "application/calendar+json")
+ self.assertEqual(cd.toxml(), jsonXML)
+
+ comp = Component.fromString(jsonText, format="application/calendar+json")
+ cd = CalendarData.fromCalendar(comp)
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "text/calendar")
+ self.assertEqual(cd.toxml(), dataXML)
+
+ cd = CalendarData.fromCalendar(comp, format="application/calendar+json")
+ self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText))
+ self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText))
+ self.assertEqual(cd.content_type, "application/calendar+json")
+ 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="%04d1001T000000Z" % (PyCalendarDateTime.getToday().getYear(),),
- end="%04d1101T000000Z" % (PyCalendarDateTime.getToday().getYear(),),
</del><ins>+ start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+ end="%04d1101T000000Z" % (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"> """
</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="America/New_York")), 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="America/New_York")), 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"> """
</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="America/New_York")), 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="America/New_York")), 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"> """
</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="America/New_York")), 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="America/New_York")), 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"> "Start within, end within - overlap",
</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"> "Start before, end before - no overlap",
</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"> "Start before, end right before - no overlap",
</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"> "Start before, end within - overlap",
</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"> "Start after, end after - no overlap",
</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"> "Start right after, end after - no overlap",
</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"> "Start within, end after - overlap",
</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"> "Start before, end after - overlap",
</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"> "All day: Start within, end within - overlap",
</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"> "All day: Start before, end before - no overlap",
</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"> "All day: Start before, end right before - no overlap",
</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"> "All day: Start before, end within - overlap",
</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"> "All day: Start after, end after - no overlap",
</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"> "All day: Start right after, end after - no overlap",
</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"> "All day: Start within, end after - overlap",
</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"> "All day: Start before, end after - overlap",
</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"> """
</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"> """
</span><span class="cx"> tests = (
</span><del>- ("2012-04-04 12:34:56", PyCalendarDateTime(2012, 4, 4, 12, 34, 56)),
- ("2012-12-31 01:01:01", PyCalendarDateTime(2012, 12, 31, 1, 1, 1)),
</del><ins>+ ("2012-04-04 12:34:56", DateTime(2012, 4, 4, 12, 34, 56)),
+ ("2012-12-31 01:01:01", 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"> """
</span><span class="cx">
</span><span class="cx"> tests = (
</span><del>- ("2012-04-04", PyCalendarDateTime(2012, 4, 4)),
- ("2012-12-31 00:00:00", PyCalendarDateTime(2012, 12, 31)),
</del><ins>+ ("2012-04-04", DateTime(2012, 4, 4)),
+ ("2012-12-31 00:00:00", 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"> """
</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"> """
</span><span class="cx"> calendar = Component.fromStream(file(os.path.join(self.data_dir, "Holidays", "C318ABFE-1ED0-11D9-A5E0-000A958A3252.ics")))
</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 = "recurrence expansion should give us no end date here"
</span><span class="lines">@@ -658,44 +658,44 @@
</span><span class="cx"> """
</span><span class="cx"> parse_date()
</span><span class="cx"> """
</span><del>- self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
</del><ins>+ self.assertEqual(DateTime.parseText("19970714"), 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"> """
</span><span class="cx"> parse_datetime()
</span><span class="cx"> """
</span><del>- dt = PyCalendarDateTime.parseText("19980118T230000")
- self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
</del><ins>+ dt = DateTime.parseText("19980118T230000")
+ 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("19980119T070000Z")
- self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+ dt = DateTime.parseText("19980119T070000Z")
+ 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"> """
</span><span class="cx"> parse_date_or_datetime()
</span><span class="cx"> """
</span><del>- self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
</del><ins>+ self.assertEqual(DateTime.parseText("19970714"), DateTime(1997, 7, 14))
</ins><span class="cx">
</span><del>- dt = PyCalendarDateTime.parseText("19980118T230000")
- self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
</del><ins>+ dt = DateTime.parseText("19980118T230000")
+ 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("19980119T070000Z")
- self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+ dt = DateTime.parseText("19980119T070000Z")
+ 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"> """
</span><span class="cx"> parse_duration()
</span><span class="cx"> """
</span><del>- self.assertEqual(PyCalendarDuration.parseText("P15DT5H0M20S"), PyCalendarDuration(days=15, hours=5, minutes=0, seconds=20))
- self.assertEqual(PyCalendarDuration.parseText("+P15DT5H0M20S"), PyCalendarDuration(days=15, hours=5, minutes=0, seconds=20))
- self.assertEqual(PyCalendarDuration.parseText("-P15DT5H0M20S"), PyCalendarDuration(days=15 * -1, hours=5 * -1, minutes=0, seconds=20 * -1))
</del><ins>+ self.assertEqual(Duration.parseText("P15DT5H0M20S"), Duration(days=15, hours=5, minutes=0, seconds=20))
+ self.assertEqual(Duration.parseText("+P15DT5H0M20S"), Duration(days=15, hours=5, minutes=0, seconds=20))
+ self.assertEqual(Duration.parseText("-P15DT5H0M20S"), Duration(days=15 * -1, hours=5 * -1, minutes=0, seconds=20 * -1))
</ins><span class="cx">
</span><del>- self.assertEqual(PyCalendarDuration.parseText("P7W"), PyCalendarDuration(weeks=7))
</del><ins>+ self.assertEqual(Duration.parseText("P7W"), 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"> """,
</span><span class="cx"> (
</span><span class="cx"> ("mailto:user1@example.com", None),
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+ ("mailto:user1@example.com", 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"> """,
</span><span class="cx"> (
</span><span class="cx"> ("mailto:user1@example.com", None),
</span><del>- ("mailto:user3@example.com", PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+ ("mailto:user3@example.com", 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"> ("mailto:user2@example.com", None),
</span><del>- ("mailto:user2@example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
</del><ins>+ ("mailto:user2@example.com", DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", 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("ATTACH", "foobar", valuetype=PyCalendarValue.VALUETYPE_BINARY))
</del><ins>+ vevent.addProperty(Property("ATTACH", "foobar", 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), "%s: wrong number of instances" % (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), "%s: wrong number of instances" % (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"> """,
</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"> """,
</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"> "Simple recurring - no limit",
</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"> """,
</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"> """,
</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"> "Simple recurring - limit effective full",
</span><span class="lines">@@ -3013,9 +3013,9 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</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"> "Complex recurring - no limit",
</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"> """,
</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"> """,
</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"> "Complex recurring - limit effective full",
</span><span class="lines">@@ -3180,15 +3180,15 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</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), "%s: wrong number of instances" % (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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """,
</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"> """,
</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"> """,
</span><del>- PyCalendarDateTime(2009, 1, 8),
</del><ins>+ DateTime(2009, 1, 8),
</ins><span class="cx"> """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"> """,
</span><del>- PyCalendarDateTime(2009, 1, 3),
</del><ins>+ DateTime(2009, 1, 3),
</ins><span class="cx"> """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"> """,
</span><del>- PyCalendarDateTime(2009, 1, 10),
</del><ins>+ DateTime(2009, 1, 10),
</ins><span class="cx"> """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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """BEGIN:VEVENT
</span><span class="lines">@@ -4349,8 +4349,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</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"> """BEGIN:VEVENT
</span><span class="lines">@@ -4388,8 +4388,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</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"> """BEGIN:VEVENT
</span><span class="lines">@@ -4425,8 +4425,8 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """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"> """,
</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"> """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, "cachedInstances"))
</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, "cachedInstances"))
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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"> """,
</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), "%s: wrong number of instances" % (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"> ("", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", 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"> ("", 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"> ("", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", 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"> ("", False,),
</span><span class="cx"> ("user01", False,),
</span><span class="lines">@@ -7415,7 +7415,7 @@
</span><span class="cx"> """,
</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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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"> """,
</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"> """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)), "12:00 AM")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 12, 0, 0)), "12:00 PM")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 23, 59, 0)), "11:59 PM")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 6, 5, 0)), "6:05 AM")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 16, 5, 0)), "4:05 PM")
</del><ins>+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 0, 0, 0)), "12:00 AM")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 12, 0, 0)), "12:00 PM")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 23, 59, 0)), "11:59 PM")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 6, 5, 0)), "6:05 AM")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 16, 5, 0)), "4:05 PM")
</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)), "00:00")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 12, 0, 0)), "12:00")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 23, 59, 0)), "23:59")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 6, 5, 0)), "06:05")
- self.assertEquals(t.dtTime(PyCalendarDateTime(2000, 1, 1, 16, 5, 0)), "16:05")
</del><ins>+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 0, 0, 0)), "00:00")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 12, 0, 0)), "12:00")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 23, 59, 0)), "23:59")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 6, 5, 0)), "06:05")
+ self.assertEquals(t.dtTime(DateTime(2000, 1, 1, 16, 5, 0)), "16:05")
</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, "PUT", joinURL(calendar_uri, filename + ".ics"), authid="wsanchez")
</del><ins>+ request = SimpleStoreRequest(
+ self,
+ "PUT",
+ joinURL(calendar_uri, filename + ".ics"),
+ headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+ authid="wsanchez"
+ )
</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] != ".ics":
</span><span class="cx"> continue
</span><del>- request = SimpleStoreRequest(self, "PUT", joinURL(calendar_uri, child.basename()), authid="wsanchez")
</del><ins>+ request = SimpleStoreRequest(
+ self,
+ "PUT",
+ joinURL(calendar_uri, child.basename()),
+ headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+ authid="wsanchez"
+ )
</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("Expected CalDAV:supported-calendar-data element; but got none.")
</span><span class="cx">
</span><span class="cx"> for calendar in supported_calendar.children:
</span><del>- if calendar.content_type != "text/calendar":
</del><ins>+ if calendar.content_type not in ("text/calendar", "application/calendar+json"):
</ins><span class="cx"> self.fail("Expected a text/calendar calendar-data type restriction")
</span><span class="cx"> if calendar.version != "2.0":
</span><span class="cx"> self.fail("Expected a version 2.0 calendar-data restriction")
</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() != "VCALENDAR":
</span><span class="cx"> self.fail("Calendar is not a VCALENDAR")
</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"> "TruncatedApr01.ics",
</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"> "TruncatedDec10.ics",
</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"> "TruncatedApr01.ics",
</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"> "TruncatedDec10.ics",
</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"> "TruncatedApr01.ics",
</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"> "TruncatedDec10.ics",
</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"> "TruncatedDec10.ics",
</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"> "TruncatedApr01.ics",
</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() != "VCALENDAR":
</span><span class="cx"> self.fail("Calendar is not a VCALENDAR")
</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 " Bad Quotes " 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 "License");
+# 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 "AS IS" 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):
+ """
+ L{bestAcceptType} tests
+ """
+ def test_bestAcceptType(self):
+
+ data = (
+ (
+ "#1.1",
+ ("Accept", "text/plain"),
+ ["text/plain"],
+ "text/plain",
+ ),
+ (
+ "#1.2",
+ ("Accept", "text/plain"),
+ ["text/calendar"],
+ None,
+ ),
+ (
+ "#1.3",
+ ("Accept", "text/*"),
+ ["text/plain"],
+ "text/plain",
+ ),
+ (
+ "#1.4",
+ ("Accept", "*/*"),
+ ["text/plain"],
+ "text/plain",
+ ),
+ (
+ "#2.1",
+ ("Accept", "text/plain"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#2.2",
+ ("Accept", "text/plain"),
+ ["text/calendar", "application/text", ],
+ None,
+ ),
+ (
+ "#2.3",
+ ("Accept", "text/*"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#2.4",
+ ("Accept", "*/*"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#2.5",
+ ("Accept", "application/text"),
+ ["text/plain", "application/text", ],
+ "application/text",
+ ),
+ (
+ "#2.6",
+ ("Accept", "application/*"),
+ ["text/plain", "application/text", ],
+ "application/text",
+ ),
+ (
+ "#3.1",
+ ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#3.2",
+ ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
+ ["text/calendar", "application/calendar", ],
+ None,
+ ),
+ (
+ "#3.3",
+ ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#3.4",
+ ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#3.5",
+ ("Accept", "text/plain;q=0.3, application/text;q=0.5"),
+ ["text/plain", "application/text", ],
+ "application/text",
+ ),
+ (
+ "#3.6",
+ ("Accept", "text/plain;q=0.5, application/*;q=0.3"),
+ ["text/plain", "application/text", ],
+ "text/plain",
+ ),
+ (
+ "#4.1",
+ ("Accept", "text/plain;q=0.5, application/text;q=0.2, text/*;q=0.3"),
+ ["text/calendar", "application/text", ],
+ "text/calendar",
+ ),
+ (
+ "#5.1",
+ None,
+ ["text/calendar", "application/text", ],
+ "text/calendar",
+ ),
+ )
+
+ for title, hdr, allowedTypes, result in data:
+ hdrs = Headers()
+ if hdr:
+ hdrs.addRawHeader(*hdr)
+ check = bestAcceptType(hdrs.getHeader("accept"), allowedTypes)
+ self.assertEqual(check, result, msg="Failed %s" % (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"> """
</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, "_dead_properties"):
</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("text/xml")
</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 = """<html>
</span><span class="cx"> <head>
</span><span class="lines">@@ -127,10 +138,11 @@
</span><span class="cx"> """
</span><span class="cx"> The timezone service POST method.
</span><span class="cx"> """
</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"> """
</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("method", ("",))
</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"> "Invalid method query parameter",
</span><span class="cx"> ))
</span><span class="cx"> method = method[0]
</span><del>-
</del><ins>+
</ins><span class="cx"> action = {
</span><span class="cx"> "list" : self.doPOSTList,
</span><span class="cx"> "get" : self.doPOSTGet,
</span><span class="cx"> "expand" : 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, "supported-method"),
</span><span class="cx"> "Unknown method query parameter",
</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"> """
</span><span class="cx"> Return a list of all timezones known to the server.
</span><span class="cx"> """
</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"> """
</span><span class="cx"> Return the specified timezone data.
</span><span class="cx"> """
</span><del>-
</del><ins>+
</ins><span class="cx"> tzid = request.args.get("tzid", ())
</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("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
</span><span class="cx"> return response
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def doPOSTExpand(self, request):
</span><span class="cx"> """
</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("start", ())
</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("end", ())
</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 <= 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("Invalid TimezoneService mode: %s" % (config.TimezoneService.Mode,))
</span><span class="cx">
</span><ins>+ self.formats = []
+ self.formats.append("text/calendar")
+ self.formats.append("text/plain")
+ if config.EnableJSONData:
+ self.formats.append("application/calendar+json")
</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, "timezones.xml")
</span><span class="lines">@@ -268,7 +274,7 @@
</span><span class="cx"> {
</span><span class="cx"> "name": "get",
</span><span class="cx"> "parameters": [
</span><del>- {"name": "format", "required": False, "multi": False, "values": ["text/calendar", "text/plain", ], },
</del><ins>+ {"name": "format", "required": False, "multi": False, "values": self.formats, },
</ins><span class="cx"> {"name": "tzid", "required": True, "multi": 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("format", ("text/calendar",))
</span><del>- if len(format) != 1 or format[0] not in ("text/calendar", "text/plain",):
</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 != "text/plain" 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) > 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) > 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"> """
</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"> """
</span><span class="cx">
</span><del>- self.dtstamp = PyCalendarDateTime.getNowUTC().getXMLText()
</del><ins>+ self.dtstamp = DateTime.getNowUTC().getXMLText()
</ins><span class="cx"> self._scanTZs("")
</span><span class="cx"> self._dumpTZs()
</span><span class="cx">
</span><span class="lines">@@ -672,7 +678,7 @@
</span><span class="cx"> """
</span><span class="cx"> Update existing DB info by comparing md5's.
</span><span class="cx"> """
</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("", 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("Invalid calendar data for tzid: %s" % (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):
+ """
+ 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}
+ """
+
+ # 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("/")[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 = "%s/%s" % (content_type.mediaType, content_type.mediaSubtype,)
+ if ctype in allowedTypes:
+ if qval > result_qval:
+ result = ctype
+ result_qval = qval
+
+ # Subtype wildcard match
+ elif content_type.mediaType != "*" and content_type.mediaSubtype == "*":
+ if content_type.mediaType in toptypes:
+ if qval > result_qval:
+ result = toptypes[content_type.mediaType]
+ result_qval = qval
+
+ # Full wildcard match
+ elif content_type.mediaType == "*" and content_type.mediaSubtype == "*":
+ if qval > 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"> """
</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("utf-8")
</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 "<%s: %r: %r>" % (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 "<%s: %r: %r>" % (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 < other_name: return True
- if my_name > other_name: return False
</del><ins>+ if my_name < other_name:
+ return True
+ if my_name > other_name:
+ return False
</ins><span class="cx">
</span><span class="cx"> return self.value() < 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"> """
</span><span class="cx"> Duplicate this object and all its contents.
</span><span class="lines">@@ -105,35 +133,45 @@
</span><span class="cx"> """
</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"> """
</span><span class="cx"> Returns a set containing parameter names for this property.
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</span><span class="cx"> X{vCard} component.
</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 = ["text/vcard"]
+ if config.EnableJSONData:
+ cls.allowedTypesList.append("application/vcard+json")
+ return cls.allowedTypesList
+
+
+ @classmethod
+ def allFromString(clazz, string, format=None):
</ins><span class="cx"> """
</span><span class="cx"> FIXME: Just default to reading a single VCARD - actually need more
</span><span class="cx"> """
</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"> """
</span><span class="cx"> FIXME: Just default to reading a single VCARD - actually need more
</span><span class="cx"> """
</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("%s" % (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"> """
</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"> """
</span><del>- if type(string) is unicode:
- string = string.encode("utf-8")
- else:
- # Valid utf-8 please
- string.decode("utf-8")
</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):
+ """
+ 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}.
+ """
+ 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"> """
</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"> """
</span><del>- cal = Card()
</del><ins>+
+ if isstream:
+ pass
+ else:
+ if type(data) is unicode:
+ data = data.encode("utf-8")
+ else:
+ # Valid utf-8 please
+ data.decode("utf-8")
+
+ # No BOMs please
+ if data[:3] == codecs.BOM_UTF8:
+ data = data[3:]
+
+ errmsg = "Unknown"
</ins><span class="cx"> try:
</span><del>- result = cal.parse(stream)
- except PyCalendarError:
</del><ins>+ result = Card.parseData(data, format)
+ except ErrorBase, e:
+ errmsg = "%s: %s" % (e.mReason, e.mData,)
</ins><span class="cx"> result = None
</span><span class="cx"> if not result:
</span><del>- stream.seek(0)
- raise InvalidVCardDataError("%s" % (stream.read(),))
- return clazz(None, pycard=cal)
</del><ins>+ if isstream:
+ data.seek(0)
+ data = data.read()
+ raise InvalidVCardDataError("%s\n%s" % (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"> """
</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"> """
</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["pycard"]
</span><span class="cx">
</span><span class="cx"> if pyobj is not None:
</span><del>- if not isinstance(pyobj, PyCalendarComponentBase):
- raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
</del><ins>+ if not isinstance(pyobj, ComponentBase):
+ raise TypeError("Not a ComponentBase: %r" % (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("VCards have no child components")
</span><span class="cx">
</span><del>- def __str__ (self): return str(self._pycard)
- def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, str(self._pycard))
</del><span class="cx">
</span><ins>+ def __str__(self):
+ return str(self._pycard)
+
+
+ def __repr__(self):
+ return "<%s: %r>" % (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):
+ """
+ Return text representation
+ """
+ assert self.name() == "VCARD", "Must be a VCARD: %r" % (self,)
+
+ result = self._pycard.getText(format)
+ if result is None:
+ raise ValueError("Unknown format requested for address data.")
+ 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"> """
</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"> """
</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"> """
</span><span class="cx"> Duplicate this object and all its contents.
</span><span class="lines">@@ -331,6 +436,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</span><span class="cx"> properties = tuple(self.properties(name))
</span><del>- if len(properties) == 1: return properties[0]
- if len(properties) > 1: raise InvalidVCardDataError("More than one %s property in component %r" % (name, self))
</del><ins>+ if len(properties) == 1:
+ return properties[0]
+ if len(properties) > 1:
+ raise InvalidVCardDataError("More than one %s property in component %r" % (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"> """
</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"> """
</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"> """
</span><span class="cx"> remove all properties with name
</span><span class="lines">@@ -400,6 +513,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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("X-ADDRESSBOOKSERVER-MEMBER"))]
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def validVCardData(self, doFix=True, doRaise=True):
</span><span class="cx"> """
</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("vCard data had unfixable problems:\n %s" % ("\n ".join(unfixed),))
</span><span class="cx"> if doRaise:
</span><del>- raise InvalidVCardDataError("Calendar data had unfixable problems:\n %s" % ("\n ".join(unfixed),))
</del><ins>+ raise InvalidVCardDataError("Address data had unfixable problems:\n %s" % ("\n ".join(unfixed),))
</ins><span class="cx"> if fixed:
</span><span class="cx"> log.debug("vCard data had fixable problems:\n %s" % ("\n ".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"> """
</span><span class="cx"> @raise ValueError: if the given vcard data is not valid.
</span><span class="cx"> """
</span><del>- if self.name() != "VCARD": raise InvalidVCardDataError("Not a vcard")
</del><ins>+ if self.name() != "VCARD":
+ raise InvalidVCardDataError("Not a vcard")
</ins><span class="cx">
</span><span class="cx"> version = self.propertyValue("VERSION")
</span><span class="cx"> if version != "3.0":
</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"> """
</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("Ignoring file '%s' because it is not a %s file" % (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, "utf-8")
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> def writeXML(xmlfile, root):
</span><del>-
</del><ins>+
</ins><span class="cx"> data = """<?xml version="1.0" encoding="utf-8"?>
</span><span class="cx"> <!DOCTYPE %s SYSTEM "%s.dtd">
</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, "w") 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 = "calendars"
</span><span class="cx"> _notifierPrefix = "CalDAV"
</span><span class="cx">
</span><ins>+ _componentCalendarName = {
+ "VEVENT": "calendar",
+ "VTODO": "tasks",
+ "VJOURNAL": "journals",
+ "VAVAILABILITY": "available",
+ "VPOLL": "polls",
+ }
+
</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("calendar")
- 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("VEVENT")
</del><ins>+ for name in ical.allowedStoreComponents:
+ cal = self.createCalendarWithName(self._componentCalendarName[name])
+ cal.setSupportedComponents(name)
+ props = cal.properties()
+ if name not in ("VEVENT", "VAVAILABILITY",):
+ props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Transparent())
+ else:
+ props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Opaque())
+ else:
+ cal = self.createCalendarWithName("calendar")
</ins><span class="cx">
</span><del>- # Default tasks
- defaultTasks = self.createCalendarWithName("tasks")
- props = defaultTasks.properties()
- defaultTasks.setSupportedComponents("VTODO")
-
</del><span class="cx"> self.createCalendarWithName("inbox")
</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 > 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 > (PyCalendarDateTime.getToday() +
- PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
</del><ins>+ if expand > (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 "infinity"
</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"> """
</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(), "user01")
</span><span class="cx"> result = (yield scheduler.doSchedulingViaPOST("mailto:user01@example.com", ["mailto:user01@example.com", ], 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]), "mailto:user01@example.com")
- self.assertTrue(str(result.responses[0].children[1]).startswith("2"))
- self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace("\n", "\r\n"))
</del><ins>+ self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01@example.com")
+ self.assertTrue(str(result.responses[0].reqstatus).startswith("2"))
+ self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace("\n", "\r\n"))
</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(), "user01")
</span><span class="cx"> result = (yield scheduler.doSchedulingViaPOST("mailto:user01@example.com", ["mailto:user01@example.com", ], 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]), "mailto:user01@example.com")
- self.assertTrue(str(result.responses[0].children[1]).startswith("2"))
- self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace("\n", "\r\n"))
</del><ins>+ self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01@example.com")
+ self.assertTrue(str(result.responses[0].reqstatus).startswith("2"))
+ self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace("\n", "\r\n"))
</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(), "user01")
</span><span class="cx"> result = (yield scheduler.doSchedulingViaPOST("mailto:user01@example.com", ["mailto:user01@example.com", ], 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]), "mailto:user01@example.com")
- self.assertTrue(str(result.responses[0].children[1]).startswith("2"))
- self.assertEqual(normalizeiCalendarText(str(result.responses[0].children[2].children[0])), data_reply.replace("\n", "\r\n"))
</del><ins>+ self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01@example.com")
+ self.assertTrue(str(result.responses[0].reqstatus).startswith("2"))
+ self.assertEqual(normalizeiCalendarText(str(result.responses[0].calendar)), data_reply.replace("\n", "\r\n"))
</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) <= 0 and compareDateTime(timerange.start, cached_start) >= 0:
</span><span class="lines">@@ -187,8 +187,8 @@
</span><span class="cx"> logItems["fb-uncached"] = logItems.get("fb-uncached", 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) >= 0 and compareDateTime(timerange.end, cache_end) <= 0:
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx"> logItems["fb-cached"] = logItems.get("fb-cached", 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"> """
</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"> """
</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("DURATION"):
</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), "FREEBUSY property does not contain a list of values: %r" % (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 < 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 < 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("BUSYTYPE")
</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("DURATION"):
</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("DTSTART", timerange.start))
</span><span class="cx"> fb.addProperty(Property("DTEND", timerange.end))
</span><del>- fb.addProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ fb.addProperty(Property("DTSTAMP", DateTime.getNowUTC()))
</ins><span class="cx"> if len(fbinfo[0]) != 0:
</span><span class="cx"> fb.addProperty(Property("FREEBUSY", fbinfo[0], {"FBTYPE": "BUSY"}))
</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("X-CALENDARSERVER-DTSTAMP", PyCalendarDateTime.getNowUTC().getText())
</del><ins>+ serverAttendee.setParameter("X-CALENDARSERVER-DTSTAMP", 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() == "VALARM":
</span><span class="cx"> serverComponent.addComponent(comp)
</span><span class="cx">
</span><ins>+ # VPOLL
+ if serverComponent.name() == "VPOLL":
+ 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("POLL-ITEM-ID")
+ 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("POLL-ITEM-ID")
+ 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 ("RESPONSE",):
+ 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 ("VEVENT", "VJOURNAL",):
</del><ins>+ if component.name() in ("VEVENT", "VJOURNAL", "VPOLL"):
</ins><span class="cx"> dtstart = component.getProperty("DTSTART")
</span><span class="cx"> dtend = component.getProperty("DTEND")
</span><span class="cx"> duration = component.getProperty("DURATION")
</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("DURATION")
</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("DUE")
</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("RDATE")
</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("EXDATE")
</span><span class="cx"> comp.removePropertyParameters("ORGANIZER", ("SCHEDULE-STATUS",))
</span><span class="cx"> comp.removePropertyParameters("ATTENDEE", ("SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
</span><ins>+ comp.removePropertyParameters("VOTER", ("SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
</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"> """
</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"> """
</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"> """
</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("METHOD")
</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"> "1.2;Scheduling message has been delivered",
</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"> "3.7;Invalid Calendar User",
</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("\n", "\r\n")),
</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("\n", "\r\n")),
</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("\n", "\r\n")),
</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 "ORGANIZER"
</ins><span class="cx"> for item in response.responses:
</span><del>- assert isinstance(item, caldavxml.Response), "Wrong element in response"
- 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"> "SCHEDULE-STATUS",
</span><span class="cx"> status.split(";")[0],
</span><del>- "ATTENDEE" if is_organizer else "ORGANIZER",
</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"> """
</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(**{
+ "content-type": "text/calendar",
+ "version": "2.0",
+ })
+ )
+ if config.EnableJSONData:
+ dataTypes.append(
+ ischedulexml.CalendarDataType(**{
+ "content-type": "application/calendar+json",
+ "version": "2.0",
+ })
+ )
</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="VFREEBUSY"
</span><span class="cx"> ),
</span><span class="cx"> ),
</span><del>- ischedulexml.CalendarDataTypes(
- ischedulexml.CalendarDataType(**{
- "content-type": "text/calendar",
- "version": "2.0",
- }),
- ),
</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("content-type")
+ format = self.determineType(contentType)
+
+ if format is None:
+ msg = "MIME type %s not allowed in iSchedule request" % (contentType,)
+ self.log.error(msg)
+ raise HTTPError(scheduler.errorResponse(
+ responsecode.FORBIDDEN,
+ (ischedule_namespace, "invalid-calendar-data-type"),
+ 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):
+ """
+ Determine if the supplied content-type is valid for storing and return the matching PyCalendar type.
+ """
+ format = None
+ if content_type is not None:
+ format = "%s/%s" % (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("originator")
</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"> """
</span><span class="cx"> Carry out iSchedule specific processing.
</span><span class="cx"> """
</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', ("F"))[0] == "T":
</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"> "Originator": ("mailto:wsanchez@example.com",),
</span><span class="cx"> "Recipient": ("mailto:cdaboo@example.com",),
</span><ins>+ "Content-Type": "text/calendar",
</ins><span class="cx"> }),
</span><span class="cx"> content="""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"> "Originator": ("mailto:user01@example.org",),
</span><span class="cx"> "Recipient": ("mailto:user02@example.com",),
</span><ins>+ "Content-Type": ("text/calendar",)
</ins><span class="cx"> }),
</span><span class="cx"> content="""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"> """
</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 = "2.0"
</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("ATTENDEE"))
</del><ins>+ attendees = tuple(from_component.properties(from_component.recipientPropertyName()))
</ins><span class="cx"> if len(attendees) != 1:
</span><span class="cx"> log.error("There must be one and only one ATTENDEE property in a REPLY\n%s" % (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"> "X-CALENDARSERVER-ATTENDEE-REF": attendee.value(),
</span><del>- "X-CALENDARSERVER-DTSTAMP": PyCalendarDateTime.getNowUTC().getText(),
</del><ins>+ "X-CALENDARSERVER-DTSTAMP": 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("X-CALENDARSERVER-ATTENDEE-REF", attendee.value())
</span><del>- private_comment.setParameter("X-CALENDARSERVER-DTSTAMP", PyCalendarDateTime.getNowUTC().getText())
</del><ins>+ private_comment.setParameter("X-CALENDARSERVER-DTSTAMP", 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() == "VPOLL":
+ # 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):
+ """
+ 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}
+ """
+
+ responses = {}
+ for prop in from_component.properties("POLL-ITEM-ID"):
+ responses[prop.value()] = prop
+
+ for component in to_component.subcomponents():
+ if component.name() in ignoredComponents:
+ continue
+ poll_item_id = component.propertyValue("POLL-ITEM-ID")
+ 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("RESPONSE"):
+ if voter is not None:
+ component.removeProperty(voter)
+ continue
+
+ # Add or update voter
+ if voter is None:
+ voter = Property("VOTER", attendee.value())
+ component.addProperty(voter)
+ voter.setParameter("RESPONSE", responses[poll_item_id].parameterValue("RESPONSE"))
+
+
+ @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"> """
</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("DTSTAMP", PyCalendarDateTime.getNowUTC()))
</del><ins>+ itip.replacePropertyInAllComponents(Property("DTSTAMP", 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"> "EXDATE",
</span><span class="cx"> "ORGANIZER",
</span><span class="cx"> "ATTENDEE",
</span><ins>+ "VOTER",
</ins><span class="cx"> "X-CALENDARSERVER-PRIVATE-COMMENT",
</span><span class="cx"> "SUMMARY",
</span><span class="cx"> "LOCATION",
</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() == "VPOLL":
+ 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):
+ """
+ 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}
+ """
+
+ for component in tuple(vpoll.subcomponents()):
+ if component.name() in ignoredComponents:
+ continue
+ poll_item_id = component.propertyValue("POLL-ITEM-ID")
+ if poll_item_id is None:
+ continue
+ voter = component.getVoterProperty((attendee,))
+ if voter is not None and voter.hasParameter("RESPONSE"):
+ vpoll.addProperty(Property("POLL-ITEM-ID", poll_item_id, {"RESPONSE": voter.parameterValue("RESPONSE")}))
+ vpoll.removeComponent(component)
+
+
+ @staticmethod
</ins><span class="cx"> def prepareSchedulingMessage(itip, reply=False):
</span><span class="cx"> """
</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("ATTENDEE", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND", "X-CALENDARSERVER-DTSTAMP",))
</span><ins>+ itip.removePropertyParameters("VOTER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND", "X-CALENDARSERVER-DTSTAMP",))
</ins><span class="cx"> itip.removePropertyParameters("ORGANIZER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
</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"> """
</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(
+ "ScheduleResonseDetails",
+ ["recipient", "reqstatus", "calendar", "error", "message", ]
+ )
+
</ins><span class="cx"> def __init__(self, method, success_response, recipient_mapper=None):
</span><span class="cx"> """
</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 > 400: # Error codes only
</span><span class="cx"> self.log.error("Error during %s for %s: %s" % (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"> """
</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"> """
</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"> """
</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"> "#1.3 With single busy time",
</span><span class="cx"> [
</span><del>- [PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"), ],
</del><ins>+ [Period.parseText("20080601T120000Z/20080601T130000Z"), ],
</ins><span class="cx"> [],
</span><span class="cx"> [],
</span><span class="cx"> ],
</span><span class="lines">@@ -120,8 +120,8 @@
</span><span class="cx"> "#1.4 With multiple busy time",
</span><span class="cx"> [
</span><span class="cx"> [
</span><del>- PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
- PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
</del><ins>+ Period.parseText("20080601T120000Z/20080601T130000Z"),
+ Period.parseText("20080601T140000Z/20080601T150000Z"),
</ins><span class="cx"> ],
</span><span class="cx"> [],
</span><span class="cx"> [],
</span><span class="lines">@@ -148,10 +148,10 @@
</span><span class="cx"> "#1.5 With multiple busy time, some overlap",
</span><span class="cx"> [
</span><span class="cx"> [
</span><del>- PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
- PyCalendarPeriod.parseText("20080601T123000Z/20080601T133000Z"),
- PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
- PyCalendarPeriod.parseText("20080601T150000Z/20080601T160000Z"),
</del><ins>+ Period.parseText("20080601T120000Z/20080601T130000Z"),
+ Period.parseText("20080601T123000Z/20080601T133000Z"),
+ Period.parseText("20080601T140000Z/20080601T150000Z"),
+ Period.parseText("20080601T150000Z/20080601T160000Z"),
</ins><span class="cx"> ],
</span><span class="cx"> [],
</span><span class="cx"> [],
</span><span class="lines">@@ -178,14 +178,14 @@
</span><span class="cx"> "#1.6 With all busy time types",
</span><span class="cx"> [
</span><span class="cx"> [
</span><del>- PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
- PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
</del><ins>+ Period.parseText("20080601T120000Z/20080601T130000Z"),
+ Period.parseText("20080601T140000Z/20080601T150000Z"),
</ins><span class="cx"> ],
</span><span class="cx"> [
</span><del>- PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
</del><ins>+ Period.parseText("20080601T140000Z/20080601T150000Z"),
</ins><span class="cx"> ],
</span><span class="cx"> [
</span><del>- PyCalendarPeriod.parseText("20080601T160000Z/20080601T170000Z"),
</del><ins>+ Period.parseText("20080601T160000Z/20080601T170000Z"),
</ins><span class="cx"> ],
</span><span class="cx"> ],
</span><span class="cx"> "20080601T000000Z",
</span><span class="lines">@@ -211,7 +211,7 @@
</span><span class="cx"> (
</span><span class="cx"> "#1.7 With single busy time and event details",
</span><span class="cx"> [
</span><del>- [PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"), ],
</del><ins>+ [Period.parseText("20080601T120000Z/20080601T130000Z"), ],
</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("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</del><ins>+ self.assertEqual(fbinfo[0], [Period.parseText("%s/%s" % (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("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
</del><ins>+ self.assertEqual(fbinfo[0], [Period.parseText("%s/%s" % (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["now"] = 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user1@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user1@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user1@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user1@example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user1@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user1@example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user1@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user1@example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user1@example.com", DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><span class="cx"> ("mailto:user3@example.com", None),
</span><del>- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user3@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user1@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user3@example.com", 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"> """,
</span><span class="cx"> (
</span><span class="cx"> ("mailto:user3@example.com", None),
</span><del>- ("mailto:user4@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user4@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user4@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user4@example.com", 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"> """,
</span><span class="cx"> (
</span><del>- ("mailto:user1@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user2@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
- ("mailto:user4@example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
</del><ins>+ ("mailto:user1@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user2@example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+ ("mailto:user4@example.com", 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"> """,
</span><span class="cx"> ("mailto:user2@example.com",),
</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"> """,
</span><span class="cx"> ("mailto:user2@example.com",),
</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"> """,
</span><span class="cx"> "",
</span><span class="cx"> ("mailto:user2@example.com",),
</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"> """
</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 = """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("SQL.calhome", pickle=True, key_normalization=False)
</span><span class="cx">
</span><ins>+ _componentCalendarName = {
+ "VEVENT": "calendar",
+ "VTODO": "tasks",
+ "VJOURNAL": "journals",
+ "VAVAILABILITY": "available",
+ "VPOLL": "polls",
+ }
+
+ _componentDefaultColumn = {
+ "VEVENT": schema.CALENDAR_HOME_METADATA.DEFAULT_EVENTS,
+ "VTODO": schema.CALENDAR_HOME_METADATA.DEFAULT_TASKS,
+ "VPOLL": schema.CALENDAR_HOME_METADATA.DEFAULT_POLLS,
+ }
+
+ _componentDefaultAttribute = {
+ "VEVENT": "_default_events",
+ "VTODO": "_default_tasks",
+ "VPOLL": "_default_polls",
+ }
+
</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 (
- "_default_events",
- "_default_tasks",
</del><ins>+ default_attributes = tuple([cls._componentDefaultAttribute[name] for name in sorted(cls._componentDefaultAttribute.keys())])
+ return default_attributes + (
</ins><span class="cx"> "_alarm_vevent_timed",
</span><span class="cx"> "_alarm_vevent_allday",
</span><span class="cx"> "_alarm_vtodo_timed",
</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("calendar")
-
</del><span class="cx"> # Check whether components type must be separate
</span><span class="cx"> if config.RestrictCalendarsToOneComponentType:
</span><del>- yield defaultCal.setSupportedComponents("VEVENT")
- yield self.setDefaultCalendar(defaultCal, False)
-
- # Default tasks
- defaultTasks = yield self.createCalendarWithName("tasks")
- yield defaultTasks.setSupportedComponents("VTODO")
- 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 ("VEVENT", "VAVAILABILITY",):
+ 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("calendar")
+ for name in ical.allowedStoreComponents:
+ yield self.setDefaultCalendar(cal, name)
</ins><span class="cx">
</span><span class="cx"> inbox = yield self.createCalendarWithName("inbox")
</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("VEVENT", "calendar")
- yield _requireCalendarWithType("VTODO", "tasks")
</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"> """
</span><del>- First see if default provisioned calendar exists in the calendar home and pick that. Otherwise
- pick another from the calendar home.
- """
-
- componentType = "VTODO" if tasks else "VEVENT"
- test_name = "tasks" if tasks else "calendar"
-
- 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("No valid calendars to use as a default %s calendar." % (componentType,))
-
- yield self.setDefaultCalendar(defaultCalendar, tasks)
-
- returnValue(defaultCalendar)
-
-
- @inlineCallbacks
- def setDefaultCalendar(self, calendar, tasks=False):
- """
</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"> """
</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 = "VTODO" if tasks else "VEVENT"
- attribute_to_test = "_default_tasks" if tasks else "_default_events"
- 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"> """
</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 = "_default_tasks" if componentType == "VTODO" else "_default_events"
</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 = "%ss" % (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 == "VTODO")
</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"> """
</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, "_alarm_vevent_timed"),
</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 > 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 > (PyCalendarDateTime.getToday() +
- PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
</del><ins>+ if expand > (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, "UNKNOWN", isInboxItem, txn)
</span><span class="cx">
</span><span class="cx"> # Special - for unbounded recurrence we insert a value for "infinity"
</span><span class="lines">@@ -2470,8 +2459,8 @@
</span><span class="cx"> # We also need to add the "infinity" 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, "UNKNOWN", 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"> """
</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"> """
</span><span class="cx"> Return an iCalendar ATTACH property for this attachment.
</span><span class="cx"> """
</span><del>- attach = Property("ATTACH", "", valuetype=PyCalendarValue.VALUETYPE_URI)
</del><ins>+ attach = Property("ATTACH", "", 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"> """
</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"> """
</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 = """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"> "ATTACH",
</span><span class="cx"> "http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s" % (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"> "ATTACH",
</span><span class="cx"> "http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s" % (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("calendar_store")
</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("ho").child("me").children():
</span><span class="cx"> if not home.basename().startswith("."):
</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"> """
</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 = {"now": PyCalendarDateTime.getToday().getYear()}
</del><ins>+ self.nowYear = {"now": 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() == "inbox":
</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(("VEVENT", "VTODO",)))
</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(("VEVENT", "VTODO",)))
</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(("VEVENT", "VTODO",)))
</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("calendar_1")
</span><del>- yield home.setDefaultCalendar(calendar1, False)
</del><ins>+ yield home.setDefaultCalendar(calendar1, "VEVENT")
</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="home_defaults")
</span><span class="cx"> calendar1 = yield home.calendarWithName("calendar_1")
</span><span class="cx"> calendar2 = yield home.calendarWithName("calendar_1-vtodo")
</span><del>- yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, False), InvalidDefaultCalendar)
</del><ins>+ yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, "VEVENT"), 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="home_defaults")
</span><span class="cx"> calendar1 = yield home.calendarWithName("calendar_1")
</span><span class="cx"> calendar2 = yield home.calendarWithName("calendar_1-vtodo")
</span><del>- yield home.setDefaultCalendar(calendar2, True)
</del><ins>+ yield home.setDefaultCalendar(calendar2, "VTODO")
</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="home_defaults")
</span><span class="cx"> calendar1 = yield home.calendarWithName("inbox")
</span><del>- yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
</del><ins>+ yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, "VEVENT"), InvalidDefaultCalendar)
</ins><span class="cx"> yield self.commit()
</span><span class="cx">
</span><span class="cx"> home = yield self.homeUnderTest(name="home_defaults")
</span><span class="cx"> home_other = yield self.homeUnderTest(name="home_splits")
</span><span class="cx"> calendar1 = yield home_other.calendarWithName("calendar_1")
</span><del>- yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
</del><ins>+ yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, "VEVENT"), 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, ["indexing.ics"])
</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, ["indexing.ics"])
</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, ["indexing.ics"])
</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, ["indexing.ics"])
</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["now"] = 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"> "inbox": {},
</span><span class="cx"> # XXX: implementation is configuration-sensitive regarding the
</span><span class="cx"> # 'tasks' calendar and it shouldn't be.
</span><del>- "tasks": {}
</del><ins>+ "tasks": {},
+ "polls": {},
</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 = {"1.ics": self.sampleEvent("uid1")}
</span><span class="cx"> if c2 is None:
</span><span class="cx"> c2 = {"2.ics": self.sampleEvent("uid2")}
</span><del>- defaults = {"calendar": {}, "inbox": {}, "tasks": {}}
</del><ins>+ defaults = {"calendar": {}, "inbox": {}, "tasks": {}, "polls": {}}
</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"> """
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> if not merge:
</span><del>- yield outHome.removeCalendarWithName("calendar")
</del><span class="cx"> if config.RestrictCalendarsToOneComponentType:
</span><del>- yield outHome.removeCalendarWithName("tasks")
</del><ins>+ for name in ical.allowedStoreComponents:
+ yield outHome.removeCalendarWithName(outHome._componentCalendarName[name])
+ else:
+ yield outHome.removeCalendarWithName("calendar")
</ins><span class="cx"> yield outHome.removeCalendarWithName("inbox")
</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"> """
</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"> """
</span><span class="cx"> Return up to the oldest batchSize events which exist completely earlier
</span><del>- than "cutoff" (PyCalendarDateTime)
</del><ins>+ than "cutoff" (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 < truncateLowerLimit:
</span><span class="cx"> raise ValueError("Cannot query events older than %s" % (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 < truncateLowerLimit:
</span><span class="cx"> raise ValueError("Cannot query events older than %s" % (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 > 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 >= 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 < 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"> "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" nclob default null,
</span><span class="cx"> "ALARM_VEVENT_ALLDAY" nclob default null,
</span><span class="cx"> "ALARM_VTODO_TIMED" nclob default null,
</span><span class="lines">@@ -365,7 +366,7 @@
</span><span class="cx"> "VALUE" 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 (
- "HOSTNAME" nvarchar2(255),
- "PID" integer not null,
- "PORT" integer not null,
- "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
- primary key("HOSTNAME", "PORT")
-);
-
-create table NAMED_LOCK (
- "LOCK_NAME" nvarchar2(255) primary key
-);
-
-create table CALENDAR_HOME (
- "RESOURCE_ID" integer primary key,
- "OWNER_UID" nvarchar2(255) unique,
- "DATAVERSION" integer default 0 not null
-);
-
-create table CALENDAR (
- "RESOURCE_ID" integer primary key
-);
-
-create table CALENDAR_HOME_METADATA (
- "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
- "QUOTA_USED_BYTES" integer default 0 not null,
- "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
- "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
- "ALARM_VEVENT_TIMED" nclob default null,
- "ALARM_VEVENT_ALLDAY" nclob default null,
- "ALARM_VTODO_TIMED" nclob default null,
- "ALARM_VTODO_ALLDAY" nclob default null,
- "AVAILABILITY" nclob default null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_METADATA (
- "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
- "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table NOTIFICATION_HOME (
- "RESOURCE_ID" integer primary key,
- "OWNER_UID" nvarchar2(255) unique
-);
-
-create table NOTIFICATION (
- "RESOURCE_ID" integer primary key,
- "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
- "NOTIFICATION_UID" nvarchar2(255),
- "XML_TYPE" nvarchar2(255),
- "XML_DATA" nclob,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- "TRANSP" integer default 0 not null,
- "ALARM_VEVENT_TIMED" nclob default null,
- "ALARM_VEVENT_ALLDAY" nclob default null,
- "ALARM_VTODO_TIMED" nclob default null,
- "ALARM_VTODO_ALLDAY" nclob default null,
- "TIMEZONE" nclob default null,
- primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
- unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
-);
-
-create table CALENDAR_BIND_MODE (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "RESOURCE_ID" integer primary key,
- "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "ICALENDAR_TEXT" nclob,
- "ICALENDAR_UID" nvarchar2(255),
- "ICALENDAR_TYPE" nvarchar2(255),
- "ATTACHMENTS_MODE" integer default 0 not null,
- "DROPBOX_ID" nvarchar2(255),
- "ORGANIZER" nvarchar2(255),
- "RECURRANCE_MIN" date,
- "RECURRANCE_MAX" date,
- "ACCESS" integer default 0 not null,
- "SCHEDULE_OBJECT" integer default 0,
- "SCHEDULE_TAG" nvarchar2(36) default null,
- "SCHEDULE_ETAGS" nclob default null,
- "PRIVATE_COMMENTS" integer default 0 not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
-);
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MO (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "INSTANCE_ID" integer primary key,
- "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" integer not null,
- "START_DATE" timestamp not null,
- "END_DATE" timestamp not null,
- "FBTYPE" integer not null,
- "TRANSPARENT" integer not null
-);
-
-create table FREE_BUSY_TYPE (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
- "USER_ID" nvarchar2(255),
- "TRANSPARENT" integer not null
-);
-
-create table ATTACHMENT (
- "ATTACHMENT_ID" integer primary key,
- "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
- "DROPBOX_ID" nvarchar2(255),
- "CONTENT_TYPE" nvarchar2(255),
- "SIZE" integer not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "PATH" nvarchar2(1024)
-);
-
-create table ATTACHMENT_CALENDAR_OBJECT (
- "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
- "MANAGED_ID" nvarchar2(255),
- "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
- primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
- unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
-);
-
-create table RESOURCE_PROPERTY (
- "RESOURCE_ID" integer not null,
- "NAME" nvarchar2(255),
- "VALUE" nclob,
- "VIEWER_UID" nvarchar2(255),
- primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
-);
-
-create table ADDRESSBOOK_HOME (
- "RESOURCE_ID" integer primary key,
- "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
- "OWNER_UID" nvarchar2(255) unique,
- "DATAVERSION" integer default 0 not null
-);
-
-create table ADDRESSBOOK_HOME_METADATA (
- "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
- "QUOTA_USED_BYTES" integer default 0 not null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
-);
-
-create table ADDRESSBOOK_OBJECT (
- "RESOURCE_ID" integer primary key,
- "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "VCARD_TEXT" nclob,
- "VCARD_UID" nvarchar2(255),
- "KIND" integer not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
-);
-
-create table ADDRESSBOOK_OBJECT_KIND (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
- "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
- primary key("GROUP_ID", "MEMBER_ID")
-);
-
-create table ABO_FOREIGN_MEMBERS (
- "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
- "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "MEMBER_ADDRESS" nvarchar2(255),
- primary key("GROUP_ID", "MEMBER_ADDRESS")
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
-);
-
-create table CALENDAR_OBJECT_REVISIONS (
- "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
- "CALENDAR_RESOURCE_ID" integer references CALENDAR,
- "CALENDAR_NAME" nvarchar2(255) default null,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null
-);
-
-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" nvarchar2(255) default null,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null
-);
-
-create table NOTIFICATION_OBJECT_REVISIONS (
- "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null,
- unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
-);
-
-create table APN_SUBSCRIPTIONS (
- "TOKEN" nvarchar2(255),
- "RESOURCE_KEY" nvarchar2(255),
- "MODIFIED" integer not null,
- "SUBSCRIBER_GUID" nvarchar2(255),
- "USER_AGENT" nvarchar2(255) default null,
- "IP_ADDR" nvarchar2(255) default null,
- primary key("TOKEN", "RESOURCE_KEY")
-);
-
-create table IMIP_TOKENS (
- "TOKEN" nvarchar2(255),
- "ORGANIZER" nvarchar2(255),
- "ATTENDEE" nvarchar2(255),
- "ICALUID" nvarchar2(255),
- "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- primary key("ORGANIZER", "ATTENDEE", "ICALUID")
-);
-
-create table IMIP_INVITATION_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "FROM_ADDR" nvarchar2(255),
- "TO_ADDR" nvarchar2(255),
- "ICALENDAR_TEXT" nclob
-);
-
-create table IMIP_POLLING_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table IMIP_REPLY_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "ORGANIZER" nvarchar2(255),
- "ATTENDEE" nvarchar2(255),
- "ICALENDAR_TEXT" nclob
-);
-
-create table PUSH_NOTIFICATION_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "PUSH_ID" nvarchar2(255)
-);
-
-create table GROUP_CACHER_POLLING_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
-);
-
-create table CALENDARSERVER (
- "NAME" nvarchar2(255) primary key,
- "VALUE" 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 (
+ "HOSTNAME" nvarchar2(255),
+ "PID" integer not null,
+ "PORT" integer not null,
+ "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
+ primary key("HOSTNAME", "PORT")
+);
+
+create table NAMED_LOCK (
+ "LOCK_NAME" nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table CALENDAR (
+ "RESOURCE_ID" integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
+ "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "AVAILABILITY" nclob default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
+ "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+ "RESOURCE_ID" integer primary key,
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
+ "NOTIFICATION_UID" nvarchar2(255),
+ "XML_TYPE" nvarchar2(255),
+ "XML_DATA" nclob,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ "TRANSP" integer default 0 not null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "TIMEZONE" nclob default null,
+ primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
+ unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
+);
+
+create table CALENDAR_BIND_MODE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "RESOURCE_ID" integer primary key,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob,
+ "ICALENDAR_UID" nvarchar2(255),
+ "ICALENDAR_TYPE" nvarchar2(255),
+ "ATTACHMENTS_MODE" integer default 0 not null,
+ "DROPBOX_ID" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "RECURRANCE_MIN" date,
+ "RECURRANCE_MAX" date,
+ "ACCESS" integer default 0 not null,
+ "SCHEDULE_OBJECT" integer default 0,
+ "SCHEDULE_TAG" nvarchar2(36) default null,
+ "SCHEDULE_ETAGS" nclob default null,
+ "PRIVATE_COMMENTS" integer default 0 not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "INSTANCE_ID" integer primary key,
+ "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" integer not null,
+ "START_DATE" timestamp not null,
+ "END_DATE" timestamp not null,
+ "FBTYPE" integer not null,
+ "TRANSPARENT" integer not null
+);
+
+create table FREE_BUSY_TYPE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
+ "USER_ID" nvarchar2(255),
+ "TRANSPARENT" integer not null
+);
+
+create table ATTACHMENT (
+ "ATTACHMENT_ID" integer primary key,
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "DROPBOX_ID" nvarchar2(255),
+ "CONTENT_TYPE" nvarchar2(255),
+ "SIZE" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PATH" nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+ "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
+ "MANAGED_ID" nvarchar2(255),
+ "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+ primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
+ unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
+);
+
+create table RESOURCE_PROPERTY (
+ "RESOURCE_ID" integer not null,
+ "NAME" nvarchar2(255),
+ "VALUE" nclob,
+ "VIEWER_UID" nvarchar2(255),
+ primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
+);
+
+create table ADDRESSBOOK_HOME (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
+);
+
+create table ADDRESSBOOK_OBJECT (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "VCARD_TEXT" nclob,
+ "VCARD_UID" nvarchar2(255),
+ "KIND" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
+ primary key("GROUP_ID", "MEMBER_ID")
+);
+
+create table ABO_FOREIGN_MEMBERS (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ADDRESS" nvarchar2(255),
+ primary key("GROUP_ID", "MEMBER_ADDRESS")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "CALENDAR_RESOURCE_ID" integer references CALENDAR,
+ "CALENDAR_NAME" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+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" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null,
+ unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table APN_SUBSCRIPTIONS (
+ "TOKEN" nvarchar2(255),
+ "RESOURCE_KEY" nvarchar2(255),
+ "MODIFIED" integer not null,
+ "SUBSCRIBER_GUID" nvarchar2(255),
+ "USER_AGENT" nvarchar2(255) default null,
+ "IP_ADDR" nvarchar2(255) default null,
+ primary key("TOKEN", "RESOURCE_KEY")
+);
+
+create table IMIP_TOKENS (
+ "TOKEN" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALUID" nvarchar2(255),
+ "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ primary key("ORGANIZER", "ATTENDEE", "ICALUID")
+);
+
+create table IMIP_INVITATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "FROM_ADDR" nvarchar2(255),
+ "TO_ADDR" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table IMIP_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PUSH_ID" nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+ "NAME" nvarchar2(255) primary key,
+ "VALUE" 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 (
- "HOSTNAME" nvarchar2(255),
- "PID" integer not null,
- "PORT" integer not null,
- "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
- primary key("HOSTNAME", "PORT")
-);
-
-create table NAMED_LOCK (
- "LOCK_NAME" nvarchar2(255) primary key
-);
-
-create table CALENDAR_HOME (
- "RESOURCE_ID" integer primary key,
- "OWNER_UID" nvarchar2(255) unique,
- "DATAVERSION" integer default 0 not null
-);
-
-create table CALENDAR (
- "RESOURCE_ID" integer primary key
-);
-
-create table CALENDAR_HOME_METADATA (
- "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
- "QUOTA_USED_BYTES" integer default 0 not null,
- "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
- "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
- "ALARM_VEVENT_TIMED" nclob default null,
- "ALARM_VEVENT_ALLDAY" nclob default null,
- "ALARM_VTODO_TIMED" nclob default null,
- "ALARM_VTODO_ALLDAY" nclob default null,
- "AVAILABILITY" nclob default null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_METADATA (
- "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
- "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table NOTIFICATION_HOME (
- "RESOURCE_ID" integer primary key,
- "OWNER_UID" nvarchar2(255) unique
-);
-
-create table NOTIFICATION (
- "RESOURCE_ID" integer primary key,
- "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
- "NOTIFICATION_UID" nvarchar2(255),
- "XML_TYPE" nvarchar2(255),
- "XML_DATA" nclob,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- "TRANSP" integer default 0 not null,
- "ALARM_VEVENT_TIMED" nclob default null,
- "ALARM_VEVENT_ALLDAY" nclob default null,
- "ALARM_VTODO_TIMED" nclob default null,
- "ALARM_VTODO_ALLDAY" nclob default null,
- "TIMEZONE" nclob default null,
- primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
- unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
-);
-
-create table CALENDAR_BIND_MODE (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "RESOURCE_ID" integer primary key,
- "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "ICALENDAR_TEXT" nclob,
- "ICALENDAR_UID" nvarchar2(255),
- "ICALENDAR_TYPE" nvarchar2(255),
- "ATTACHMENTS_MODE" integer default 0 not null,
- "DROPBOX_ID" nvarchar2(255),
- "ORGANIZER" nvarchar2(255),
- "RECURRANCE_MIN" date,
- "RECURRANCE_MAX" date,
- "ACCESS" integer default 0 not null,
- "SCHEDULE_OBJECT" integer default 0,
- "SCHEDULE_TAG" nvarchar2(36) default null,
- "SCHEDULE_ETAGS" nclob default null,
- "PRIVATE_COMMENTS" integer default 0 not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
-);
-
-create table CALENDAR_OBJECT_ATTACHMENTS_MO (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "INSTANCE_ID" integer primary key,
- "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" integer not null,
- "START_DATE" timestamp not null,
- "END_DATE" timestamp not null,
- "FBTYPE" integer not null,
- "TRANSPARENT" integer not null
-);
-
-create table FREE_BUSY_TYPE (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
- "USER_ID" nvarchar2(255),
- "TRANSPARENT" integer not null
-);
-
-create table ATTACHMENT (
- "ATTACHMENT_ID" integer primary key,
- "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
- "DROPBOX_ID" nvarchar2(255),
- "CONTENT_TYPE" nvarchar2(255),
- "SIZE" integer not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "PATH" nvarchar2(1024)
-);
-
-create table ATTACHMENT_CALENDAR_OBJECT (
- "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
- "MANAGED_ID" nvarchar2(255),
- "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
- primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
- unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
-);
-
-create table RESOURCE_PROPERTY (
- "RESOURCE_ID" integer not null,
- "NAME" nvarchar2(255),
- "VALUE" nclob,
- "VIEWER_UID" nvarchar2(255),
- primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
-);
-
-create table ADDRESSBOOK_HOME (
- "RESOURCE_ID" integer primary key,
- "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
- "OWNER_UID" nvarchar2(255) unique,
- "DATAVERSION" integer default 0 not null
-);
-
-create table ADDRESSBOOK_HOME_METADATA (
- "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
- "QUOTA_USED_BYTES" integer default 0 not null,
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
-);
-
-create table ADDRESSBOOK_OBJECT (
- "RESOURCE_ID" integer primary key,
- "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "VCARD_TEXT" nclob,
- "VCARD_UID" nvarchar2(255),
- "KIND" integer not null,
- "MD5" nchar(32),
- "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
-);
-
-create table ADDRESSBOOK_OBJECT_KIND (
- "ID" integer primary key,
- "DESCRIPTION" 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 (
- "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
- "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
- primary key("GROUP_ID", "MEMBER_ID")
-);
-
-create table ABO_FOREIGN_MEMBERS (
- "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
- "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
- "MEMBER_ADDRESS" nvarchar2(255),
- primary key("GROUP_ID", "MEMBER_ADDRESS")
-);
-
-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" nvarchar2(255),
- "BIND_MODE" integer not null,
- "BIND_STATUS" integer not null,
- "BIND_REVISION" integer default 0 not null,
- "MESSAGE" nclob,
- primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
- unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
-);
-
-create table CALENDAR_OBJECT_REVISIONS (
- "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
- "CALENDAR_RESOURCE_ID" integer references CALENDAR,
- "CALENDAR_NAME" nvarchar2(255) default null,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null
-);
-
-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" nvarchar2(255) default null,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null
-);
-
-create table NOTIFICATION_OBJECT_REVISIONS (
- "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
- "RESOURCE_NAME" nvarchar2(255),
- "REVISION" integer not null,
- "DELETED" integer not null,
- unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
-);
-
-create table APN_SUBSCRIPTIONS (
- "TOKEN" nvarchar2(255),
- "RESOURCE_KEY" nvarchar2(255),
- "MODIFIED" integer not null,
- "SUBSCRIBER_GUID" nvarchar2(255),
- "USER_AGENT" nvarchar2(255) default null,
- "IP_ADDR" nvarchar2(255) default null,
- primary key("TOKEN", "RESOURCE_KEY")
-);
-
-create table IMIP_TOKENS (
- "TOKEN" nvarchar2(255),
- "ORGANIZER" nvarchar2(255),
- "ATTENDEE" nvarchar2(255),
- "ICALUID" nvarchar2(255),
- "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- primary key("ORGANIZER", "ATTENDEE", "ICALUID")
-);
-
-create table IMIP_INVITATION_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "FROM_ADDR" nvarchar2(255),
- "TO_ADDR" nvarchar2(255),
- "ICALENDAR_TEXT" nclob
-);
-
-create table IMIP_POLLING_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table IMIP_REPLY_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "ORGANIZER" nvarchar2(255),
- "ATTENDEE" nvarchar2(255),
- "ICALENDAR_TEXT" nclob
-);
-
-create table PUSH_NOTIFICATION_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "PUSH_ID" nvarchar2(255)
-);
-
-create table GROUP_CACHER_POLLING_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
-);
-
-create table CALENDAR_OBJECT_SPLITTER_WORK (
- "WORK_ID" integer primary key not null,
- "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
- "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
-);
-
-create table CALENDARSERVER (
- "NAME" nvarchar2(255) primary key,
- "VALUE" 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 (
+ "HOSTNAME" nvarchar2(255),
+ "PID" integer not null,
+ "PORT" integer not null,
+ "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
+ primary key("HOSTNAME", "PORT")
+);
+
+create table NAMED_LOCK (
+ "LOCK_NAME" nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table CALENDAR (
+ "RESOURCE_ID" integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
+ "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "AVAILABILITY" nclob default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
+ "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+ "RESOURCE_ID" integer primary key,
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
+ "NOTIFICATION_UID" nvarchar2(255),
+ "XML_TYPE" nvarchar2(255),
+ "XML_DATA" nclob,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ "TRANSP" integer default 0 not null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "TIMEZONE" nclob default null,
+ primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
+ unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
+);
+
+create table CALENDAR_BIND_MODE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "RESOURCE_ID" integer primary key,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob,
+ "ICALENDAR_UID" nvarchar2(255),
+ "ICALENDAR_TYPE" nvarchar2(255),
+ "ATTACHMENTS_MODE" integer default 0 not null,
+ "DROPBOX_ID" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "RECURRANCE_MIN" date,
+ "RECURRANCE_MAX" date,
+ "ACCESS" integer default 0 not null,
+ "SCHEDULE_OBJECT" integer default 0,
+ "SCHEDULE_TAG" nvarchar2(36) default null,
+ "SCHEDULE_ETAGS" nclob default null,
+ "PRIVATE_COMMENTS" integer default 0 not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "INSTANCE_ID" integer primary key,
+ "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" integer not null,
+ "START_DATE" timestamp not null,
+ "END_DATE" timestamp not null,
+ "FBTYPE" integer not null,
+ "TRANSPARENT" integer not null
+);
+
+create table FREE_BUSY_TYPE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
+ "USER_ID" nvarchar2(255),
+ "TRANSPARENT" integer not null
+);
+
+create table ATTACHMENT (
+ "ATTACHMENT_ID" integer primary key,
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "DROPBOX_ID" nvarchar2(255),
+ "CONTENT_TYPE" nvarchar2(255),
+ "SIZE" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PATH" nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+ "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
+ "MANAGED_ID" nvarchar2(255),
+ "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+ primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
+ unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
+);
+
+create table RESOURCE_PROPERTY (
+ "RESOURCE_ID" integer not null,
+ "NAME" nvarchar2(255),
+ "VALUE" nclob,
+ "VIEWER_UID" nvarchar2(255),
+ primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
+);
+
+create table ADDRESSBOOK_HOME (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
+);
+
+create table ADDRESSBOOK_OBJECT (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "VCARD_TEXT" nclob,
+ "VCARD_UID" nvarchar2(255),
+ "KIND" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
+ primary key("GROUP_ID", "MEMBER_ID")
+);
+
+create table ABO_FOREIGN_MEMBERS (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ADDRESS" nvarchar2(255),
+ primary key("GROUP_ID", "MEMBER_ADDRESS")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "CALENDAR_RESOURCE_ID" integer references CALENDAR,
+ "CALENDAR_NAME" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+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" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null,
+ unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table APN_SUBSCRIPTIONS (
+ "TOKEN" nvarchar2(255),
+ "RESOURCE_KEY" nvarchar2(255),
+ "MODIFIED" integer not null,
+ "SUBSCRIBER_GUID" nvarchar2(255),
+ "USER_AGENT" nvarchar2(255) default null,
+ "IP_ADDR" nvarchar2(255) default null,
+ primary key("TOKEN", "RESOURCE_KEY")
+);
+
+create table IMIP_TOKENS (
+ "TOKEN" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALUID" nvarchar2(255),
+ "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ primary key("ORGANIZER", "ATTENDEE", "ICALUID")
+);
+
+create table IMIP_INVITATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "FROM_ADDR" nvarchar2(255),
+ "TO_ADDR" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table IMIP_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PUSH_ID" nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+ "NAME" nvarchar2(255) primary key,
+ "VALUE" 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 (
+ "HOSTNAME" nvarchar2(255),
+ "PID" integer not null,
+ "PORT" integer not null,
+ "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null,
+ primary key("HOSTNAME", "PORT")
+);
+
+create table NAMED_LOCK (
+ "LOCK_NAME" nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table CALENDAR (
+ "RESOURCE_ID" integer primary key
+);
+
+create table CALENDAR_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
+ "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "AVAILABILITY" nclob default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_METADATA (
+ "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
+ "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+ "RESOURCE_ID" integer primary key,
+ "OWNER_UID" nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+ "RESOURCE_ID" integer primary key,
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
+ "NOTIFICATION_UID" nvarchar2(255),
+ "XML_TYPE" nvarchar2(255),
+ "XML_DATA" nclob,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ "TRANSP" integer default 0 not null,
+ "ALARM_VEVENT_TIMED" nclob default null,
+ "ALARM_VEVENT_ALLDAY" nclob default null,
+ "ALARM_VTODO_TIMED" nclob default null,
+ "ALARM_VTODO_ALLDAY" nclob default null,
+ "TIMEZONE" nclob default null,
+ primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
+ unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
+);
+
+create table CALENDAR_BIND_MODE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "RESOURCE_ID" integer primary key,
+ "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob,
+ "ICALENDAR_UID" nvarchar2(255),
+ "ICALENDAR_TYPE" nvarchar2(255),
+ "ATTACHMENTS_MODE" integer default 0 not null,
+ "DROPBOX_ID" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "RECURRANCE_MIN" date,
+ "RECURRANCE_MAX" date,
+ "ACCESS" integer default 0 not null,
+ "SCHEDULE_OBJECT" integer default 0,
+ "SCHEDULE_TAG" nvarchar2(36) default null,
+ "SCHEDULE_ETAGS" nclob default null,
+ "PRIVATE_COMMENTS" integer default 0 not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "INSTANCE_ID" integer primary key,
+ "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" integer not null,
+ "START_DATE" timestamp not null,
+ "END_DATE" timestamp not null,
+ "FBTYPE" integer not null,
+ "TRANSPARENT" integer not null
+);
+
+create table FREE_BUSY_TYPE (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
+ "USER_ID" nvarchar2(255),
+ "TRANSPARENT" integer not null
+);
+
+create table ATTACHMENT (
+ "ATTACHMENT_ID" integer primary key,
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "DROPBOX_ID" nvarchar2(255),
+ "CONTENT_TYPE" nvarchar2(255),
+ "SIZE" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PATH" nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+ "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
+ "MANAGED_ID" nvarchar2(255),
+ "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+ primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"),
+ unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
+);
+
+create table RESOURCE_PROPERTY (
+ "RESOURCE_ID" integer not null,
+ "NAME" nvarchar2(255),
+ "VALUE" nclob,
+ "VIEWER_UID" nvarchar2(255),
+ primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
+);
+
+create table ADDRESSBOOK_HOME (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
+ "OWNER_UID" nvarchar2(255) unique,
+ "DATAVERSION" integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+ "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
+ "QUOTA_USED_BYTES" integer default 0 not null,
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "OWNER_HOME_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
+);
+
+create table ADDRESSBOOK_OBJECT (
+ "RESOURCE_ID" integer primary key,
+ "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "VCARD_TEXT" nclob,
+ "VCARD_UID" nvarchar2(255),
+ "KIND" integer not null,
+ "MD5" nchar(32),
+ "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "RESOURCE_NAME"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "VCARD_UID")
+);
+
+create table ADDRESSBOOK_OBJECT_KIND (
+ "ID" integer primary key,
+ "DESCRIPTION" 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 (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT,
+ primary key("GROUP_ID", "MEMBER_ID")
+);
+
+create table ABO_FOREIGN_MEMBERS (
+ "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+ "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+ "MEMBER_ADDRESS" nvarchar2(255),
+ primary key("GROUP_ID", "MEMBER_ADDRESS")
+);
+
+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" nvarchar2(255),
+ "BIND_MODE" integer not null,
+ "BIND_STATUS" integer not null,
+ "BIND_REVISION" integer default 0 not null,
+ "MESSAGE" nclob,
+ primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_RESOURCE_ID"),
+ unique("ADDRESSBOOK_HOME_RESOURCE_ID", "GROUP_ADDRESSBOOK_NAME")
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+ "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+ "CALENDAR_RESOURCE_ID" integer references CALENDAR,
+ "CALENDAR_NAME" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+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" nvarchar2(255) default null,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+ "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
+ "RESOURCE_NAME" nvarchar2(255),
+ "REVISION" integer not null,
+ "DELETED" integer not null,
+ unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table APN_SUBSCRIPTIONS (
+ "TOKEN" nvarchar2(255),
+ "RESOURCE_KEY" nvarchar2(255),
+ "MODIFIED" integer not null,
+ "SUBSCRIBER_GUID" nvarchar2(255),
+ "USER_AGENT" nvarchar2(255) default null,
+ "IP_ADDR" nvarchar2(255) default null,
+ primary key("TOKEN", "RESOURCE_KEY")
+);
+
+create table IMIP_TOKENS (
+ "TOKEN" nvarchar2(255),
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALUID" nvarchar2(255),
+ "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ primary key("ORGANIZER", "ATTENDEE", "ICALUID")
+);
+
+create table IMIP_INVITATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "FROM_ADDR" nvarchar2(255),
+ "TO_ADDR" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table IMIP_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "ORGANIZER" nvarchar2(255),
+ "ATTENDEE" nvarchar2(255),
+ "ICALENDAR_TEXT" nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "PUSH_ID" nvarchar2(255)
+);
+
+create table GROUP_CACHER_POLLING_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR_OBJECT_SPLITTER_WORK (
+ "WORK_ID" integer primary key not null,
+ "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+ "RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade
+);
+
+create table CALENDARSERVER (
+ "NAME" nvarchar2(255) primary key,
+ "VALUE" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 ("DEFAULT_POLLS" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
--- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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 "License");
+-- 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 "AS IS" 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("calendar")
- # 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("tasks")
</del><ins>+ for name in ical.allowedStoreComponents:
+ yield home.removeCalendarWithName(home._componentCalendarName[name])
+ else:
+ yield home.removeCalendarWithName("calendar")
</ins><span class="cx"> yield home.removeCalendarWithName("inbox")
</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"> """
</span><span class="cx">
</span><del>- nowYear = PyCalendarDateTime.getToday().getYear()
</del><ins>+ nowYear = DateTime.getToday().getYear()
</ins><span class="cx"> return data % {"now": 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 = "VEVENT"
+ elif propname == customxml.ScheduleDefaultTasksURL:
+ ctype = "VTODO"
</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>