[CalendarServer-changes] [11916] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:15:37 PDT 2014


Revision: 11916
          http://trac.calendarserver.org//changeset/11916
Author:   cdaboo at apple.com
Date:     2013-11-08 12:46:55 -0800 (Fri, 08 Nov 2013)
Log Message:
-----------
Update to new pycalendar api. Add support for JSON iCalendar data. Add support for VPOLL (disabled by config for now).

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tools/anonymize.py
    CalendarServer/trunk/calendarserver/tools/calverify.py
    CalendarServer/trunk/calendarserver/tools/dbinspect.py
    CalendarServer/trunk/calendarserver/tools/gateway.py
    CalendarServer/trunk/calendarserver/tools/managetimezones.py
    CalendarServer/trunk/calendarserver/tools/purge.py
    CalendarServer/trunk/calendarserver/tools/test/test_calverify.py
    CalendarServer/trunk/calendarserver/tools/test/test_purge.py
    CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py
    CalendarServer/trunk/contrib/performance/loadtest/ical.py
    CalendarServer/trunk/contrib/performance/loadtest/profiles.py
    CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
    CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py
    CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py
    CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py
    CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py
    CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py
    CalendarServer/trunk/contrib/performance/stats.py
    CalendarServer/trunk/contrib/performance/test_stats.py
    CalendarServer/trunk/contrib/tools/sortrecurrences.py
    CalendarServer/trunk/support/build.sh
    CalendarServer/trunk/twext/enterprise/dal/syntax.py
    CalendarServer/trunk/twext/enterprise/fixtures.py
    CalendarServer/trunk/twext/enterprise/queue.py
    CalendarServer/trunk/twext/enterprise/test/test_queue.py
    CalendarServer/trunk/twext/protocols/test/test_memcache.py
    CalendarServer/trunk/twistedcaldav/__init__.py
    CalendarServer/trunk/twistedcaldav/accounting.py
    CalendarServer/trunk/twistedcaldav/authkerb.py
    CalendarServer/trunk/twistedcaldav/backup.py
    CalendarServer/trunk/twistedcaldav/caldavxml.py
    CalendarServer/trunk/twistedcaldav/carddavxml.py
    CalendarServer/trunk/twistedcaldav/customxml.py
    CalendarServer/trunk/twistedcaldav/database.py
    CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py
    CalendarServer/trunk/twistedcaldav/dateops.py
    CalendarServer/trunk/twistedcaldav/directory/addressbook.py
    CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
    CalendarServer/trunk/twistedcaldav/directory/test/util.py
    CalendarServer/trunk/twistedcaldav/dropbox.py
    CalendarServer/trunk/twistedcaldav/freebusyurl.py
    CalendarServer/trunk/twistedcaldav/ical.py
    CalendarServer/trunk/twistedcaldav/icaldav.py
    CalendarServer/trunk/twistedcaldav/instance.py
    CalendarServer/trunk/twistedcaldav/linkresource.py
    CalendarServer/trunk/twistedcaldav/localization.py
    CalendarServer/trunk/twistedcaldav/memcachelock.py
    CalendarServer/trunk/twistedcaldav/memcachepool.py
    CalendarServer/trunk/twistedcaldav/method/get.py
    CalendarServer/trunk/twistedcaldav/method/propfind.py
    CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py
    CalendarServer/trunk/twistedcaldav/method/report_common.py
    CalendarServer/trunk/twistedcaldav/method/report_freebusy.py
    CalendarServer/trunk/twistedcaldav/mkcolxml.py
    CalendarServer/trunk/twistedcaldav/notifications.py
    CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py
    CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py
    CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py
    CalendarServer/trunk/twistedcaldav/sharing.py
    CalendarServer/trunk/twistedcaldav/sql.py
    CalendarServer/trunk/twistedcaldav/stdconfig.py
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py
    CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py
    CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
    CalendarServer/trunk/twistedcaldav/test/test_dateops.py
    CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
    CalendarServer/trunk/twistedcaldav/test/test_localization.py
    CalendarServer/trunk/twistedcaldav/test/test_multiget.py
    CalendarServer/trunk/twistedcaldav/test/test_props.py
    CalendarServer/trunk/twistedcaldav/test/test_timezones.py
    CalendarServer/trunk/twistedcaldav/test/test_upgrade.py
    CalendarServer/trunk/twistedcaldav/timezones.py
    CalendarServer/trunk/twistedcaldav/timezoneservice.py
    CalendarServer/trunk/twistedcaldav/timezonestdservice.py
    CalendarServer/trunk/twistedcaldav/upgrade.py
    CalendarServer/trunk/twistedcaldav/util.py
    CalendarServer/trunk/twistedcaldav/vcard.py
    CalendarServer/trunk/twistedcaldav/xmlutil.py
    CalendarServer/trunk/txdav/caldav/datastore/file.py
    CalendarServer/trunk/txdav/caldav/datastore/index_file.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py
    CalendarServer/trunk/txdav/caldav/datastore/util.py
    CalendarServer/trunk/txdav/caldav/icalendarstore.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
    CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/trunk/txdav/common/datastore/test/util.py
    CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py

Added Paths:
-----------
    CalendarServer/trunk/twistedcaldav/test/test_util.py
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v26.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql

Removed Paths:
-------------
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
    CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql

Property Changed:
----------------
    CalendarServer/trunk/


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

Modified: CalendarServer/trunk/calendarserver/tools/anonymize.py
===================================================================
--- 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)
@@ -33,8 +33,8 @@
 
 from twext.python.plistlib import readPlistFromString
 
-from pycalendar.calendar import PyCalendar
-from pycalendar.attribute import PyCalendarAttribute
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.parameter import Parameter
 
 COPY_CAL_XATTRS = (
     'WebDAV:{DAV:}resourcetype',
@@ -67,6 +67,8 @@
     else:
         sys.exit(0)
 
+
+
 def main():
 
     try:
@@ -83,8 +85,6 @@
     # Get configuration
     #
     directoryNode = "/Search"
-    sourceDirectory = None
-    destDirectory = None
 
     for opt, arg in optargs:
         if opt in ("-h", "--help"):
@@ -107,6 +107,7 @@
     directoryMap.dumpDsImports(os.path.join(destDirectory, "dsimports"))
 
 
+
 def anonymizeRoot(directoryMap, sourceDirectory, destDirectory):
     # sourceDirectory and destDirectory are DocumentRoots
 
@@ -244,12 +245,10 @@
 
                     resources += 1
 
-
                 # Store new ctag on calendar
                 xml = "<?xml version='1.0' encoding='UTF-8'?>\r\n<getctag xmlns='http://calendarserver.org/ns/'>%s</getctag>\r\n" % (str(datetime.datetime.now()),)
                 xattr.setxattr(destCal, "WebDAV:{http:%2F%2Fcalendarserver.org%2Fns%2F}getctag", zlib.compress(xml))
 
-
             # Calendar home quota
             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,)
             xattr.setxattr(destHome, "WebDAV:{http:%2F%2Ftwistedmatrix.com%2Fxml_namespace%2Fdav%2Fprivate%2F}quota-used", zlib.compress(xml))
@@ -280,9 +279,10 @@
     print("")
 
 
+
 def anonymizeData(directoryMap, data):
     try:
-        pyobj = PyCalendar.parseText(data)
+        pyobj = Calendar.parseText(data)
     except Exception, e:
         print("Failed to parse (%s): %s" % (e, data))
         return None
@@ -309,13 +309,13 @@
                             comp.removeProperty(prop)
                             continue
                     prop.setValue("urn:uuid:%s" % (record['guid'],))
-                    if prop.hasAttribute('X-CALENDARSERVER-EMAIL'):
-                        prop.replaceAttribute(PyCalendarAttribute('X-CALENDARSERVER-EMAIL', record['email']))
+                    if prop.hasParameter('X-CALENDARSERVER-EMAIL'):
+                        prop.replaceParameter(Parameter('X-CALENDARSERVER-EMAIL', record['email']))
                     else:
-                        prop.removeAttributes('EMAIL')
-                        prop.addAttribute(PyCalendarAttribute('EMAIL', record['email']))
-                    prop.removeAttributes('CN')
-                    prop.addAttribute(PyCalendarAttribute('CN', record['name']))
+                        prop.removeParameters('EMAIL')
+                        prop.addParameter(Parameter('EMAIL', record['email']))
+                    prop.removeParameters('CN')
+                    prop.addParameter(Parameter('CN', record['name']))
             except KeyError:
                 pass
 
@@ -345,11 +345,12 @@
     return pyobj.getText(includeTimezones=True)
 
 
+
 class DirectoryMap(object):
 
     def __init__(self, node):
 
-        self.map = { }
+        self.map = {}
         self.byType = {
             'users' : [],
             'groups' : [],
@@ -373,10 +374,10 @@
 
         print("Fetching records from directory: %s" % (node,))
 
-        for internalType, (recordType, friendlyType) in self.strings.iteritems():
+        for internalType, (recordType, _ignore_friendlyType) in self.strings.iteritems():
             print(" %s..." % (internalType,))
             child = Popen(
-                args = [
+                args=[
                     "/usr/bin/dscl", "-plist", node, "-readall",
                     "/%s" % (recordType,),
                     "GeneratedUID", "RecordName", "EMailAddress", "GroupMembers"
@@ -405,6 +406,7 @@
         print("Done.")
         print("")
 
+
     def addRecord(self, internalType="users", guid=None, names=None,
         emails=None, members=None, cua=None):
 
@@ -458,6 +460,7 @@
                 keys.append(email)
         return keys
 
+
     def cua2key(self, cua):
         key = cua.lower()
 
@@ -473,10 +476,11 @@
 
         return key
 
+
     def lookupCUA(self, cua):
         key = self.cua2key(cua)
 
-        if key and self.map.has_key(key):
+        if key and key in self.map:
             return self.map[key]
         else:
             return None
@@ -491,6 +495,7 @@
         if unknown:
             print(" Principals not found in directory: %d" % (unknown,))
 
+
     def dumpDsImports(self, dirPath):
         if not os.path.exists(dirPath):
             os.makedirs(dirPath)
@@ -567,6 +572,8 @@
     Error trying to access dscl
     """
 
+
+
 class DatabaseError(Exception):
     """
     Error trying to access sqlite3
@@ -574,8 +581,6 @@
 
 
 
-
-
 def anonymize(text):
     """
     Return a string whose value is the hex digest of text, repeated as needed
@@ -592,19 +597,18 @@
     h = hashlib.md5(text)
     h = h.hexdigest()
     l = len(text)
-    return (h*((l/32)+1))[:-(32-(l%32))]
+    return (h * ((l / 32) + 1))[:-(32 - (l % 32))]
 
 
 
 nameChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
 def randomName(length):
     l = []
-    for i in xrange(length):
+    for _ignore in xrange(length):
         l.append(random.choice(nameChars))
     return "".join(l)
 
 
 
-
 if __name__ == "__main__":
     main()

Modified: CalendarServer/trunk/calendarserver/tools/calverify.py
===================================================================
--- 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)
@@ -47,12 +47,12 @@
 import traceback
 import uuid
 
-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
+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
 
 from twisted.application.service import Service
 from twisted.internet.defer import inlineCallbacks, returnValue
@@ -543,7 +543,7 @@
         tr = schema.TIME_RANGE
         kwds = {
             "Start" : pyCalendarTodatetime(start),
-            "Max"   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0))
+            "Max"   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0))
         }
         rows = (yield Select(
             [ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED],
@@ -596,7 +596,7 @@
         tr = schema.TIME_RANGE
         kwds = {
             "Start" : pyCalendarTodatetime(start),
-            "Max"   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
+            "Max"   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
             "UUID" : uuid,
         }
         rows = (yield Select(
@@ -626,7 +626,7 @@
 
         kwds = {
             "Start" : pyCalendarTodatetime(start),
-            "Max"   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
+            "Max"   : pyCalendarTodatetime(DateTime(1900, 1, 1, 0, 0, 0)),
             "UUID" : uuid,
         }
         rows = (yield Select(
@@ -704,8 +704,8 @@
             ),
         ).on(self.txn, **kwds))
         try:
-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
+            caldata = Calendar.parseText(rows[0][0]) if rows else None
+        except ErrorBase:
             caltxt = rows[0][0] if rows else None
             if caltxt:
                 caltxt = caltxt.replace("\r\n ", "")
@@ -713,8 +713,8 @@
                     if doFix:
                         caltxt = (yield self.fixBadOldCua(resid, caltxt))
                         try:
-                            caldata = PyCalendar.parseText(caltxt) if rows else None
-                        except PyCalendarError:
+                            caldata = Calendar.parseText(caltxt) if rows else None
+                        except ErrorBase:
                             self.parseError = "No fix bad CALENDARSERVER-OLD-CUA"
                             returnValue(None)
                     else:
@@ -746,8 +746,8 @@
         ).on(self.txn, **kwds))
 
         try:
-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
+            caldata = Calendar.parseText(rows[0][0]) if rows else None
+        except ErrorBase:
             returnValue((None, None, None, None,))
 
         returnValue((caldata, rows[0][1], rows[0][2], rows[0][3],) if rows else (None, None, None, None,))
@@ -1056,14 +1056,14 @@
 
         self.output.write("\n---- Scanning calendar data ----\n")
 
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = PyCalendarDateTime.getToday()
+        self.now = DateTime.getNowUTC()
+        self.start = DateTime.getToday()
         self.start.setDateOnly(False)
         self.end = self.start.duplicate()
         self.end.offsetYear(1)
         self.fix = self.options["fix"]
 
-        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+        self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
 
         self.txn = self.store.newTransaction()
 
@@ -1426,14 +1426,14 @@
 
         self.output.write("\n---- Scanning calendar data ----\n")
 
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = self.options["start"] if "start" in self.options else PyCalendarDateTime.getToday()
+        self.now = DateTime.getNowUTC()
+        self.start = self.options["start"] if "start" in self.options else DateTime.getToday()
         self.start.setDateOnly(False)
         self.end = self.start.duplicate()
         self.end.offsetYear(1)
         self.fix = self.options["fix"]
 
-        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+        self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
 
         self.txn = self.store.newTransaction()
 
@@ -2028,7 +2028,7 @@
         """
         Return the master iCal component in this calendar.
 
-        @return: the L{PyCalendarComponent} for the master component,
+        @return: the L{Component} for the master component,
             or C{None} if there isn't one.
         """
         for component in calendar.getComponents(definitions.cICalComponent_VEVENT):
@@ -2042,7 +2042,7 @@
         # Expand events into instances in the start/end range
         results = []
         calendar.getVEvents(
-            PyCalendarPeriod(
+            Period(
                 start=start,
                 end=end,
             ),
@@ -2082,10 +2082,10 @@
                 if cancelled:
                     partstat = "CANCELLED"
                 else:
-                    if not prop.hasAttribute(definitions.cICalAttribute_PARTSTAT):
-                        partstat = definitions.cICalAttribute_PARTSTAT_NEEDSACTION
+                    if not prop.hasParameter(definitions.cICalParameter_PARTSTAT):
+                        partstat = definitions.cICalParameter_PARTSTAT_NEEDSACTION
                     else:
-                        partstat = prop.getAttributeValue(definitions.cICalAttribute_PARTSTAT)
+                        partstat = prop.getParameterValue(definitions.cICalParameter_PARTSTAT)
 
                 attendees.setdefault(caladdr, set()).add((instance_id, partstat))
 
@@ -2140,9 +2140,9 @@
 
         self.output.write("\n---- Scanning calendar data ----\n")
 
-        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = PyCalendarDateTime.getToday()
+        self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+        self.now = DateTime.getNowUTC()
+        self.start = DateTime.getToday()
         self.start.setDateOnly(False)
         self.start.setTimezone(self.tzid)
         self.end = self.start.duplicate()
@@ -2328,7 +2328,7 @@
                     continue
                 dtstart = instance.component.propertyValue("DTSTART")
                 if tzid is None and dtstart.getTimezoneID():
-                    tzid = PyCalendarTimezone(tzid=dtstart.getTimezoneID())
+                    tzid = Timezone(tzid=dtstart.getTimezoneID())
                 hasFloating |= dtstart.isDateOnly() or dtstart.floating()
 
                 details.append(InstanceDetails(resid, uid, instance.start, instance.end, instance.component.getOrganizer(), instance.component.propertyValue("SUMMARY")))
@@ -2369,7 +2369,7 @@
 
         # Adjust floating and sort
         if hasFloating and tzid is not None:
-            utc = PyCalendarTimezone(utc=True)
+            utc = Timezone(utc=True)
             for item in details:
                 if item.start.floating():
                     item.start.setTimezone(tzid)
@@ -2449,9 +2449,9 @@
 
         self.output.write("\n---- Scanning calendar data ----\n")
 
-        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()
+        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()
         self.start.setDateOnly(False)
         self.start.setTimezone(self.tzid)
         self.fix = self.options["fix"]

Modified: CalendarServer/trunk/calendarserver/tools/dbinspect.py
===================================================================
--- 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)
@@ -24,7 +24,7 @@
 
 from calendarserver.tools import tables
 from calendarserver.tools.cmdline import utilityMain
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twext.enterprise.dal.syntax import Select, Parameter, Count, Delete, \
     Constant
 from twisted.application.service import Service
@@ -715,12 +715,12 @@
             end += "T000000Z"
 
         try:
-            start = PyCalendarDateTime.parseText(start)
+            start = DateTime.parseText(start)
         except ValueError:
             print("Invalid start value")
             returnValue(None)
         try:
-            end = PyCalendarDateTime.parseText(end)
+            end = DateTime.parseText(end)
         except ValueError:
             print("Invalid end value")
             returnValue(None)

Modified: CalendarServer/trunk/calendarserver/tools/gateway.py
===================================================================
--- 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)
@@ -36,9 +36,9 @@
 from calendarserver.tools.purge import WorkerService, PurgeOldEventsService, DEFAULT_BATCH_SIZE, DEFAULT_RETAIN_DAYS
 from calendarserver.tools.cmdline import utilityMain
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
-from twistedcaldav.config import config, ConfigDict 
+from twistedcaldav.config import config, ConfigDict
 
 from calendarserver.tools.config import WRITABLE_CONFIG_KEYS, setKeyPath, getKeyPath, flattenDictionary, WritableConfig
 
@@ -373,7 +373,7 @@
             return
         self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
 
-        
+
     def command_getLocationAndResourceList(self, command):
         self.respondWithRecordsOfTypes(self.dir, command, ["locations", "resources"])
 
@@ -424,10 +424,8 @@
             self.command_readConfig(command)
 
 
-
     # Proxies
 
-
     @inlineCallbacks
     def command_listWriteProxies(self, command):
         principal = principalForPrincipalID(command['Principal'], directory=self.dir)
@@ -538,14 +536,13 @@
         @type command: C{dict}
         """
         retainDays = command.get("RetainDays", DEFAULT_RETAIN_DAYS)
-        cutoff = PyCalendarDateTime.getToday()
+        cutoff = DateTime.getToday()
         cutoff.setDateOnly(False)
         cutoff.offsetDay(-retainDays)
         eventCount = (yield PurgeOldEventsService.purgeOldEvents(self.store, cutoff, DEFAULT_BATCH_SIZE))
         self.respond(command, {'EventsRemoved' : eventCount, "RetainDays" : retainDays})
 
 
-
     @inlineCallbacks
     def respondWithProxies(self, directory, command, principal, proxyType):
         proxies = []
@@ -562,7 +559,6 @@
         })
 
 
-
     def respondWithRecordsOfTypes(self, directory, command, recordTypes):
         result = []
         for recordType in recordTypes:
@@ -572,7 +568,6 @@
         self.respond(command, result)
 
 
-
     def respond(self, command, result):
         self.output.write(writePlistToString({'command' : command['command'], 'result' : result}))
 
@@ -581,6 +576,7 @@
         self.output.write(writePlistToString({'error' : msg, }))
 
 
+
 def recordToDict(record):
     recordDict = {}
     for key, info in attrMap.iteritems():
@@ -596,6 +592,8 @@
             pass
     return recordDict
 
+
+
 def respondWithError(msg, status=1):
     sys.stdout.write(writePlistToString({'error' : msg, }))
 

Modified: CalendarServer/trunk/calendarserver/tools/managetimezones.py
===================================================================
--- 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)
@@ -16,8 +16,8 @@
 ##
 from __future__ import print_function
 
-from pycalendar.calendar import PyCalendar
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.datetime import DateTime
 
 
 from twext.python.log import StandardIOObserver
@@ -95,11 +95,11 @@
         pass
 
     if not tzvers:
-        tzvers = PyCalendarDateTime.getToday().getText()
+        tzvers = DateTime.getToday().getText()
     print("Converting data (version: %s) at: %s" % (tzvers, zonedir,))
     startYear = 1800
-    endYear = PyCalendarDateTime.getToday().getYear() + 10
-    PyCalendar.sProdID = "-//calendarserver.org//Zonal//EN"
+    endYear = DateTime.getToday().getYear() + 10
+    Calendar.sProdID = "-//calendarserver.org//Zonal//EN"
     zonefiles = "northamerica", "southamerica", "europe", "africa", "asia", "australasia", "antarctica", "etcetera", "backward"
     parser = tzconvert()
     for file in zonefiles:

Modified: CalendarServer/trunk/calendarserver/tools/purge.py
===================================================================
--- 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)
@@ -23,7 +23,7 @@
 
 from getopt import getopt, GetoptError
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twext.python.log import Logger
 
@@ -147,7 +147,7 @@
         if dryrun:
             verbose = True
 
-        cutoff = PyCalendarDateTime.getToday()
+        cutoff = DateTime.getToday()
         cutoff.setDateOnly(False)
         cutoff.offsetDay(-days)
         cls.cutoff = cutoff
@@ -328,7 +328,7 @@
 
         cls.uuid = uuid
         if days > 0:
-            cutoff = PyCalendarDateTime.getToday()
+            cutoff = DateTime.getToday()
             cutoff.setDateOnly(False)
             cutoff.offsetDay(-days)
             cls.cutoff = cutoff
@@ -352,7 +352,7 @@
         service = cls(store)
         service.uuid = uuid
         if days > 0:
-            cutoff = PyCalendarDateTime.getToday()
+            cutoff = DateTime.getToday()
             cutoff.setDateOnly(False)
             cutoff.offsetDay(-days)
             service.cutoff = cutoff
@@ -732,7 +732,7 @@
     def _purgeUID(self, uid):
 
         if self.when is None:
-            self.when = PyCalendarDateTime.getNowUTC()
+            self.when = DateTime.getNowUTC()
 
         # Does the record exist?
         record = self.directory.recordWithUID(uid)
@@ -1020,7 +1020,7 @@
         @type event: L{twistedcaldav.ical.Component}
 
         @param when: the cutoff date (anything after which is removed)
-        @type when: PyCalendarDateTime
+        @type when: DateTime
 
         @param cua: Calendar User Address of principal being purged, to compare
             to see if it's the organizer of the event or just an attendee

Modified: CalendarServer/trunk/calendarserver/tools/test/test_calverify.py
===================================================================
--- 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)
@@ -22,7 +22,7 @@
 from calendarserver.tools.calverify import BadDataService, \
     SchedulingMismatchService, DoubleBookingService, DarkPurgeService
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks
@@ -969,7 +969,7 @@
         self.notifierFactory.reset()
 
 
-now = PyCalendarDateTime.getToday()
+now = DateTime.getToday()
 now.setDay(1)
 now.offsetMonth(2)
 nowYear = now.getYear()
@@ -1404,7 +1404,7 @@
 
         home = (yield self.homeUnderTest(name=self.uuid3))
         calendar = (yield self.calendarUnderTest(name="calendar2", home=self.uuid3))
-        yield home.setDefaultCalendar(calendar)
+        yield home.setDefaultCalendar(calendar, "VEVENT")
         yield self.commit()
 
 
@@ -1431,7 +1431,7 @@
             "uid": "",
             "uuid": "",
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -1498,7 +1498,7 @@
             "uid": "",
             "uuid": "",
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -1707,7 +1707,7 @@
             "uid": "",
             "uuid": "",
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -1758,7 +1758,7 @@
             "uid": "",
             "uuid": "",
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -1934,7 +1934,7 @@
             "uid": "",
             "uuid": CalVerifyMismatchTestsBase.uuidl1,
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -1983,7 +1983,7 @@
             "uid": "",
             "uuid": CalVerifyMismatchTestsBase.uuidl1,
             "tzid": "",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
@@ -2446,7 +2446,7 @@
             "uid": "",
             "uuid": self.uuidl1,
             "tzid": "utc",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
         }
         output = StringIO()
         calverify = DoubleBookingService(self._sqlCalendarStore, options, output, reactor, config)
@@ -2609,7 +2609,7 @@
             "uid": "",
             "uuid": self.uuidl1,
             "tzid": "utc",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
             "no-organizer": False,
             "invalid-organizer": False,
             "disabled-organizer": False,
@@ -2656,7 +2656,7 @@
             "uid": "",
             "uuid": self.uuidl1,
             "tzid": "utc",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
             "no-organizer": False,
             "invalid-organizer": False,
             "disabled-organizer": False,
@@ -2715,7 +2715,7 @@
             "uid": "",
             "uuid": self.uuidl1,
             "tzid": "utc",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
             "no-organizer": True,
             "invalid-organizer": False,
             "disabled-organizer": False,
@@ -2774,7 +2774,7 @@
             "uid": "",
             "uuid": self.uuidl1,
             "tzid": "utc",
-            "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+            "start": DateTime(nowYear, 1, 1, 0, 0, 0),
             "no-organizer": True,
             "invalid-organizer": True,
             "disabled-organizer": True,

Modified: CalendarServer/trunk/calendarserver/tools/test/test_purge.py
===================================================================
--- 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)
@@ -21,8 +21,8 @@
 from twistedcaldav.ical import Component
 from twistedcaldav.test.util import StoreTestCase
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twisted.internet.defer import inlineCallbacks
 from txdav.common.datastore.test.util import populateCalendarsFrom
@@ -33,11 +33,11 @@
 import os
 
 
-future = PyCalendarDateTime.getNowUTC()
+future = DateTime.getNowUTC()
 future.offsetDay(1)
 future = future.getText()
 
-past = PyCalendarDateTime.getNowUTC()
+past = DateTime.getNowUTC()
 past.offsetDay(-1)
 past = past.getText()
 
@@ -230,7 +230,7 @@
     def test_cancelRepeating(self):
         # A repeating event where purged CUA is organizer
         event = Component.fromString(REPEATING_1_ICS_BEFORE)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_MODIFIED)
         self.assertEquals(str(event), REPEATING_1_ICS_AFTER)
@@ -239,7 +239,7 @@
     def test_cancelAllDayRepeating(self):
         # A repeating All Day event where purged CUA is organizer
         event = Component.fromString(REPEATING_2_ICS_BEFORE)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_MODIFIED)
         self.assertEquals(str(event), REPEATING_2_ICS_AFTER)
@@ -248,7 +248,7 @@
     def test_cancelFutureEvent(self):
         # A future event
         event = Component.fromString(FUTURE_EVENT_ICS)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
 
@@ -256,7 +256,7 @@
     def test_cancelNonMeeting(self):
         # A repeating non-meeting event
         event = Component.fromString(REPEATING_NON_MEETING_ICS)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
 
@@ -264,7 +264,7 @@
     def test_cancelAsAttendee(self):
         # A repeating meeting event where purged CUA is an attendee
         event = Component.fromString(REPEATING_ATTENDEE_MEETING_ICS)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
 
@@ -273,7 +273,7 @@
         # A repeating meeting occurrence with no master, where purged CUA is
         # an attendee
         event = Component.fromString(INVITED_TO_OCCURRENCE_ICS)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
 
@@ -282,7 +282,7 @@
         # Multiple meeting occurrences with no master, where purged CUA is
         # an attendee
         event = Component.fromString(INVITED_TO_MULTIPLE_OCCURRENCES_ICS)
-        action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)),
+        action = PurgePrincipalService._cancelEvent(event, DateTime(2010, 12, 6, 12, 0, 0, Timezone(utc=True)),
             "urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66")
         self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
 

Modified: CalendarServer/trunk/calendarserver/tools/test/test_purge_old_events.py
===================================================================
--- 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)
@@ -21,8 +21,8 @@
 from calendarserver.tools.purge import PurgeOldEventsService, PurgeAttachmentsService, \
     PurgePrincipalService
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twext.enterprise.dal.syntax import Update, Delete
 from twext.web2.http_headers import MimeType
@@ -39,7 +39,7 @@
 import os
 
 
-now = PyCalendarDateTime.getToday().getYear()
+now = DateTime.getToday().getYear()
 
 OLD_ICS = """BEGIN:VCALENDAR
 VERSION:2.0
@@ -443,7 +443,7 @@
 
     @inlineCallbacks
     def test_eventsOlderThan(self):
-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
         txn = self._sqlCalendarStore.newTransaction()
 
         # Query for all old events
@@ -475,7 +475,7 @@
 
     @inlineCallbacks
     def test_removeOldEvents(self):
-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
         txn = self._sqlCalendarStore.newTransaction()
 
         # Remove oldest event - except we don't know what that is because of the dummy timestamps
@@ -598,7 +598,7 @@
         self.assertTrue(os.path.exists(mattachmentPath2))
 
         # Delete all old events (including the event containing the attachment)
-        cutoff = PyCalendarDateTime(now, 4, 1, 0, 0, 0)
+        cutoff = DateTime(now, 4, 1, 0, 0, 0)
         count = (yield self.transactionUnderTest().removeOldEvents(cutoff))
 
         # See which events have gone and which exist
@@ -633,7 +633,7 @@
         # Dry run
         total = (yield PurgeOldEventsService.purgeOldEvents(
             self._sqlCalendarStore,
-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
+            DateTime(now, 4, 1, 0, 0, 0),
             2,
             dryrun=True,
             verbose=False
@@ -643,7 +643,7 @@
         # Actually remove
         total = (yield PurgeOldEventsService.purgeOldEvents(
             self._sqlCalendarStore,
-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
+            DateTime(now, 4, 1, 0, 0, 0),
             2,
             verbose=False
         ))
@@ -652,7 +652,7 @@
         # There should be no more left
         total = (yield PurgeOldEventsService.purgeOldEvents(
             self._sqlCalendarStore,
-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
+            DateTime(now, 4, 1, 0, 0, 0),
             2,
             verbose=False
         ))
@@ -681,7 +681,7 @@
         # Purge home1
         total, ignored = (yield PurgePrincipalService.purgeUIDs(self._sqlCalendarStore, self.directory,
             self.rootResource, ("home1",), verbose=False, proxies=False,
-            when=PyCalendarDateTime(now, 4, 1, 12, 0, 0, 0, PyCalendarTimezone(utc=True))))
+            when=DateTime(now, 4, 1, 12, 0, 0, 0, Timezone(utc=True))))
 
         # 4 items deleted: 3 events and 1 vcard
         self.assertEquals(total, 4)
@@ -768,7 +768,7 @@
         # Remove old events first
         total = (yield PurgeOldEventsService.purgeOldEvents(
             self._sqlCalendarStore,
-            PyCalendarDateTime(now, 4, 1, 0, 0, 0),
+            DateTime(now, 4, 1, 0, 0, 0),
             2,
             verbose=False
         ))

Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- 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)
@@ -29,9 +29,9 @@
 from contrib.performance.httpclient import StringProducer, readBody
 from contrib.performance.loadtest.subscribe import Periodical
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
 
 from twext.internet.adaptendpoint import connect
 from twext.internet.gaiendpoint import GAIEndpoint
@@ -1609,13 +1609,13 @@
             msg("Availability request spanning multiple days (%r to %r), "
                 "dropping the end date." % (start, end))
 
-        start.setTimezone(PyCalendarTimezone(utc=True))
+        start.setTimezone(Timezone(utc=True))
         start.setHHMMSS(0, 0, 0)
-        end = start + PyCalendarDuration(hours=24)
+        end = start + Duration(hours=24)
 
         start = start.getText()
         end = end.getText()
-        now = PyCalendarDateTime.getNowUTC().getText()
+        now = DateTime.getNowUTC().getText()
 
         label_suffix = "small"
         if len(users) > 5:
@@ -1919,7 +1919,7 @@
         # the sim can fire a PUT between the PROPFIND and when process the removals.
         old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
 
-        now = PyCalendarDateTime.getNowUTC()
+        now = DateTime.getNowUTC()
         now.setDateOnly(True)
         now.offsetMonth(-1) # 1 month back default
         result = yield self._report(

Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- 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)
@@ -42,8 +42,8 @@
 from contrib.performance.loadtest.logger import SummarizingMixin
 from contrib.performance.loadtest.ical import IncorrectResponseCode
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
 
 class ProfileBase(object):
     """
@@ -407,9 +407,9 @@
             vevent = vcalendar.mainComponent()
             uid = str(uuid4())
             dtstart = self._eventStartDistribution.sample()
-            dtend = dtstart + PyCalendarDuration(seconds=self._eventDurationDistribution.sample())
-            vevent.replaceProperty(Property("CREATED", PyCalendarDateTime.getNowUTC()))
-            vevent.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+            vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
             vevent.replaceProperty(Property("DTSTART", dtstart))
             vevent.replaceProperty(Property("DTEND", dtend))
             vevent.replaceProperty(Property("UID", uid))
@@ -650,9 +650,9 @@
             vevent = vcalendar.mainComponent()
             uid = str(uuid4())
             dtstart = self._eventStartDistribution.sample()
-            dtend = dtstart + PyCalendarDuration(seconds=self._eventDurationDistribution.sample())
-            vevent.replaceProperty(Property("CREATED", PyCalendarDateTime.getNowUTC()))
-            vevent.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+            vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
             vevent.replaceProperty(Property("DTSTART", dtstart))
             vevent.replaceProperty(Property("DTEND", dtend))
             vevent.replaceProperty(Property("UID", uid))
@@ -719,8 +719,8 @@
             vtodo = vcalendar.mainComponent()
             uid = str(uuid4())
             due = self._taskStartDistribution.sample()
-            vtodo.replaceProperty(Property("CREATED", PyCalendarDateTime.getNowUTC()))
-            vtodo.replaceProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+            vtodo.replaceProperty(Property("CREATED", DateTime.getNowUTC()))
+            vtodo.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
             vtodo.replaceProperty(Property("DUE", due))
             vtodo.replaceProperty(Property("UID", uid))
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_ical.py
===================================================================
--- 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)
@@ -24,8 +24,8 @@
 from contrib.performance.loadtest.ical import XMPPPush, Event, Calendar, OS_X_10_6
 from contrib.performance.loadtest.sim import _DirectoryRecord
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
 from twisted.internet.protocol import ProtocolToConsumerAdapter
@@ -1957,8 +1957,8 @@
         self.client.outbox = "/calendars/__uids__/%s/outbox/" % (self.record.uid,)
         requests = self.interceptRequests()
 
-        start = PyCalendarDateTime(2011, 6, 10, 10, 45, 0, tzid=PyCalendarTimezone(utc=True))
-        end = PyCalendarDateTime(2011, 6, 10, 11, 15, 0, tzid=PyCalendarTimezone(utc=True))
+        start = DateTime(2011, 6, 10, 10, 45, 0, tzid=Timezone(utc=True))
+        end = DateTime(2011, 6, 10, 11, 15, 0, tzid=Timezone(utc=True))
         d = self.client.requestAvailability(
             start, end, [u"urn:uuid:user05", u"urn:uuid:user10"])
 

Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/invite.py
===================================================================
--- 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)
@@ -16,7 +16,7 @@
 
 from caldavclientlibrary.protocol.url import URL
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twext.web2.dav.util import joinURL
 from caldavclientlibrary.protocol.webdav.definitions import davxml
 
@@ -67,7 +67,7 @@
         """
 
         # Invite as user02
-        now = PyCalendarDateTime.getNowUTC()
+        now = DateTime.getNowUTC()
         href = joinURL(self.sessions[1].calendarHref, "organizer.ics")
         self.sessions[1].writeData(URL(path=href), ICAL % (now.getYear() + 1,), "text/calendar")
 

Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/put.py
===================================================================
--- 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)
@@ -16,7 +16,7 @@
 
 from caldavclientlibrary.protocol.url import URL
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twext.web2.dav.util import joinURL
 
 ICAL = """BEGIN:VCALENDAR
@@ -62,7 +62,7 @@
         Execute the actual HTTP request.
         """
 
-        now = PyCalendarDateTime.getNowUTC()
+        now = DateTime.getNowUTC()
         href = joinURL(self.sessions[0].calendarHref, "put.ics")
         self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1,), "text/calendar")
 

Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py
===================================================================
--- 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)
@@ -18,7 +18,7 @@
 from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
 from twext.web2.dav.util import joinURL
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
 from caldavclientlibrary.protocol.http.data.string import ResponseDataString
 
@@ -70,7 +70,7 @@
         Do some setup prior to the real request.
         """
         # Add resources to create required number of changes
-        self.start = PyCalendarDateTime.getNowUTC()
+        self.start = DateTime.getNowUTC()
         self.start.setHHMMSS(12, 0, 0)
         self.end = self.start.duplicate()
         self.end.offsetHours(1)

Modified: CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py
===================================================================
--- 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)
@@ -18,7 +18,7 @@
 from caldavclientlibrary.protocol.webdav.definitions import davxml
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
 from twext.web2.dav.util import joinURL
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 ICAL = """BEGIN:VCALENDAR
 CALSCALE:GREGORIAN
@@ -75,7 +75,7 @@
             self.synctoken = results[davxml.sync_token]
 
             # Add resources to create required number of changes
-            now = PyCalendarDateTime.getNowUTC()
+            now = DateTime.getNowUTC()
             for i in range(self.count):
                 href = joinURL(self.sessions[0].calendarHref, "sync-collection-%d.ics" % (i + 1,))
                 self.sessions[0].writeData(URL(path=href), ICAL % (now.getYear() + 1, i + 1,), "text/calendar")

Modified: CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py
===================================================================
--- 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)
@@ -27,7 +27,7 @@
 from contrib.performance.sqlusage.requests.put import PutTest
 from contrib.performance.sqlusage.requests.query import QueryTest
 from contrib.performance.sqlusage.requests.sync import SyncTest
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twext.web2.dav.util import joinURL
 import getopt
 import itertools
@@ -183,7 +183,7 @@
         @param n: number of events
         @type n: C{int}
         """
-        now = PyCalendarDateTime.getNowUTC()
+        now = DateTime.getNowUTC()
         for i in range(n - self.currentCount):
             index = self.currentCount + i + 1
             href = joinURL(calendarhref, "%d.ics" % (index,))

Modified: CalendarServer/trunk/contrib/performance/stats.py
===================================================================
--- 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)
@@ -16,10 +16,10 @@
 
 from __future__ import print_function
 from math import log, sqrt
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.property import PyCalendarProperty
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration as PyDuration
+from pycalendar.icalendar.property import Property
+from pycalendar.timezone import Timezone
 from twisted.python.util import FancyEqMixin
 from zope.interface import Interface, implements
 import random
@@ -338,7 +338,7 @@
 
 
     def sample(self):
-        now = PyCalendarDateTime.getNowUTC()
+        now = DateTime.getNowUTC()
         now.offsetSeconds(int(self._offset.sample()))
         return now
 
@@ -390,7 +390,7 @@
             60 * 60 * 8 * 6,
             # Standard deviation of 4 workdays
             60 * 60 * 8 * 4)
-        self.now = PyCalendarDateTime.getNow
+        self.now = DateTime.getNow
 
 
     def astimestamp(self, dt):
@@ -406,7 +406,7 @@
         # Find a workday that follows the timestamp
         weekday = when.getDayOfWeek()
         for i in range(NUM_WEEKDAYS):
-            day = when + PyCalendarDuration(days=i)
+            day = when + PyDuration(days=i)
             if (weekday + i) % NUM_WEEKDAYS in self._daysOfWeek:
                 # Joy, a day on which work might occur.  Find the first hour on
                 # this day when work may start.
@@ -419,8 +419,8 @@
 
 
     def sample(self):
-        offset = PyCalendarDuration(seconds=int(self._helperDistribution.sample()))
-        beginning = self.now(PyCalendarTimezone(tzid=self._tzname))
+        offset = PyDuration(seconds=int(self._helperDistribution.sample()))
+        beginning = self.now(Timezone(tzid=self._tzname))
         while offset:
             start, end = self._findWorkAfter(beginning)
             if end - start > offset:
@@ -463,8 +463,7 @@
             index = self._helperDistribution.sample()
             rrule = self._rrules[index]
             if rrule:
-                prop = PyCalendarProperty()
-                prop.parse(rrule)
+                prop = Property.parseText(rrule)
                 return prop
 
         return None

Modified: CalendarServer/trunk/contrib/performance/test_stats.py
===================================================================
--- 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)
@@ -20,8 +20,8 @@
     SQLDuration, LogNormalDistribution, UniformDiscreteDistribution,
     UniformIntegerDistribution, WorkDistribution, quantize,
     RecurrenceDistribution)
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 class SQLDurationTests(TestCase):
     def setUp(self):
@@ -90,21 +90,21 @@
         tzname = "US/Eastern"
         dist = WorkDistribution(["mon", "wed", "thu", "sat"], 10, 20, tzname)
         dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
-        dist.now = lambda tzname = None: PyCalendarDateTime(2011, 5, 29, 18, 5, 36, tzid=tzname)
+        dist.now = lambda tzname = None: DateTime(2011, 5, 29, 18, 5, 36, tzid=tzname)
         value = dist.sample()
         self.assertEqual(
             # Move past three workdays - monday, wednesday, thursday - using 30
             # of the hours, and then five and a half hours into the fourth
             # workday, saturday.  Workday starts at 10am, so the sample value
             # is 3:30pm, ie 1530 hours.
-            PyCalendarDateTime(2011, 6, 4, 15, 30, 0, tzid=PyCalendarTimezone(tzid=tzname)),
+            DateTime(2011, 6, 4, 15, 30, 0, tzid=Timezone(tzid=tzname)),
             value
         )
 
         dist = WorkDistribution(["mon", "tue", "wed", "thu", "fri"], 10, 20, tzname)
         dist._helperDistribution = UniformDiscreteDistribution([35 * 60 * 60 + 30 * 60])
         value = dist.sample()
-        self.assertTrue(isinstance(value, PyCalendarDateTime))
+        self.assertTrue(isinstance(value, DateTime))
 
     # twisted.trial.unittest.FailTest: not equal:
     # a = datetime.datetime(2011, 6, 4, 15, 30, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)

Modified: CalendarServer/trunk/contrib/tools/sortrecurrences.py
===================================================================
--- 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)
@@ -20,7 +20,7 @@
 import os
 import sys
 import traceback
-from pycalendar.calendar import PyCalendar
+from pycalendar.icalendar.calendar import Calendar
 
 def usage(error_msg=None):
     if error_msg:
@@ -72,7 +72,7 @@
                 print("Path does not exist: '%s'. Ignoring." % (arg,))
                 continue
 
-            cal = PyCalendar()
+            cal = Calendar()
             cal.parse(open(arg))
             print(str(cal.serialize()))
 

Modified: CalendarServer/trunk/support/build.sh
===================================================================
--- 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)
@@ -808,7 +808,7 @@
     "${pypi}/p/${n}/${p}.tar.gz";
 
   # XXX actually PyCalendar should be imported in-place.
-  py_dependency -fe -i "src" -r 11458 \
+  py_dependency -fe -i "src" -r 11914 \
     "PyCalendar" "pycalendar" "pycalendar" \
     "${svn_uri_base}/PyCalendar/trunk";
 

Modified: CalendarServer/trunk/twext/enterprise/dal/syntax.py
===================================================================
--- 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)
@@ -1686,6 +1686,7 @@
             SQLFragment(' in %s mode' % (self.mode,)))
 
 
+
 class DatabaseLock(_LockingStatement):
     """
     An SQL exclusive session level advisory lock
@@ -1706,6 +1707,7 @@
         return succeed(None)
 
 
+
 class DatabaseUnlock(_LockingStatement):
     """
     An SQL exclusive session level advisory lock
@@ -1726,6 +1728,7 @@
         return succeed(None)
 
 
+
 class Savepoint(_LockingStatement):
     """
     An SQL 'savepoint' statement.

Modified: CalendarServer/trunk/twext/enterprise/fixtures.py
===================================================================
--- 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)
@@ -194,7 +194,6 @@
         No implementation.
         """
 
-
     def callFromThread(self, thunk, *a, **kw):
         """
         No implementation.
@@ -223,14 +222,16 @@
             self.factory = ConnectionFactory()
             connect = self.factory.connect
         self.connect = connect
-        self.paused             = False
-        self.holders            = []
-        self.pool               = ConnectionPool(connect,
-                                                 maxConnections=2,
-                                                 dialect=self.dialect,
-                                                 paramstyle=self.paramstyle)
+        self.paused = False
+        self.holders = []
+        self.pool = ConnectionPool(
+            connect,
+            maxConnections=2,
+            dialect=self.dialect,
+            paramstyle=self.paramstyle
+        )
         self.pool._createHolder = self.makeAHolder
-        self.clock              = self.pool.reactor = ClockWithThreads()
+        self.clock = self.pool.reactor = ClockWithThreads()
         self.pool.startService()
         test.addCleanup(self.flushHolders)
 
@@ -239,7 +240,7 @@
         """
         Flush all pending C{submit}s since C{pauseHolders} was called.  This
         makes sure the service is stopped and the fake ThreadHolders are all
-        executing their queues so failed tsets can exit cleanly.
+        executing their queues so failed tests can exit cleanly.
         """
         self.paused = False
         for holder in self.holders:

Modified: CalendarServer/trunk/twext/enterprise/queue.py
===================================================================
--- 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)
@@ -115,7 +115,7 @@
     (in the worst case) pass from worker->controller->controller->worker.
     """
 
-    def performWork(table, workID):
+    def performWork(table, workID): #@NoSelf
         """
         @param table: The table where work is waiting.
         @type table: L{TableSyntax}
@@ -371,7 +371,6 @@
         will be taken care of by the job queueing machinery.
         """
 
-
     @classmethod
     def forTable(cls, table):
         """

Modified: CalendarServer/trunk/twext/enterprise/test/test_queue.py
===================================================================
--- 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)
@@ -563,8 +563,8 @@
             t = StringTransport()
             p.makeConnection(t)
             return p, t
-        worker1, trans1 = peer()
-        worker2, trans2 = peer()
+        worker1, _ignore_trans1 = peer()
+        worker2, _ignore_trans2 = peer()
         # Ask the worker to do something.
         worker1.performWork(schema.DUMMY_WORK_ITEM, 1)
         self.assertEquals(worker1.currentLoad, 1)
@@ -678,7 +678,7 @@
         """
         Keep relaying data until there's no more.
         """
-        for x in range(turns):
+        for _ignore_x in range(turns):
             if not (self.pump() or self.pump()):
                 return
 

Modified: CalendarServer/trunk/twext/protocols/test/test_memcache.py
===================================================================
--- 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)
@@ -329,7 +329,7 @@
         def check(result):
             self.assertEquals(result, (0, "bar"))
             self.assertEquals(len(self.clock.calls), 1)
-            for i in range(self.proto.persistentTimeOut):
+            for _ignore_i in range(self.proto.persistentTimeOut):
                 self.clock.advance(1)
             return self.assertFailure(d2, TimeoutError).addCallback(checkTime)
         def checkTime(ignored):

Modified: CalendarServer/trunk/twistedcaldav/__init__.py
===================================================================
--- 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)
@@ -59,12 +59,14 @@
 })
 
 # Do some PyCalendar init
-from pycalendar.calendar import PyCalendar
-from pycalendar.property import PyCalendarProperty
-from pycalendar.value import PyCalendarValue
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.icalendar.property import Property
+from pycalendar.vcard.card import Card
+from pycalendar.value import Value
 
-PyCalendar.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
+Calendar.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
+Card.setPRODID("-//CALENDARSERVER.ORG//NONSGML Version 1//EN")
 
 # These are properties we use directly and we want the default value type set for TEXT
-PyCalendarProperty.registerDefaultValue("X-CALENDARSERVER-PRIVATE-COMMENT", PyCalendarValue.VALUETYPE_TEXT)
-PyCalendarProperty.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", PyCalendarValue.VALUETYPE_TEXT)
+Property.registerDefaultValue("X-CALENDARSERVER-PRIVATE-COMMENT", Value.VALUETYPE_TEXT)
+Property.registerDefaultValue("X-CALENDARSERVER-ATTENDEE-COMMENT", Value.VALUETYPE_TEXT)

Modified: CalendarServer/trunk/twistedcaldav/accounting.py
===================================================================
--- 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)
@@ -42,6 +42,8 @@
         accountingEnabledForPrincipal(principal)
     )
 
+
+
 def accountingEnabledForCategory(category):
     """
     Determine if accounting is enabled for the given category.
@@ -51,6 +53,8 @@
         return False
     return AccountingCategories.get(category, False)
 
+
+
 def accountingEnabledForPrincipal(principal):
     """
     Determine if accounting is enabled for the given principal.
@@ -69,6 +73,8 @@
 
     return False
 
+
+
 def emitAccounting(category, principal, data, tag=None):
     """
     Write the supplied data to the appropriate location for the given
@@ -80,7 +86,7 @@
     @type category: C{tuple}
     @param data: data to write.
     @type data: C{str}
-    """    
+    """
     if isinstance(principal, str):
         principalLogPath = principal
     elif accountingEnabled(category, principal):
@@ -107,7 +113,7 @@
             logDirectory,
             datetime.datetime.now().isoformat()
         )
-    
+
         if not os.path.isdir(os.path.join(logRoot, logDirectory)):
             os.makedirs(os.path.join(logRoot, logDirectory))
             logFilename = "%s-01" % (logFilename,)
@@ -128,7 +134,7 @@
                     log.error("Too many %s accounting files for %s" % (category, principal))
                     return None
                 index += 1
-    
+
         #
         # Now write out the data to the log file
         #
@@ -137,7 +143,7 @@
             logFile.write(data)
         finally:
             logFile.close()
-            
+
         return logFilename
 
     except OSError, e:

Modified: CalendarServer/trunk/twistedcaldav/authkerb.py
===================================================================
--- 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)
@@ -22,7 +22,7 @@
 
     1. An alternative to password based BASIC authentication in which the BASIC credentials are
         verified against Kerberos.
-   
+
     2. The NEGOTIATE mechanism (as defined in http://www.ietf.org/rfc/rfc4559.txt)
         that implements full GSSAPI authentication.
 """
@@ -58,7 +58,7 @@
 
     def __init__(self, principal=None, type=None, hostname=None):
         """
-        
+
         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com at EXAMPLE.COM'). If C{None}
             then the type and hostname arguments are used instead.
         @type service:     str
@@ -82,6 +82,7 @@
 
         self.service, self.realm = self._splitPrincipal(principal)
 
+
     def _splitPrincipal(self, principal):
 
         try:
@@ -93,12 +94,14 @@
         except IndexError:
             self.log.error("Invalid Kerberos principal: %s" % (principal,))
             raise ValueError('Authentication System Failure: Invalid Kerberos principal: %s' % (principal,))
-                
+
         service = "%s@%s" % (servicetype, service,)
         realm = realm
-        
+
         return (service, realm,)
-        
+
+
+
 class BasicKerberosCredentials(credentials.UsernamePassword):
     """
     A set of user/password credentials that checks itself against Kerberos.
@@ -106,7 +109,7 @@
 
     def __init__(self, username, password, service, realm):
         """
-        
+
         @param username:   user name of user to authenticate
         @type username:    str
         @param password:   password for user being authenticated
@@ -117,11 +120,13 @@
         @type hostname:    str
         """
         credentials.UsernamePassword.__init__(self, username, password)
-        
+
         # Convert Kerberos principal spec into service and realm
         self.service = service
         self.default_realm = realm
-        
+
+
+
 class BasicKerberosCredentialFactory(KerberosCredentialFactoryBase):
     """
     Authorizer for insecure Basic (base64-encoded plaintext) authentication.
@@ -134,7 +139,7 @@
 
     def __init__(self, principal=None, type=None, hostname=None):
         """
-        
+
         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com at EXAMPLE.COM'). If C{None}
             then the type and hostname arguments are used instead.
         @type service:     str
@@ -146,9 +151,11 @@
 
         super(BasicKerberosCredentialFactory, self).__init__(principal, type, hostname)
 
+
     def getChallenge(self, _ignore_peer):
         return succeed({'realm': self.realm})
 
+
     def decode(self, response, request): #@UnusedVariable
         try:
             creds = (response + '===').decode('base64')
@@ -161,6 +168,8 @@
             return succeed(c)
         raise error.LoginFailed('Invalid credentials')
 
+
+
 class BasicKerberosCredentialsChecker(object):
     log = Logger()
 
@@ -187,9 +196,11 @@
                     pcreds.authnPrincipal,
                     pcreds.authzPrincipal,
                 ))
-        
+
         raise error.UnauthorizedLogin("Bad credentials for: %s" % (pcreds.authnURI,))
 
+
+
 class NegotiateCredentials(object):
     """
     A set of user/password credentials that checks itself against Kerberos.
@@ -198,10 +209,12 @@
     implements(credentials.ICredentials)
 
     def __init__(self, principal, username):
-        
+
         self.principal = principal
         self.username = username
-        
+
+
+
 class NegotiateCredentialFactory(KerberosCredentialFactoryBase):
     """
     Authorizer for Negotiate authentication (http://www.ietf.org/rfc/rfc4559.txt).
@@ -211,7 +224,7 @@
 
     def __init__(self, principal=None, type=None, hostname=None):
         """
-        
+
         @param principal:  full Kerberos principal (e.g., 'HTTP/server.example.com at EXAMPLE.COM'). If C{None}
             then the type and hostname arguments are used instead.
         @type service:     str
@@ -223,22 +236,24 @@
 
         super(NegotiateCredentialFactory, self).__init__(principal, type, hostname)
 
+
     def getChallenge(self, _ignore_peer):
         return succeed({})
 
+
     def decode(self, base64data, request):
-        
+
         # Init GSSAPI first - we won't specify the service now as we need to accept a target
         # name that is case-insenstive as some clients will use "http" instead of "HTTP"
         try:
-            _ignore_result, context = kerberos.authGSSServerInit("");
+            _ignore_result, context = kerberos.authGSSServerInit("")
         except kerberos.GSSError, ex:
             self.log.error("authGSSServerInit: %s(%s)" % (ex[0][0], ex[1][0],))
             raise error.LoginFailed('Authentication System Failure: %s(%s)' % (ex[0][0], ex[1][0],))
 
         # Do the GSSAPI step and get response and username
         try:
-            kerberos.authGSSServerStep(context, base64data);
+            kerberos.authGSSServerStep(context, base64data)
         except kerberos.GSSError, ex:
             self.log.error("authGSSServerStep: %s(%s)" % (ex[0][0], ex[1][0],))
             kerberos.authGSSServerClean(context)
@@ -264,13 +279,13 @@
         principal = kerberos.authGSSServerUserName(context)
         username = principal
         realmname = ""
-        
+
         # Username may include realm suffix which we want to strip
         if username.find("@") != -1:
             splits = username.split("@", 1)
             username = splits[0]
             realmname = splits[1]
-        
+
         # We currently do not support cross-realm authentication, so we
         # must verify that the realm we got exactly matches the one we expect.
         if realmname != self.realm:
@@ -278,11 +293,11 @@
 
         # Close the context
         try:
-            kerberos.authGSSServerClean(context);
+            kerberos.authGSSServerClean(context)
         except kerberos.GSSError, ex:
             self.log.error("authGSSServerClean: %s" % (ex[0][0], ex[1][0],))
             raise error.LoginFailed('Authentication System Failure %s(%s)' % (ex[0][0], ex[1][0],))
-        
+
         # If we successfully decoded and verified the Kerberos credentials we need to add the Kerberos
         # response data to the outgoing request
 
@@ -299,6 +314,8 @@
 
         return succeed(NegotiateCredentials(principal, username))
 
+
+
 class NegotiateCredentialsChecker(object):
 
     implements(checkers.ICredentialsChecker)
@@ -320,6 +337,5 @@
                 pcreds.authnPrincipal,
                 pcreds.authzPrincipal,
             ))
-        
+
         raise error.UnauthorizedLogin("Bad credentials for: %s" % (pcreds.authnURI,))
-

Modified: CalendarServer/trunk/twistedcaldav/backup.py
===================================================================
--- 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)
@@ -38,19 +38,22 @@
         for x in xrange(0, len(argv)):
             opt = argv[x]
             if opt.startswith('-'):
-                self[opt.strip('-')] = argv[x+1]
+                self[opt.strip('-')] = argv[x + 1]
 
 
+
 def debug(string):
     if VERBOSE:
         print("DEBUG:", string)
 
 
+
 def funclog(string):
     if FUNCLOG:
         print("FUNCLOG:", string)
 
 
+
 def logFuncCall(func):
     def printArgs(args):
         a = []
@@ -60,6 +63,7 @@
 
         return ''.join(a).strip(', ')
 
+
     def printKwargs(kwargs):
         a = []
         for kwarg, value in kwargs:
@@ -67,8 +71,9 @@
 
         return ''.join(a).strip(', ')
 
+
     def _(*args, **kwargs):
-        funclog("%s(%s)" % (func.func_name, 
+        funclog("%s(%s)" % (func.func_name,
                             ', '.join((printArgs(args),
                                        printKwargs(kwargs))).strip(', ')))
 
@@ -77,10 +82,11 @@
         funclog("%s - > %s" % (func.func_name, retval))
 
         return retval
-    
+
     return _
 
 
+
 @logFuncCall
 def readConfig(configFile):
     config = readPlist(configFile + '.default')
@@ -89,14 +95,16 @@
         config.update(readPlist(configFile))
 
     return config
-        
 
+
+
 @logFuncCall
 def mkroot(path):
     root = '/'.join(path.rstrip('/').split('/')[:-1])
     os.makedirs(root)
 
 
+
 @logFuncCall
 def serveradmin(action, service):
     cmd = ' '.join((
@@ -112,6 +120,7 @@
     return status
 
 
+
 @logFuncCall
 def isRunning(service):
     cmd = ' '.join((
@@ -134,21 +143,25 @@
         return False
 
 
+
 @logFuncCall
 def copy(src, dst):
     shutil.copytree(src, dst)
 
 
+
 @logFuncCall
 def move(src, dst):
     os.rename(src, dst)
 
 
+
 @logFuncCall
 def remove(dst):
     shutil.rmtree(dst)
 
 
+
 @logFuncCall
 def purge(root, patterns):
     removed = []
@@ -175,5 +188,5 @@
                     os.remove(full)
 
                     removed.append(full)
-                    
+
     return removed

Modified: CalendarServer/trunk/twistedcaldav/caldavxml.py
===================================================================
--- 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)
@@ -25,8 +25,8 @@
 See draft spec: http://ietf.webdav.org/caldav/draft-dusseault-caldav.txt
 """
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from txdav.xml.element import registerElement, dav_namespace
 from txdav.xml.element import WebDAVElement, PCDATAElement
@@ -110,8 +110,8 @@
         if "start" not in attributes and "end" not in attributes:
             raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
 
-        self.start = PyCalendarDateTime.parseText(attributes["start"]) if "start" in attributes else None
-        self.end = PyCalendarDateTime.parseText(attributes["end"]) if "end" in attributes else None
+        self.start = DateTime.parseText(attributes["start"]) if "start" in attributes else None
+        self.end = DateTime.parseText(attributes["end"]) if "end" in attributes else None
 
 
     def valid(self, level=0):
@@ -139,23 +139,102 @@
 
 
 
-class CalDAVTimeZoneElement (CalDAVTextElement):
+class CalDAVDataMixin(object):
     """
-    CalDAV element containing iCalendar data with a single VTIMEZONE component.
+    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/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
+
     def calendar(self):
         """
-        Returns a calendar component derived from this element, which contains
-        exactly one VTIMEZONE component.
+        Returns a calendar component derived from this element.
         """
-        return iComponent.fromString(str(self))
+        data = self.calendarData()
+        if data:
+            return iComponent.fromString(data, format=self.content_type)
+        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
+
+
+
+class CalDAVTimeZoneElement (CalDAVDataMixin, CalDAVTextElement):
+    """
+    CalDAV element containing iCalendar data with a single VTIMEZONE component.
+    """
+
     def gettimezone(self):
         """
         Get the timezone to use. If none, return UTC timezone.
 
-        @return: the L{PyCalendarTimezone} derived from the VTIMEZONE or utc.
+        @return: the L{Timezone} derived from the VTIMEZONE or utc.
         """
         calendar = self.calendar()
         if calendar is not None:
@@ -164,7 +243,7 @@
                 return tz
 
         # Default to using utc tzinfo
-        return PyCalendarTimezone(utc=True)
+        return Timezone(utc=True)
 
 
     def valid(self):
@@ -231,8 +310,13 @@
     name = "calendar-timezone"
     hidden = True
 
+    allowed_attributes = {
+        "content-type": False,
+        "version"     : False,
+    }
 
 
+
 @registerElement
 class SupportedCalendarComponentSets (CalDAVElement):
     """
@@ -428,7 +512,7 @@
 
 
 @registerElement
-class CalendarData (CalDAVElement):
+class CalendarData (CalDAVDataMixin, CalDAVElement):
     """
     Defines which parts of a calendar component object should be returned by a
     report.
@@ -448,21 +532,6 @@
         "version"     : False,
     }
 
-    @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
-
-
     def __init__(self, *children, **attributes):
         super(CalendarData, self).__init__(*children, **attributes)
 
@@ -515,61 +584,8 @@
                 # optimize them originals away
                 self.children = (data,)
 
-        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"
 
-
-    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
-
-
-
 @registerElement
 class CalendarComponent (CalDAVElement):
     """
@@ -882,8 +898,13 @@
     """
     name = "timezone"
 
+    allowed_attributes = {
+        "content-type": False,
+        "version"     : False,
+    }
 
 
+
 @registerElement
 class TimeRange (CalDAVTimeRangeElement):
     """

Modified: CalendarServer/trunk/twistedcaldav/carddavxml.py
===================================================================
--- 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)
@@ -22,7 +22,7 @@
 This API is considered private to static.py and is therefore subject to
 change.
 
-See draft spec: 
+See draft spec:
 """
 
 from txdav.xml.element import registerElement, dav_namespace
@@ -30,6 +30,7 @@
 from txdav.xml.element import WebDAVEmptyElement, WebDAVTextElement
 from txdav.xml.element import ResourceType, Collection
 
+from twistedcaldav.config import config
 from twistedcaldav.vcard import Component
 
 ##
@@ -50,6 +51,7 @@
     namespace = carddav_namespace
 
 
+
 class CardDAVEmptyElement (WebDAVEmptyElement):
     """
     CardDAV element with no contents.
@@ -57,6 +59,7 @@
     namespace = carddav_namespace
 
 
+
 class CardDAVTextElement (WebDAVTextElement):
     """
     CardDAV element containing PCDATA.
@@ -64,6 +67,93 @@
     namespace = carddav_namespace
 
 
+
+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
+
+
+
 @registerElement
 class AddressBookHomeSet (CardDAVElement):
     """
@@ -73,9 +163,10 @@
     name = "addressbook-home-set"
     hidden = True
 
-    allowed_children = { (dav_namespace, "href"): (0, None) }
+    allowed_children = {(dav_namespace, "href"): (0, None)}
 
 
+
 @registerElement
 class AddressBookDescription (CardDAVTextElement):
     """
@@ -88,6 +179,7 @@
     # May be protected; but we'll let the client set this if they like.
 
 
+
 @registerElement
 class SupportedAddressData (CardDAVElement):
     """
@@ -98,9 +190,10 @@
     hidden = True
     protected = True
 
-    allowed_children = { (carddav_namespace, "address-data-type"): (0, None) }
+    allowed_children = {(carddav_namespace, "address-data-type"): (0, None)}
 
 
+
 @registerElement
 class MaxResourceSize (CardDAVTextElement):
     """
@@ -112,6 +205,7 @@
     protected = True
 
 
+
 @registerElement
 class AddressBook (CardDAVEmptyElement):
     """
@@ -121,6 +215,7 @@
     name = "addressbook"
 
 
+
 @registerElement
 class AddressBookQuery (CardDAVElement):
     """
@@ -130,11 +225,11 @@
     name = "addressbook-query"
 
     allowed_children = {
-        (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),
+        (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),
     }
 
     def __init__(self, *children, **attributes):
@@ -148,9 +243,9 @@
             qname = child.qname()
 
             if qname in (
-                (dav_namespace, "allprop" ),
+                (dav_namespace, "allprop"),
                 (dav_namespace, "propname"),
-                (dav_namespace, "prop"    ),
+                (dav_namespace, "prop"),
             ):
                 if props is not None:
                     raise ValueError("Only one of CardDAV:allprop, CardDAV:propname, CardDAV:prop allowed")
@@ -159,7 +254,7 @@
             elif qname == (carddav_namespace, "filter"):
                 filter = child
             elif qname == (carddav_namespace, "limit"):
-                # type check 
+                # type check
                 child.childOfType(NResults)
                 limit = child
 
@@ -170,11 +265,12 @@
             if filter is None:
                 raise ValueError("CARDDAV:filter required")
 
-        self.props  = props
+        self.props = props
         self.filter = filter
         self.limit = limit
 
 
+
 @registerElement
 class AddressDataType (CardDAVEmptyElement):
     """
@@ -190,8 +286,9 @@
     }
 
 
+
 @registerElement
-class AddressData (CardDAVElement):
+class AddressData (CardDAVDataMixin, CardDAVElement):
     """
     Defines which parts of a address component object should be returned by a
     report.
@@ -201,7 +298,7 @@
 
     allowed_children = {
         (carddav_namespace, "allprop"): (0, 1),
-        (carddav_namespace, "prop"   ): (0, None),
+        (carddav_namespace, "prop"): (0, None),
         PCDATAElement                 : (0, None),
     }
     allowed_attributes = {
@@ -209,27 +306,11 @@
         "version"     : False,
     }
 
-    @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
-
     def __init__(self, *children, **attributes):
         super(AddressData, self).__init__(*children, **attributes)
 
         properties = None
-        data       = None
+        data = None
 
         for child in self.children:
             qname = child.qname()
@@ -256,73 +337,25 @@
                 else:
                     data += child
 
-            else: raise AssertionError("We shouldn't be here")
+            else:
+                raise AssertionError("We shouldn't be here")
 
-
         self.properties = properties
 
         if data is not None:
             try:
                 if properties is not None:
-                    raise ValueError("Only one of allprop, prop (%r) or PCDATA (%r) allowed"% (properties, str(data)))
+                    raise ValueError("Only one of allprop, prop (%r) or PCDATA (%r) allowed" % (properties, str(data)))
             except ValueError:
-                if not data.isWhitespace(): raise
+                if not data.isWhitespace():
+                    raise
             else:
                 # Since we've already combined PCDATA elements, we'd may as well
                 # optimize them originals away
                 self.children = (data,)
 
-        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"
 
-    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
-
-
 @registerElement
 class AllProperties (CardDAVEmptyElement):
     """
@@ -332,6 +365,7 @@
     name = "allprop"
 
 
+
 @registerElement
 class Property (CardDAVEmptyElement):
     """
@@ -362,6 +396,7 @@
             self.novalue = False
 
 
+
 @registerElement
 class Filter (CardDAVElement):
     """
@@ -370,10 +405,11 @@
     """
     name = "filter"
 
-    allowed_children = { (carddav_namespace, "prop-filter"): (0, None) }
-    allowed_attributes = { "test": False }
-        
+    allowed_children = {(carddav_namespace, "prop-filter"): (0, None)}
+    allowed_attributes = {"test": False}
 
+
+
 @registerElement
 class PropertyFilter (CardDAVElement):
     """
@@ -383,9 +419,9 @@
     name = "prop-filter"
 
     allowed_children = {
-        (carddav_namespace, "is-not-defined" ): (0, 1),
-        (carddav_namespace, "text-match"     ): (0, None),
-        (carddav_namespace, "param-filter"   ): (0, None),
+        (carddav_namespace, "is-not-defined"): (0, 1),
+        (carddav_namespace, "text-match"): (0, None),
+        (carddav_namespace, "param-filter"): (0, None),
     }
     allowed_attributes = {
         "name": True,
@@ -393,6 +429,7 @@
     }
 
 
+
 @registerElement
 class ParameterFilter (CardDAVElement):
     """
@@ -402,12 +439,13 @@
     name = "param-filter"
 
     allowed_children = {
-        (carddav_namespace, "is-not-defined" ): (0, 1),
-        (carddav_namespace, "text-match"     ): (0, 1),
+        (carddav_namespace, "is-not-defined"): (0, 1),
+        (carddav_namespace, "text-match"): (0, 1),
     }
-    allowed_attributes = { "name": True }
+    allowed_attributes = {"name": True}
 
 
+
 @registerElement
 class Limit (WebDAVElement):
     """
@@ -416,10 +454,11 @@
     namespace = carddav_namespace
     name = "limit"
     allowed_children = {
-        (carddav_namespace, "nresults" )  : (1, 1),
+        (carddav_namespace, "nresults")  : (1, 1),
     }
 
 
+
 @registerElement
 class NResults (WebDAVTextElement):
     """
@@ -439,6 +478,7 @@
     name = "is-not-defined"
 
 
+
 @registerElement
 class TextMatch (CardDAVTextElement):
     """
@@ -464,6 +504,7 @@
     }
 
 
+
 @registerElement
 class AddressBookMultiGet (CardDAVElement):
     """
@@ -475,10 +516,10 @@
     # To allow for an empty element in a supported-report-set property we need
     # to relax the child restrictions
     allowed_children = {
-        (dav_namespace, "allprop" ): (0, 1),
+        (dav_namespace, "allprop"): (0, 1),
         (dav_namespace, "propname"): (0, 1),
-        (dav_namespace, "prop"    ): (0, 1),
-        (dav_namespace, "href"    ): (0, None),    # Actually ought to be (1, None)
+        (dav_namespace, "prop"): (0, 1),
+        (dav_namespace, "href"): (0, None),    # Actually ought to be (1, None)
     }
 
     def __init__(self, *children, **attributes):
@@ -491,9 +532,9 @@
             qname = child.qname()
 
             if qname in (
-                (dav_namespace, "allprop" ),
+                (dav_namespace, "allprop"),
                 (dav_namespace, "propname"),
-                (dav_namespace, "prop"    ),
+                (dav_namespace, "prop"),
             ):
                 if property is not None:
                     raise ValueError("Only one of DAV:allprop, DAV:propname, DAV:prop allowed")
@@ -502,10 +543,11 @@
             elif qname == (dav_namespace, "href"):
                 resources.append(child)
 
-        self.property  = property
+        self.property = property
         self.resources = resources
 
 
+
 @registerElement
 class NoUIDConflict(CardDAVElement):
     """
@@ -514,9 +556,10 @@
     """
     name = "no-uid-conflict"
 
-    allowed_children = { (dav_namespace, "href"): (1, 1) }
-    
+    allowed_children = {(dav_namespace, "href"): (1, 1)}
 
+
+
 @registerElement
 class SupportedFilter(CardDAVElement):
     """
@@ -527,11 +570,12 @@
     name = "supported-filter"
 
     allowed_children = {
-        (carddav_namespace, "prop-filter" ): (0, None),
+        (carddav_namespace, "prop-filter"): (0, None),
         (carddav_namespace, "param-filter"): (0, None)
     }
-    
 
+
+
 @registerElement
 class DirectoryGateway(CardDAVElement):
     """
@@ -541,17 +585,19 @@
     hidden = True
     protected = True
 
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-    
+    allowed_children = {(dav_namespace, "href"): (0, None)}
 
+
+
 @registerElement
 class Directory(CardDAVEmptyElement):
     """
     CardDAV property on a principal to indicate where the directory resource is.
     """
     name = "directory"
-    
 
+
+
 @registerElement
 class DefaultAddressBookURL (CardDAVElement):
     """
@@ -559,14 +605,17 @@
     """
     name = "default-addressbook-URL"
 
-    allowed_children = { (dav_namespace, "href"): (0, 1) }
+    allowed_children = {(dav_namespace, "href"): (0, 1)}
 
+
+
 ##
 # Extensions to ResourceType
 ##
 
-def _isAddressBook(self): return bool(self.childrenOfType(AddressBook))
+def _isAddressBook(self):
+    return bool(self.childrenOfType(AddressBook))
 ResourceType.isAddressBook = _isAddressBook
 
 ResourceType.addressbook = ResourceType(Collection(), AddressBook())
-ResourceType.directory   = ResourceType(Collection(), AddressBook(), Directory())
+ResourceType.directory = ResourceType(Collection(), AddressBook(), Directory())

Modified: CalendarServer/trunk/twistedcaldav/customxml.py
===================================================================
--- 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)
@@ -34,7 +34,7 @@
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.ical import Component as iComponent
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 
 calendarserver_namespace = "http://calendarserver.org/ns/"
@@ -640,7 +640,7 @@
 
     def __init__(self, *children):
         super(DTStamp, self).__init__(children)
-        self.children = (PCDATAElement(PyCalendarDateTime.getNowUTC().getText()),)
+        self.children = (PCDATAElement(DateTime.getNowUTC().getText()),)
 
 
 

Modified: CalendarServer/trunk/twistedcaldav/database.py
===================================================================
--- 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)
@@ -44,14 +44,15 @@
     """
     A ThreadPool that closes connections for each worker thread
     """
-    
+
     def _worker(self):
         log.debug("Starting ADBAPI thread: %s" % (thread.get_ident(),))
         ThreadPool._worker(self)
         self._closeConnection()
 
+
     def _closeConnection(self):
-        
+
         tid = thread.get_ident()
         log.debug("Closing ADBAPI thread: %s" % (tid,))
 
@@ -59,6 +60,8 @@
         self.pool._close(conn)
         del self.pool.connections[tid]
 
+
+
 class AbstractADBAPIDatabase(object):
     """
     A generic SQL database.
@@ -66,7 +69,7 @@
 
     def __init__(self, dbID, dbapiName, dbapiArgs, persistent, **kwargs):
         """
-        
+
         @param persistent: C{True} if the data in the DB must be perserved during upgrades,
             C{False} if the DB data can be re-created from an external source.
         @type persistent: bool
@@ -77,12 +80,14 @@
         self.dbapikwargs = kwargs
 
         self.persistent = persistent
-        
+
         self.initialized = False
 
+
     def __repr__(self):
         return "<%s %r>" % (self.__class__.__name__, self.pool)
 
+
     @inlineCallbacks
     def open(self):
         """
@@ -92,7 +97,7 @@
         if not self.initialized:
 
             self.pool = ConnectionPool(self.dbapiName, *self.dbapiArgs, **self.dbapikwargs)
-            
+
             # sqlite3 is not thread safe which means we have to close the sqlite3 connections in the same thread that
             # opened them. We need a special thread pool class that has a thread worker function that does a close
             # when a thread is closed.
@@ -126,7 +131,7 @@
                         elif version != self._db_version():
                             log.error("Database %s has different schema (v.%s vs. v.%s)"
                                       % (self.dbID, version, self._db_version()))
-                            
+
                             # Upgrade the DB
                             yield self._db_upgrade(version)
 
@@ -139,8 +144,9 @@
                 self.pool = None
                 raise
 
+
     def close(self):
-        
+
         if self.initialized:
             try:
                 self.pool.close()
@@ -149,9 +155,10 @@
             self.pool = None
             self.initialized = False
 
+
     @inlineCallbacks
     def clean(self):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
@@ -165,14 +172,15 @@
             else:
                 break
 
+
     @inlineCallbacks
     def execute(self, sql, *query_params):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
                 yield self.open()
-    
+
             try:
                 yield self._db_execute(sql, *query_params)
             except Exception, e:
@@ -181,14 +189,15 @@
             else:
                 break
 
+
     @inlineCallbacks
     def executescript(self, script):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
                 yield self.open()
-    
+
             try:
                 yield self._db_execute_script(script)
             except Exception, e:
@@ -197,14 +206,15 @@
             else:
                 break
 
+
     @inlineCallbacks
     def query(self, sql, *query_params):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
                 yield self.open()
-    
+
             try:
                 result = (yield self._db_all_values_for_sql(sql, *query_params))
             except Exception, e:
@@ -215,14 +225,15 @@
 
         returnValue(result)
 
+
     @inlineCallbacks
     def queryList(self, sql, *query_params):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
                 yield self.open()
-            
+
             try:
                 result = (yield self._db_values_for_sql(sql, *query_params))
             except Exception, e:
@@ -233,14 +244,15 @@
 
         returnValue(result)
 
+
     @inlineCallbacks
     def queryOne(self, sql, *query_params):
-        
+
         # Re-try at least once
         for _ignore in (0, 1):
             if not self.initialized:
                 yield self.open()
-    
+
             try:
                 result = (yield self._db_value_for_sql(sql, *query_params))
             except Exception, e:
@@ -251,21 +263,25 @@
 
         returnValue(result)
 
+
     def _db_version(self):
         """
         @return: the schema version assigned to this DB.
         """
         raise NotImplementedError
-        
+
+
     def _db_type(self):
         """
         @return: the collection type assigned to this DB.
         """
         raise NotImplementedError
-        
+
+
     def _test_schema_table(self):
         return self._test_table("CALDAV")
 
+
     @inlineCallbacks
     def _db_init(self):
         """
@@ -275,12 +291,12 @@
 
         # TODO we need an exclusive lock of some kind here to prevent a race condition
         # in which multiple processes try to create the tables.
-        
 
         yield self._db_init_schema_table()
         yield self._db_init_data_tables()
         yield self._db_recreate()
 
+
     @inlineCallbacks
     def _db_init_schema_table(self):
         """
@@ -310,12 +326,14 @@
             """, (self._db_type(),)
         )
 
+
     def _db_init_data_tables(self):
         """
         Initialise the underlying database tables.
         """
         raise NotImplementedError
 
+
     def _db_empty_data_tables(self):
         """
         Delete the database tables.
@@ -323,7 +341,8 @@
 
         # Implementations can override this to re-create data
         pass
-        
+
+
     def _db_recreate(self):
         """
         Recreate the database tables.
@@ -332,12 +351,13 @@
         # Implementations can override this to re-create data
         pass
 
+
     @inlineCallbacks
     def _db_upgrade(self, old_version):
         """
         Upgrade the database tables.
         """
-        
+
         if self.persistent:
             yield self._db_upgrade_data_tables(old_version)
             yield self._db_upgrade_schema()
@@ -346,7 +366,8 @@
             # DB upgrades they SHOULD override this method and handle those for better performance.
             yield self._db_remove()
             yield self._db_init()
-    
+
+
     def _db_upgrade_data_tables(self, old_version):
         """
         Upgrade the data from an older version of the DB.
@@ -372,12 +393,14 @@
         yield self._db_remove_data_tables()
         yield self._db_remove_schema()
 
+
     def _db_remove_data_tables(self):
         """
         Remove all the data from an older version of the DB.
         """
         raise NotImplementedError("Each database must remove its own tables.")
 
+
     @inlineCallbacks
     def _db_remove_schema(self):
         """
@@ -385,6 +408,7 @@
         """
         yield self._db_execute("drop table if exists CALDAV")
 
+
     @inlineCallbacks
     def _db_all_values_for_sql(self, sql, *query_params):
         """
@@ -395,11 +419,12 @@
             resulting from executing C{sql} with C{query_params}.
         @raise AssertionError: if the query yields multiple columns.
         """
-        
+
         sql = self._prepare_statement(sql)
         results = (yield self.pool.runQuery(sql, *query_params))
         returnValue(tuple(results))
 
+
     @inlineCallbacks
     def _db_values_for_sql(self, sql, *query_params):
         """
@@ -411,11 +436,12 @@
             resulting from executing C{sql} with C{query_params}.
         @raise AssertionError: if the query yields multiple columns.
         """
-        
+
         sql = self._prepare_statement(sql)
         results = (yield self.pool.runQuery(sql, *query_params))
         returnValue(tuple([row[0] for row in results]))
 
+
     @inlineCallbacks
     def _db_value_for_sql(self, sql, *query_params):
         """
@@ -433,6 +459,7 @@
             value = row
         returnValue(value)
 
+
     def _db_execute(self, sql, *query_params):
         """
         Execute an SQL operation that returns None.
@@ -442,7 +469,7 @@
         @return: an iterable of tuples for each row resulting from executing
             C{sql} with C{query_params}.
         """
-        
+
         sql = self._prepare_statement(sql)
         return self.pool.runOperation(sql, *query_params)
 
@@ -450,37 +477,43 @@
     Since different databases support different types of columns and modifiers on those we need to
     have an "abstract" way of specifying columns in our code and then map the abstract specifiers to
     the underlying DB's allowed types.
-    
+
     Types we can use are:
-    
+
     integer
     text
     text(n)
     date
     serial
-    
+
     The " unique" modifier can be appended to any of those.
     """
     def _map_column_types(self, type):
         raise NotImplementedError
-        
+
+
     def _create_table(self, name, columns, ifnotexists=False):
         raise NotImplementedError
 
+
     def _test_table(self, name):
         raise NotImplementedError
 
+
     def _create_index(self, name, ontable, columns, ifnotexists=False):
         raise NotImplementedError
 
+
     def _prepare_statement(self, sql):
         raise NotImplementedError
-        
+
+
+
 class ADBAPISqliteMixin(object):
 
     @classmethod
     def _map_column_types(self, coltype):
-        
+
         result = ""
         splits = coltype.split()
         if splits[0] == "integer":
@@ -493,15 +526,16 @@
             result = "date"
         elif splits[0] == "serial":
             result = "integer primary key autoincrement"
-        
+
         if len(splits) > 1 and splits[1] == "unique":
             result += " unique"
-        
+
         return result
 
+
     @inlineCallbacks
     def _create_table(self, name, columns, ifnotexists=False):
-        
+
         colDefs = ["%s %s" % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
         statement = "create table %s%s (%s)" % (
             "if not exists " if ifnotexists else "",
@@ -510,6 +544,7 @@
         )
         yield self._db_execute(statement)
 
+
     @inlineCallbacks
     def _test_table(self, name):
         result = (yield self._db_value_for_sql("""
@@ -518,9 +553,10 @@
         """ % (name,)))
         returnValue(result)
 
+
     @inlineCallbacks
     def _create_index(self, name, ontable, columns, ifnotexists=False):
-        
+
         statement = "create index %s%s on %s (%s)" % (
             "if not exists " if ifnotexists else "",
             name,
@@ -529,6 +565,7 @@
         )
         yield self._db_execute(statement)
 
+
     def _prepare_statement(self, sql):
         # We are going to use the sqlite syntax of :1, :2 etc for our
         # internal statements so we do not need to remap those
@@ -537,10 +574,10 @@
 if pgdb:
 
     class ADBAPIPostgreSQLMixin(object):
-        
+
         @classmethod
         def _map_column_types(self, coltype):
-            
+
             result = ""
             splits = coltype.split()
             if splits[0] == "integer":
@@ -553,32 +590,34 @@
                 result = "date"
             elif splits[0] == "serial":
                 result = "serial"
-            
+
             if len(splits) > 1 and splits[1] == "unique":
                 result += " unique"
-            
+
             return result
-    
+
+
         @inlineCallbacks
         def _create_table(self, name, columns, ifnotexists=False):
-            
+
             colDefs = ["%s %s" % (colname, self._map_column_types(coltype)) for colname, coltype in columns]
             statement = "create table %s (%s)" % (
                 name,
                 ", ".join(colDefs),
             )
-            
+
             try:
                 yield self._db_execute(statement)
             except pgdb.DatabaseError:
-                
+
                 if not ifnotexists:
                     raise
-                
+
                 result = (yield self._test_table(name))
                 if not result:
-                    raise 
-    
+                    raise
+
+
         @inlineCallbacks
         def _test_table(self, name):
             result = (yield self._db_value_for_sql("""
@@ -586,27 +625,29 @@
              where tablename = '%s'
             """ % (name.lower(),)))
             returnValue(result)
-    
+
+
         @inlineCallbacks
         def _create_index(self, name, ontable, columns, ifnotexists=False):
-            
+
             statement = "create index %s on %s (%s)" % (
                 name,
                 ontable,
                 ", ".join(columns),
             )
-            
+
             try:
                 yield self._db_execute(statement)
             except pgdb.DatabaseError:
-                
+
                 if not ifnotexists:
                     raise
-                
+
                 result = (yield self._test_table(name))
                 if not result:
-                    raise 
-    
+                    raise
+
+
         @inlineCallbacks
         def _db_init_schema_table(self):
             """
@@ -614,7 +655,7 @@
             @param db_filename: the file name of the index database.
             @param q:           a database cursor to use.
             """
-    
+
             #
             # CALDAV table keeps track of our schema version and type
             #
@@ -623,7 +664,7 @@
                     ("KEY", "text unique"),
                     ("VALUE", "text unique"),
                 ), True)
-    
+
                 yield self._db_execute(
                     """
                     insert into CALDAV (KEY, VALUE)
@@ -638,7 +679,8 @@
                 )
             except pgdb.DatabaseError:
                 pass
-    
+
+
         def _prepare_statement(self, sql):
             # Convert :1, :2 etc format into %s
             ctr = 1
@@ -649,6 +691,6 @@
 
 else:
     class ADBAPIPostgreSQLMixin(object):
-        
+
         def __init__(self):
             raise ConfigurationError("PostgreSQL module not available.")

Modified: CalendarServer/trunk/twistedcaldav/datafilters/calendardata.py
===================================================================
--- 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)
@@ -19,7 +19,7 @@
 from twistedcaldav.datafilters.filter import CalendarFilter
 from twistedcaldav.dateops import clipPeriod
 from twistedcaldav.ical import Component
-from pycalendar.period import PyCalendarPeriod
+from pycalendar.period import Period
 
 __all__ = [
     "CalendarDataFilter",
@@ -161,7 +161,7 @@
             for property in component.properties("FREEBUSY"):
                 newvalue = []
                 for period in property.value():
-                    clipped = clipPeriod(period.getValue(), PyCalendarPeriod(self.calendardata.freebusy_set.start, self.calendardata.freebusy_set.end))
+                    clipped = clipPeriod(period.getValue(), Period(self.calendardata.freebusy_set.start, self.calendardata.freebusy_set.end))
                     if clipped:
                         newvalue.append(clipped)
                 if len(newvalue):

Modified: CalendarServer/trunk/twistedcaldav/dateops.py
===================================================================
--- 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)
@@ -28,9 +28,9 @@
     "clipPeriod"
 ]
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.period import PyCalendarPeriod
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
+from pycalendar.period import Period
 
 import datetime
 import dateutil.tz
@@ -39,14 +39,14 @@
 
 def normalizeForIndex(dt):
     """
-    Normalize a L{PyCalendarDateTime} object for use in the Index.
+    Normalize a L{DateTime} object for use in the Index.
     Convert to date-time in UTC.
-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @return: the normalized PyCalendarDateTime
+    @param dt: a L{DateTime} object to normalize
+    @return: the normalized DateTime
     """
-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-    
+    if not isinstance(dt, DateTime):
+        raise TypeError("%r is not a DateTime instance" % (dt,))
+
     dt = dt.duplicate()
     if dt.isDateOnly():
         dt.setDateOnly(False)
@@ -59,13 +59,15 @@
         dt.adjustToUTC()
         return dt
 
+
+
 def normalizeToUTC(dt):
     """
-    Normalize a L{PyCalendarDateTime} object to UTC.
+    Normalize a L{DateTime} object to UTC.
     """
-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-    
+    if not isinstance(dt, DateTime):
+        raise TypeError("%r is not a DateTime instance" % (dt,))
+
     dt = dt.duplicate()
     if dt.isDateOnly():
         dt.setDateOnly(False)
@@ -79,16 +81,18 @@
         dt.adjustToUTC()
         return dt
 
+
+
 def normalizeForExpand(dt):
     """
-    Normalize a L{PyCalendarDateTime} object for use with the CalDAV expand option.
+    Normalize a L{DateTime} object for use with the CalDAV expand option.
     Convert to date-time in UTC, leave date only and floating alone.
-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @return: the normalized PyCalendarDateTime
+    @param dt: a L{DateTime} object to normalize
+    @return: the normalized DateTime
     """
-    if not isinstance(dt, PyCalendarDateTime):
-        raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
-    
+    if not isinstance(dt, DateTime):
+        raise TypeError("%r is not a DateTime instance" % (dt,))
+
     dt = dt.duplicate()
     if dt.isDateOnly() or dt.floating():
         return dt
@@ -96,41 +100,49 @@
         dt.adjustToUTC()
         return dt
 
+
+
 def floatoffset(dt, pytz):
     """
     Apply the timezone offset to the supplied time, then force tz to utc. This gives the local
     date-time as if the local tz were UTC. It can be used in floating time comparisons with UTC date-times.
-    
-    @param dt: a L{PyCalendarDateTime} object to normalize
-    @param pytz: a L{PyCalendarTimezone} object to apply offset from
-    @return: the normalized PyCalendarDateTime
+
+    @param dt: a L{DateTime} object to normalize
+    @param pytz: a L{Timezone} object to apply offset from
+    @return: the normalized DateTime
     """
-    
+
     if pytz is None:
-        pytz = PyCalendarTimezone(utc=True)
-    
+        pytz = Timezone(utc=True)
+
     dt = dt.duplicate()
     dt.adjustTimezone(pytz)
     dt.setTimezoneUTC(True)
     return dt
 
+
+
 def adjustFloatingToTimezone(dtadjust, dtcopyfrom, pytz=None):
-    
+
     dtadjust = dtadjust.duplicate()
     dtadjust.setTimezone(pytz if pytz else dtcopyfrom.getTimezone())
     return dtadjust
 
+
+
 def compareDateTime(dt1, dt2, defaulttz=None):
-    
+
     if dt1.floating() and not dt2.floating():
         dt1 = adjustFloatingToTimezone(dt1, dt2, defaulttz)
     elif dt2.floating() and not dt1.floating():
         dt2 = adjustFloatingToTimezone(dt2, dt1, defaulttz)
-    
+
     return dt1.compareDateTime(dt2)
 
-def differenceDateTime(start, end, defaulttz = None):
 
+
+def differenceDateTime(start, end, defaulttz=None):
+
     if start.floating() and not end.floating():
         start = adjustFloatingToTimezone(start, end, defaulttz)
     elif end.floating() and not start.floating():
@@ -138,13 +150,19 @@
 
     return end - start
 
-def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
+
+
+def timeRangesOverlap(start1, end1, start2, end2, defaulttz=None):
     # Can't compare date-time and date only, so normalize
     # to date only if they are mixed.
-    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)
+    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)
 
     # Note that start times are inclusive and end times are not.
     if start1 is not None and start2 is not None:
@@ -163,40 +181,41 @@
     else:
         return False
 
+
+
 def normalizePeriodList(periods):
     """
     Normalize the list of periods by merging overlapping or consecutive ranges
     and sorting the list by each periods start.
-    @param list: a list of tuples of L{PyCalendarPeriod}. The list is changed in place.
+    @param list: a list of tuples of L{Period}. The list is changed in place.
     """
-    
+
     # First sort the list
     def sortPeriods(p1, p2):
         """
         Compare two periods. Sort by their start and then end times.
-        A period is a L{PyCalendarPeriod}.
+        A period is a L{Period}.
         @param p1: first period
         @param p2: second period
         @return: 1 if p1>p2, 0 if p1==p2, -1 if p1<p2
         """
 
-        assert isinstance(p1, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p1,)
-        assert isinstance(p2, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p2,)
-        
-        
+        assert isinstance(p1, Period), "Period is not a Period: %r" % (p1,)
+        assert isinstance(p2, Period), "Period is not a Period: %r" % (p2,)
+
         if p1.getStart() == p2.getStart():
             cmp1 = p1.getEnd()
             cmp2 = p2.getEnd()
         else:
             cmp1 = p1.getStart()
             cmp2 = p2.getStart()
-        
+
         return compareDateTime(cmp1, cmp2)
 
     for period in periods:
         period.adjustToUTC()
     periods.sort(cmp=sortPeriods)
-    
+
     # Now merge overlaps and consecutive periods
     index = None
     p = None
@@ -210,15 +229,17 @@
         ie = periods[i].getEnd()
         if (pe >= periods[i].getStart()):
             if ie > pe:
-                periods[index] = PyCalendarPeriod(periods[index].getStart(), ie)
+                periods[index] = Period(periods[index].getStart(), ie)
                 pe = ie
             periods[i] = None
         else:
             index = i
             p = periods[i]
-            pe =p.getEnd()
+            pe = p.getEnd()
     periods[:] = [x for x in periods if x]
 
+
+
 def clipPeriod(period, clipPeriod):
     """
     Clip the start/end period so that it lies entirely within the clip period.
@@ -234,20 +255,22 @@
 
     if start < clipStart:
         start = clipStart
-    
+
     if end > clipEnd:
         end = clipEnd
-    
+
     if start >= end:
         return None
     else:
         # Try to preserve use of duration in period
-        result = PyCalendarPeriod(start, end)
+        result = Period(start, end)
         result.setUseDuration(period.getUseDuration())
         return result
 
+
+
 def pyCalendarTodatetime(pydt):
-    
+
     if pydt.isDateOnly():
         return datetime.date(year=pydt.getYear(), month=pydt.getMonth(), day=pydt.getDay())
     else:
@@ -261,17 +284,19 @@
             tzinfo=dateutil.tz.tzutc()
         )
 
+
+
 def parseSQLTimestampToPyCalendar(ts):
     """
-    Parse an SQL formated timestamp into a PyCalendarDateTime
+    Parse an SQL formated timestamp into a DateTime
     @param ts: the SQL timestamp
     @type ts: C{str}
-    
-    @return: L{PyCalendarDateTime} result
+
+    @return: L{DateTime} result
     """
-    
+
     # Format is "%Y-%m-%d %H:%M:%S"
-    return PyCalendarDateTime(
+    return DateTime(
         year=int(ts[0:4]),
         month=int(ts[5:7]),
         day=int(ts[8:10]),
@@ -280,22 +305,26 @@
         seconds=int(ts[17:19])
     )
 
+
+
 def parseSQLDateToPyCalendar(ts):
     """
-    Parse an SQL formated date into a PyCalendarDateTime
+    Parse an SQL formated date into a DateTime
     @param ts: the SQL date
     @type ts: C{str}
-    
-    @return: L{PyCalendarDateTime} result
+
+    @return: L{DateTime} result
     """
-    
+
     # Format is "%Y-%m-%d", though Oracle may add zero time which we ignore
-    return PyCalendarDateTime(
+    return DateTime(
         year=int(ts[0:4]),
         month=int(ts[5:7]),
         day=int(ts[8:10])
     )
 
+
+
 def datetimeMktime(dt):
 
     assert isinstance(dt, datetime.date)
@@ -303,4 +332,3 @@
     if dt.tzinfo is None:
         dt.replace(tzinfo=dateutil.tz.tzutc())
     return calendar.timegm(dt.utctimetuple())
-

Modified: CalendarServer/trunk/twistedcaldav/directory/addressbook.py
===================================================================
--- 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)
@@ -56,6 +56,8 @@
             + config.CalDAVComplianceClasses
         )
 
+
+
 class DirectoryAddressBookProvisioningResource (
     ReadOnlyResourceMixIn,
     CalDAVComplianceMixIn,
@@ -65,18 +67,21 @@
     def defaultAccessControlList(self):
         return config.ProvisioningResourceACL
 
+
     def etag(self):
         return succeed(ETag(str(uuid4())))
 
+
     def contentType(self):
         return MimeType("httpd", "unix-directory")
 
 
+
 class DirectoryAddressBookHomeProvisioningResource (
         DirectoryAddressBookProvisioningResource
     ):
     """
-    Resource which provisions address book home collections as needed.    
+    Resource which provisions address book home collections as needed.
     """
     def __init__(self, directory, url, store):
         """
@@ -103,22 +108,27 @@
 
         self.putChild(uidsResourceName, DirectoryAddressBookHomeUIDProvisioningResource(self))
 
+
     def url(self):
         return self._url
 
+
     def listChildren(self):
         return self.directory.recordTypes()
 
+
     def principalCollections(self):
         # FIXME: directory.principalCollection smells like a hack
         # See DirectoryPrincipalProvisioningResource.__init__()
         return self.directory.principalCollection.principalCollections()
 
+
     def principalForRecord(self, record):
         # FIXME: directory.principalCollection smells like a hack
         # See DirectoryPrincipalProvisioningResource.__init__()
         return self.directory.principalCollection.principalForRecord(record)
 
+
     def homeForDirectoryRecord(self, record, request):
         uidResource = self.getChild(uidsResourceName)
         if uidResource is None:
@@ -126,17 +136,20 @@
         else:
             return uidResource.homeResourceForRecord(record, request)
 
+
     ##
     # DAV
     ##
-    
+
     def isCollection(self):
         return True
 
+
     def displayName(self):
         return "addressbooks"
 
 
+
 class DirectoryAddressBookHomeTypeProvisioningResource (
         CommonHomeTypeProvisioningResource,
         DirectoryAddressBookProvisioningResource
@@ -159,6 +172,7 @@
         self.recordType = recordType
         self._parent = parent
 
+
     def url(self):
         return joinURL(self._parent.url(), self.recordType)
 
@@ -177,16 +191,19 @@
             # Not a listable collection
             raise HTTPError(responsecode.FORBIDDEN)
 
+
     def makeChild(self, name):
         return None
 
+
     ##
     # DAV
     ##
-    
+
     def isCollection(self):
         return True
 
+
     def displayName(self):
         return self.recordType
 
@@ -194,13 +211,16 @@
     # ACL
     ##
 
+
     def principalCollections(self):
         return self._parent.principalCollections()
 
+
     def principalForRecord(self, record):
         return self._parent.principalForRecord(record)
 
 
+
 class DirectoryAddressBookHomeUIDProvisioningResource (
         CommonUIDProvisioningResource,
         DirectoryAddressBookProvisioningResource
@@ -210,11 +230,13 @@
 
     enabledAttribute = 'enabledForAddressBooks'
 
+
     def homeResourceCreator(self, record, transaction):
         return DirectoryAddressBookHomeResource.createHomeResource(
             self, record, transaction)
 
 
+
 class DirectoryAddressBookHomeResource (AddressBookHomeResource):
     """
     Address book home collection resource.

Modified: CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- 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)
@@ -35,9 +35,9 @@
 from tempfile import mkstemp, gettempdir
 from random import random
 
-from pycalendar.n import N
-from pycalendar.adr import Adr
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.vcard.n import N
+from pycalendar.vcard.adr import Adr
+from pycalendar.datetime import DateTime
 
 from socket import getfqdn
 
@@ -1494,7 +1494,7 @@
 
             birthdate = self.isoDateStringForDateAttribute(dsattributes.kDS1AttrBirthday)
             if birthdate:
-                vcard.addProperty(Property("BDAY", PyCalendarDateTime.parseText(birthdate, fullISO=True)))
+                vcard.addProperty(Property("BDAY", DateTime.parseText(birthdate, fullISO=True)))
 
             # 3.2 Delivery Addressing Types http://tools.ietf.org/html/rfc2426#section-3.2
             #
@@ -1685,7 +1685,7 @@
             # 3.6.4 REV Type Definition
             revDate = self.isoDateStringForDateAttribute(dsattributes.kDS1AttrModificationTimestamp)
             if revDate:
-                vcard.addProperty(Property("REV", PyCalendarDateTime.parseText(revDate, fullISO=True)))
+                vcard.addProperty(Property("REV", DateTime.parseText(revDate, fullISO=True)))
 
             """
             # UNIMPLEMENTED:

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_aggregate.py
===================================================================
--- 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)
@@ -36,7 +36,8 @@
                 recordTypes.add(prefix + recordType)
         return recordTypes
 
-    def _records(key):
+
+    def _records(key): #@NoSelf
         def get(self):
             records = {}
             for prefix, testClass in testServices:
@@ -58,6 +59,7 @@
 
     recordTypePrefixes = tuple(s[0] for s in testServices)
 
+
     def service(self):
         """
         Returns an IDirectoryService.
@@ -71,9 +73,9 @@
         )
         xmlService.recordTypePrefix = xml_prefix
 
-
         return AggregateDirectoryService((xmlService,), None)
 
+
     def test_setRealm(self):
         """
         setRealm gets propagated to nested services
@@ -82,4 +84,3 @@
         aggregatedService.setRealm("foo.example.com")
         for service in aggregatedService._recordTypes.values():
             self.assertEquals("foo.example.com", service.realmName)
-

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- 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)
@@ -38,6 +38,7 @@
             DirectoryService.recordType_resources,
         )
 
+
     def queryDirectory(self, recordTypes, indexType, indexKey):
 
         self.queried = True
@@ -58,42 +59,47 @@
 
                 if cacheIt:
                     cacheRecord = CachingDirectoryRecord(
-                        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"),
-                    ) 
-                    
+                        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"),
+                    )
+
                     augmentRecord = AugmentRecord(
-                        uid = cacheRecord.guid,
+                        uid=cacheRecord.guid,
                         enabled=True,
-                        enabledForCalendaring = True,
+                        enabledForCalendaring=True,
                     )
-                    
+
                     cacheRecord.addAugmentInformation(augmentRecord)
 
                     self.recordCacheForType(recordType).addRecord(cacheRecord,
                         indexType, indexKey)
 
+
+
 class CachingDirectoryTest(TestCase):
-    
+
     baseGUID = str(uuid4())
 
+
     def setUp(self):
         super(CachingDirectoryTest, self).setUp()
         self.service = TestDirectoryService()
         self.service.queried = False
 
+
     def loadRecords(self, records):
         self.service._initCaches()
         self.service.fakerecords = records
         self.service.queried = False
 
+
     def fakeRecord(
         self,
         fullName,
@@ -109,15 +115,15 @@
             shortNames = (self.shortNameForFullName(fullName),)
             if multinames:
                 shortNames += (fullName,)
-    
+
         if guid is None:
             guid = self.guidForShortName(shortNames[0], recordType=recordType)
         else:
             guid = guid.lower()
-    
+
         if emails is None:
             emails = ("%s at example.com" % (shortNames[0],),)
-    
+
         attrs = {
             "fullName": fullName,
             "guid": guid,
@@ -126,35 +132,38 @@
             "cua": tuple(["mailto:%s" % email for email in emails]),
             "authid": tuple(["Kerberos:%s" % email for email in emails])
         }
-        
+
         if members:
             attrs["members"] = members
-    
+
         if resourceInfo:
             attrs["resourceInfo"] = resourceInfo
-    
+
         return attrs
-    
+
+
     def shortNameForFullName(self, fullName):
         return fullName.lower().replace(" ", "")
-    
+
+
     def guidForShortName(self, shortName, recordType=""):
         return uuidFromName(self.baseGUID, "%s%s" % (recordType, shortName))
 
+
     def dummyRecords(self):
         SIZE = 10
         records = {
             DirectoryService.recordType_users: [
-                self.fakeRecord("User %02d" % x, DirectoryService.recordType_users, multinames=(x>5)) for x in range(1,SIZE+1)
+                self.fakeRecord("User %02d" % x, DirectoryService.recordType_users, multinames=(x > 5)) for x in range(1, SIZE + 1)
             ],
             DirectoryService.recordType_groups: [
-                self.fakeRecord("Group %02d" % x, DirectoryService.recordType_groups) for x in range(1,SIZE+1)
+                self.fakeRecord("Group %02d" % x, DirectoryService.recordType_groups) for x in range(1, SIZE + 1)
             ],
             DirectoryService.recordType_resources: [
-                self.fakeRecord("Resource %02d" % x, DirectoryService.recordType_resources) for x in range(1,SIZE+1)
+                self.fakeRecord("Resource %02d" % x, DirectoryService.recordType_resources) for x in range(1, SIZE + 1)
             ],
             DirectoryService.recordType_locations: [
-                self.fakeRecord("Location %02d" % x, DirectoryService.recordType_locations) for x in range(1,SIZE+1)
+                self.fakeRecord("Location %02d" % x, DirectoryService.recordType_locations) for x in range(1, SIZE + 1)
             ],
         }
         # Add duplicate shortnames
@@ -165,14 +174,17 @@
 
         self.loadRecords(records)
 
+
     def verifyRecords(self, recordType, expectedGUIDs):
-        
+
         records = self.service.listRecords(recordType)
         recordGUIDs = set([record.guid for record in records])
         self.assertEqual(recordGUIDs, expectedGUIDs)
 
+
+
 class GUIDLookups(CachingDirectoryTest):
-    
+
     def test_emptylist(self):
         self.dummyRecords()
 
@@ -180,7 +192,8 @@
         self.verifyRecords(DirectoryService.recordType_groups, set())
         self.verifyRecords(DirectoryService.recordType_resources, set())
         self.verifyRecords(DirectoryService.recordType_locations, set())
-    
+
+
     def test_cacheoneguid(self):
         self.dummyRecords()
 
@@ -200,7 +213,8 @@
 
         # Make sure guid is case-insensitive
         self.assertTrue(self.service.recordWithGUID(self.guidForShortName("user01", recordType=DirectoryService.recordType_users).lower()) is not None)
-        
+
+
     def test_cacheoneshortname(self):
         self.dummyRecords()
 
@@ -224,6 +238,7 @@
         ) is not None)
         self.assertFalse(self.service.queried)
 
+
     def test_cacheoneemail(self):
         self.dummyRecords()
 
@@ -245,6 +260,7 @@
         ) is not None)
         self.assertFalse(self.service.queried)
 
+
     def test_cacheonePrincipalsURLWithUIDS(self):
         self.dummyRecords()
 
@@ -267,6 +283,7 @@
         ) is not None)
         self.assertFalse(self.service.queried)
 
+
     def test_cacheonePrincipalsURLWithUsers(self):
         self.dummyRecords()
 
@@ -288,6 +305,7 @@
         ) is not None)
         self.assertFalse(self.service.queried)
 
+
     def test_cacheoneauthid(self):
         self.dummyRecords()
 
@@ -309,6 +327,7 @@
         ) is not None)
         self.assertFalse(self.service.queried)
 
+
     def test_negativeCaching(self):
         self.dummyRecords()
 
@@ -324,7 +343,6 @@
         self.assertEquals(self.service.recordWithGUID(self.guidForShortName("missing")), None)
         self.assertTrue(self.service.queried)
 
-
         # However, if negativeCaching is on, a miss is recorded as such,
         # preventing a similar queryDirectory( ) until cacheTimeout passes
         self.service.negativeCaching = True
@@ -345,6 +363,7 @@
         self.assertEquals(self.service.recordWithGUID(self.guidForShortName("missing")), None)
         self.assertTrue(self.service.queried)
 
+
     def test_duplicateShortNames(self):
         """
         Verify that when looking up records having duplicate short-names, the record of the
@@ -370,6 +389,7 @@
             "Duplicate")
         self.assertEquals(record.recordType, DirectoryService.recordType_locations)
 
+
     def test_generateMemcacheKey(self):
         """
         Verify keys are correctly generated based on the index type -- if index type is

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_digest.py
===================================================================
--- 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)
@@ -55,7 +55,7 @@
 challengeResponse = ('digest',
                      {'nonce': challengeNonce,
                       'qop': 'auth', 'realm': 'test realm',
-                      'algorithm': 'md5',})
+                      'algorithm': 'md5', })
 
 cnonce = "29fc54aa1641c6fa0e151419361c8f23"
 
@@ -116,6 +116,7 @@
                                           self.namespace2
                                       ))
 
+
     def getDigestResponse(self, challenge, ncount):
         """
         Calculate the response for the given challenge
@@ -146,6 +147,7 @@
                 )
         return expected
 
+
     def getDigestResponseComma(self, challenge, ncount):
         """
         Calculate the response for the given challenge
@@ -176,6 +178,7 @@
                 )
         return expected
 
+
     @inlineCallbacks
     def assertRaisesDeferred(self, exception, f, *args, **kwargs):
         try:
@@ -191,6 +194,7 @@
             raise self.failureException('%s not raised (%r returned)'
                                         % (exception.__name__, result))
 
+
     @inlineCallbacks
     def test_getChallenge(self):
         """
@@ -203,14 +207,15 @@
         self.assertEquals(challenge['qop'], 'auth')
         self.assertEquals(challenge['realm'], 'test realm')
         self.assertEquals(challenge['algorithm'], 'md5')
-        self.assertTrue(challenge.has_key("nonce"))
+        self.assertTrue("nonce" in challenge)
 
         challenge = (yield self.credentialFactories[1].getChallenge(clientAddress))
-        self.assertFalse(challenge.has_key('qop'))
+        self.assertFalse('qop' in challenge)
         self.assertEquals(challenge['realm'], 'test realm')
         self.assertEquals(challenge['algorithm'], 'md5')
-        self.assertTrue(challenge.has_key("nonce"))
+        self.assertTrue("nonce" in challenge)
 
+
     @inlineCallbacks
     def test_response(self):
         """
@@ -219,15 +224,16 @@
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
             self.failUnless(creds.checkPassword('password'))
 
+
     @inlineCallbacks
     def test_multiResponse(self):
         """
@@ -237,23 +243,24 @@
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
             self.failUnless(creds.checkPassword('password'))
-    
+
             clientResponse = authRequest2[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000002"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
             self.failUnless(creds.checkPassword('password'))
 
+
     @inlineCallbacks
     def test_failsWithDifferentMethod(self):
         """
@@ -263,16 +270,17 @@
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse,
                                                   SimpleRequest(None, 'POST', '/')))
             self.failIf(creds.checkPassword('password'))
 
+
     @inlineCallbacks
     def test_noUsername(self):
         """
@@ -287,7 +295,7 @@
                                   namelessAuthRequest,
                                   _trivial_GET()))
             self.assertEquals(str(e), "Invalid response, no username given.")
-    
+
             # Check for an empty username
             e = (yield self.assertRaisesDeferred(error.LoginFailed,
                                   factory.decode,
@@ -295,6 +303,7 @@
                                   _trivial_GET()))
             self.assertEquals(str(e), "Invalid response, no username given.")
 
+
     @inlineCallbacks
     def test_noNonce(self):
         """
@@ -308,6 +317,7 @@
                                   _trivial_GET()))
             self.assertEquals(str(e), "Invalid response, no nonce given.")
 
+
     @inlineCallbacks
     def test_emptyAttribute(self):
         """
@@ -323,6 +333,7 @@
                                   _trivial_GET()))
             self.assertEquals(str(e), "Invalid response, no username given.")
 
+
     @inlineCallbacks
     def test_checkHash(self):
         """
@@ -332,20 +343,21 @@
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
-    
+
             self.failUnless(creds.checkHash(
                     md5('username:test realm:password').hexdigest()))
-    
+
             self.failIf(creds.checkHash(
                     md5('username:test realm:bogus').hexdigest()))
 
+
     @inlineCallbacks
     def test_invalidNonceCount(self):
         """
@@ -359,20 +371,20 @@
 
         for ctr, factory in enumerate(credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse1 = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             clientResponse2 = authRequest2[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000002"),
             )
-    
+
             yield factory.decode(clientResponse1, _trivial_GET())
             yield factory.decode(clientResponse2, _trivial_GET())
-    
+
             if challenge.get('qop') is not None:
                 yield self.assertRaisesDeferred(
                     error.LoginFailed,
@@ -380,7 +392,7 @@
                     clientResponse2,
                     _trivial_GET()
                 )
-                
+
                 challenge = (yield factory.getChallenge(clientAddress))
 
                 clientResponse1 = authRequest1[ctr] % (
@@ -400,6 +412,7 @@
                     _trivial_GET()
                 )
 
+
     @inlineCallbacks
     def test_invalidNonce(self):
         """
@@ -415,12 +428,12 @@
         for ctr, factory in enumerate(credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
             challenge['nonce'] = "noNoncense"
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             request = _trivial_GET()
             yield self.assertRaisesDeferred(
                 error.LoginFailed,
@@ -431,11 +444,12 @@
 
             factory._invalidate(FAKE_STATIC_NONCE)
             response = (yield UnauthorizedResponse.makeResponse(
-                {"Digest":factory},
+                {"Digest": factory},
                 request.remoteAddr
             ))
             response.headers.getHeader("www-authenticate")[0][1]
 
+
     @inlineCallbacks
     def test_oldNonce(self):
         """
@@ -452,12 +466,12 @@
             challenge = (yield factory.getChallenge(clientAddress))
             nonce_count, timestamp = (yield factory.db.get(challenge['nonce']))
             factory.db.set(challenge['nonce'], (nonce_count, timestamp - 2 * digest.DigestCredentialFactory.CHALLENGE_LIFETIME_SECS))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             request = _trivial_GET()
             yield self.assertRaisesDeferred(
                 error.LoginFailed,
@@ -465,15 +479,16 @@
                 clientResponse,
                 request
             )
-            
+
             response = (yield UnauthorizedResponse.makeResponse(
-                {"Digest":factory},
+                {"Digest": factory},
                 request.remoteAddr,
             ))
             wwwhdrs = response.headers.getHeader("www-authenticate")[0][1]
             self.assertTrue('stale' in wwwhdrs, msg="No stale parameter in Digest WWW-Authenticate headers: %s" % (wwwhdrs,))
             self.assertEquals(wwwhdrs['stale'], 'true', msg="stale parameter not set to true in Digest WWW-Authenticate headers: %s" % (wwwhdrs,))
 
+
     def test_incompatibleCalcHA1Options(self):
         """
         Test that the appropriate error is raised when any of the
@@ -500,6 +515,7 @@
                 preHA1=preHA1
                 )
 
+
     @inlineCallbacks
     def test_commaURI(self):
         """
@@ -508,15 +524,16 @@
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequestComma[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponseComma(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
             self.failUnless(creds.checkPassword('password'))
 
+
     @inlineCallbacks
     def test_stale_response(self):
         """
@@ -526,20 +543,20 @@
         class newtime(object):
             def time(self):
                 return theTime
-        from twistedcaldav.directory import digest
-        self.patch(digest, "time", newtime())
+        from twistedcaldav.directory import digest as ddigest
+        self.patch(ddigest, "time", newtime())
 
         for ctr, factory in enumerate(self.credentialFactories):
             challenge = (yield factory.getChallenge(clientAddress))
-    
+
             clientResponse = authRequest1[ctr] % (
                 challenge['nonce'],
                 self.getDigestResponse(challenge, "00000001"),
             )
-    
+
             creds = (yield factory.decode(clientResponse, _trivial_GET()))
             self.failUnless(creds.checkPassword('password'))
-            
+
             theTime += DigestCredentialFactory.CHALLENGE_LIFETIME_SECS + 1
             request = _trivial_GET()
             try:
@@ -555,8 +572,8 @@
                 self.fail("Invalid exception from nonce timeout: %s" % e)
             challenge = (yield factory.getChallenge(request.remoteAddr))
             self.assertTrue(challenge.get("stale") == "true")
-            
 
+
+
 def _trivial_GET():
     return SimpleRequest(None, 'GET', '/')
-

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_directory.py
===================================================================
--- 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)
@@ -121,7 +121,6 @@
         self.count += 1
 
 
-
     def test_expandedMembers(self):
         """
         Make sure expandedMembers( ) returns a complete, flattened set of
@@ -889,7 +888,7 @@
         }
         members = pickle.loads(snapshotFile.getContent())
         self.assertEquals(members, expected)
-        
+
         # "Corrupt" the snapshot and verify it is regenerated properly
         snapshotFile.setContent("xyzzy")
         cache.delete("group-cacher-populated")
@@ -900,8 +899,8 @@
         self.assertTrue(snapshotFile.exists())
         members = pickle.loads(snapshotFile.getContent())
         self.assertEquals(members, expected)
-        
 
+
     def test_autoAcceptMembers(self):
         """
         autoAcceptMembers( ) returns an empty list if no autoAcceptGroup is
@@ -926,6 +925,7 @@
             ])
         )
 
+
     @inlineCallbacks
     def testScheduling(self):
         """
@@ -934,6 +934,7 @@
 
         groupCacher = StubGroupCacher()
 
+
         def decorateTransaction(txn):
             txn._groupCacher = groupCacher
 
@@ -945,15 +946,19 @@
 
     testScheduling.skip = "Fix WorkProposal to track delayed calls and cancel them"
 
+
+
 class StubGroupCacher(object):
     def __init__(self):
         self.called = False
         self.updateSeconds = 99
 
+
     def updateCache(self):
         self.called = True
 
 
+
 class RecordsMatchingTokensTests(TestCase):
 
     @inlineCallbacks
@@ -1038,6 +1043,7 @@
         )
 
 
+
 class GUIDTests(TestCase):
 
     def setUp(self):

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- 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)
@@ -52,7 +52,7 @@
         newUID = "38D8AC00-5490-4425-BE3A-05FFB9862444"
 
         homeResource = "/calendars/users/cdaboo/"
-        
+
         def privs1(result):
             # Change GUID in record
             self.xmlFile.setContent(
@@ -65,10 +65,10 @@
 
             # Now force the calendar home resource to be reset
             self.resetCalendars()
-            
+
             # Make sure new user cannot access old user's calendar home
             return self._checkPrivileges(None, homeResource, davxml.HRef("/principals/__uids__/" + newUID + "/"), davxml.Write, False)
-            
+
         # Make sure current user has access to their calendar home
         d = self._checkPrivileges(None, homeResource, davxml.HRef("/principals/__uids__/" + oldUID + "/"), davxml.Write, True)
         d.addCallback(privs1)

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py
===================================================================
--- 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)
@@ -142,8 +142,6 @@
             record = self.svc.recordWithShortName("users", "odtestcarlene")
             self.assertTrue(record in records)
 
-
-
     if runLDAPTests:
 
         from twistedcaldav.directory.ldapdirectory import LdapDirectoryService
@@ -196,7 +194,6 @@
                 }
                 self.svc = LdapDirectoryService(params)
 
-
     if runODTests:
 
         from twistedcaldav.directory.appleopendirectory import OpenDirectoryService

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_modify.py
===================================================================
--- 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)
@@ -47,6 +47,7 @@
         augmentsFile = os.path.join(testRoot, "augments.xml")
         config.AugmentService.params.xmlFiles = (augmentsFile,)
 
+
     def test_createRecord(self):
         directory = getDirectory()
 
@@ -75,6 +76,7 @@
         record = directory.recordWithUID("location01")
         self.assertNotEquals(record, None)
 
+
     def test_destroyRecord(self):
         directory = getDirectory()
 
@@ -95,6 +97,7 @@
         record = directory.recordWithUID("location01")
         self.assertNotEquals(record, None)
 
+
     def test_updateRecord(self):
         directory = getDirectory()
 
@@ -124,12 +127,14 @@
         record = directory.recordWithUID("location01")
         self.assertNotEquals(record, None)
 
+
     def test_createDuplicateRecord(self):
         directory = getDirectory()
 
         directory.createRecord("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
         self.assertRaises(DirectoryError, directory.createRecord, "resources", guid="resource01", shortNames=("resource01",), uid="resource01")
 
+
     def test_missingShortNames(self):
         directory = getDirectory()
 
@@ -145,6 +150,7 @@
         self.assertEquals(record.shortNames[0], "resource01")
         self.assertEquals(record.fullName, "Resource #1")
 
+
     def test_missingGUID(self):
         directory = getDirectory()
 

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectorybacker.py
===================================================================
--- 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)
@@ -21,7 +21,20 @@
 
 
     def test_multiplePhoneNumbersAndEmailAddresses(self):
-        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 at example.com', 'second at example.com'], u'dsAttrTypeStandard:RealName': 'Amanda Test'}
+        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 at example.com', 'second at example.com'],
+            u'dsAttrTypeStandard:RealName': 'Amanda Test',
+        }
         vcardRecord = VCardRecord(StubService(), attributes)
         vcard = vcardRecord.vCard()
         properties = set([prop.value() for prop in vcard.properties("TEL")])
@@ -30,6 +43,7 @@
         self.assertEquals(properties, set(["amanda at example.com", "second at example.com"]))
 
 
+
 class StubService(object):
     addDSAttrXProperties = False
     directoryBackedAddressBook = None

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py
===================================================================
--- 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)
@@ -17,7 +17,7 @@
 from twisted.internet.defer import inlineCallbacks
 from twistedcaldav.config import config
 from twistedcaldav.directory import calendaruserproxy
-from twistedcaldav.directory.calendaruserproxy import ProxySqliteDB,\
+from twistedcaldav.directory.calendaruserproxy import ProxySqliteDB, \
     ProxyPostgreSQLDB
 from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
 import twistedcaldav.test.util
@@ -28,21 +28,21 @@
     """
     Directory service provisioned principals.
     """
-    
+
     class old_ProxyDB(ProxySqliteDB):
-        
+
         def _db_version(self):
             """
             @return: the schema version assigned to this index.
             """
             return "3"
-            
+
         def _db_init_data_tables(self):
             """
             Initialise the underlying database tables.
             @param q:           a database cursor to use.
             """
-    
+
             #
             # GROUPS table
             #
@@ -55,70 +55,77 @@
                 """
             )
 
+
     class new_ProxyDB(ProxySqliteDB):
-        
+
         def _db_version(self):
             """
             @return: the schema version assigned to this index.
             """
             return "11"
-            
+
+
     class newer_ProxyDB(ProxySqliteDB):
-        
+
         def _db_version(self):
             """
             @return: the schema version assigned to this index.
             """
             return "51"
-    
+
+
     @inlineCallbacks
     def test_normalDB(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = ProxySqliteDB(db_path)
         yield db.setGroupMembers("A", ("B", "C", "D",))
-        
+
         membersA = yield db.getMembers("A")
         membershipsB = yield db.getMemberships("B")
-        
+
         self.assertEqual(membersA, set(("B", "C", "D",)))
         self.assertEqual(membershipsB, set(("A",)))
 
+
     @inlineCallbacks
     def test_normalDBNonAscii(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = ProxySqliteDB(db_path)
         principalID = "Test \xe4\xbd\x90\xe8\x97\xa4"
         yield db.setGroupMembers(principalID, ("B", "C", "D",))
-        
+
         membersA = yield db.getMembers(principalID)
         membershipsB = yield db.getMemberships("B")
-        
+
         self.assertEqual(membersA, set(("B", "C", "D",)))
         self.assertEqual(membershipsB, set((principalID,)))
 
+
     @inlineCallbacks
     def test_DBIndexed(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = ProxySqliteDB(db_path)
         self.assertEqual(set([row[1] for row in (yield db.query("PRAGMA index_list(GROUPS)"))]), set(("GROUPNAMES", "MEMBERS")))
 
+
     @inlineCallbacks
     def test_OldDB(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = self.old_ProxyDB(db_path)
         self.assertEqual(set([row[1] for row in (yield db.query("PRAGMA index_list(GROUPS)"))]), set())
 
+
     @inlineCallbacks
     def test_DBUpgrade(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = self.old_ProxyDB(db_path)
@@ -132,7 +139,7 @@
         self.assertEqual(set([row[1] for row in (yield db.query("PRAGMA index_list(GROUPS)"))]), set())
         db.close()
         db = None
-        
+
         db = ProxySqliteDB(db_path)
 
         membersA = yield db.getMembers("A")
@@ -144,9 +151,10 @@
         db.close()
         db = None
 
+
     @inlineCallbacks
     def test_DBUpgradeNewer(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = self.old_ProxyDB(db_path)
@@ -160,7 +168,7 @@
         self.assertEqual(set([row[1] for row in (yield db.query("PRAGMA index_list(GROUPS)"))]), set())
         db.close()
         db = None
-        
+
         db = self.new_ProxyDB(db_path)
 
         membersA = yield db.getMembers("A")
@@ -172,9 +180,10 @@
         db.close()
         db = None
 
+
     @inlineCallbacks
     def test_DBNoUpgradeNewer(self):
-    
+
         # Get the DB
         db_path = os.path.abspath(self.mktemp())
         db = self.new_ProxyDB(db_path)
@@ -188,7 +197,7 @@
         self.assertEqual(set([row[1] for row in (yield db.query("PRAGMA index_list(GROUPS)"))]), set(("GROUPNAMES", "MEMBERS")))
         db.close()
         db = None
-        
+
         db = self.newer_ProxyDB(db_path)
 
         membersA = yield db.getMembers("A")
@@ -200,40 +209,41 @@
         db.close()
         db = None
 
+
     @inlineCallbacks
     def test_cachingDBInsert(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             db_path = os.path.abspath(self.mktemp())
             db = ProxySqliteDB(db_path)
-            
+
             # Do one insert and check the result
             yield db.setGroupMembers("A", ("B", "C", "D",))
-    
+
             membersA = yield db.getMembers("A")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
             membershipsE = yield db.getMemberships("E")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membershipsB, set(("A",)))
             self.assertEqual(membershipsC, set(("A",)))
             self.assertEqual(membershipsD, set(("A",)))
             self.assertEqual(membershipsE, set(()))
-            
+
             # Change and check the result
             yield db.setGroupMembers("A", ("B", "C", "E",))
-    
+
             membersA = yield db.getMembers("A")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
             membershipsE = yield db.getMemberships("E")
-    
+
             self.assertEqual(membersA, set(("B", "C", "E",)))
             self.assertEqual(membershipsB, set(("A",)))
             self.assertEqual(membershipsC, set(("A",)))
@@ -242,41 +252,42 @@
 
             yield db.clean()
 
+
     @inlineCallbacks
     def test_cachingDBRemove(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             db_path = os.path.abspath(self.mktemp())
             db = ProxySqliteDB(db_path)
-            
+
             # Do one insert and check the result
             yield db.setGroupMembers("A", ("B", "C", "D",))
             yield db.setGroupMembers("X", ("B", "C",))
-    
+
             membersA = yield db.getMembers("A")
             membersX = yield db.getMembers("X")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set(("A", "X",)))
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",)))
-            
+
             # Remove and check the result
             yield db.removeGroup("A")
-    
+
             membersA = yield db.getMembers("A")
             membersX = yield db.getMembers("X")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set())
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set("X",))
@@ -285,33 +296,34 @@
 
             yield db.clean()
 
+
     @inlineCallbacks
     def test_cachingDBRemoveSpecial(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             db_path = os.path.abspath(self.mktemp())
             db = ProxySqliteDB(db_path)
-            
+
             # Do one insert and check the result
             yield db.setGroupMembers("A", ("B", "C", "D",))
             yield db.setGroupMembers("X", ("B", "C",))
-    
+
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-            
+
             # Remove and check the result
             yield db.removeGroup("A")
-    
+
             membersA = yield db.getMembers("A")
             membersX = yield db.getMembers("X")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set())
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set("X",))
@@ -320,41 +332,42 @@
 
             yield db.clean()
 
+
     @inlineCallbacks
     def test_cachingDBRemovePrincipal(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             db_path = os.path.abspath(self.mktemp())
             db = ProxySqliteDB(db_path)
-            
+
             # Do one insert and check the result
             yield db.setGroupMembers("A", ("B", "C", "D",))
             yield db.setGroupMembers("X", ("B", "C",))
-    
+
             membersA = yield db.getMembers("A")
             membersX = yield db.getMembers("X")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set(("A", "X",)))
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",)))
-            
+
             # Remove and check the result
             yield db.removePrincipal("B")
-    
+
             membersA = yield db.getMembers("A")
             membersX = yield db.getMembers("X")
             membershipsB = yield db.getMemberships("B")
             membershipsC = yield db.getMemberships("C")
             membershipsD = yield db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("C", "D",)))
             self.assertEqual(membersX, set(("C",)))
             self.assertEqual(membershipsB, set())
@@ -363,29 +376,30 @@
 
             yield db.clean()
 
+
     @inlineCallbacks
     def test_cachingDBInsertUncached(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             db_path = os.path.abspath(self.mktemp())
             db = ProxySqliteDB(db_path)
-            
+
             # Do one insert and check the result for the one we will remove
             yield db.setGroupMembers("AA", ("BB", "CC", "DD",))
             yield db.getMemberships("DD")
-    
+
             # Change and check the result
             yield db.setGroupMembers("AA", ("BB", "CC", "EE",))
-    
+
             membersAA = yield db.getMembers("AA")
             membershipsBB = yield db.getMemberships("BB")
             membershipsCC = yield db.getMemberships("CC")
             membershipsDD = yield db.getMemberships("DD")
             membershipsEE = yield db.getMemberships("EE")
-    
+
             self.assertEqual(membersAA, set(("BB", "CC", "EE",)))
             self.assertEqual(membershipsBB, set(("AA",)))
             self.assertEqual(membershipsCC, set(("AA",)))
@@ -394,11 +408,13 @@
 
             yield db.clean()
 
+
+
 class ProxyPrincipalDBPostgreSQL (twistedcaldav.test.util.TestCase):
     """
     Directory service provisioned principals.
     """
-    
+
     @inlineCallbacks
     def setUp(self):
 
@@ -406,209 +422,217 @@
         self.db = ProxyPostgreSQLDB(host="localhost", database="proxies")
         yield self.db.clean()
 
+
     @inlineCallbacks
     def tearDown(self):
         yield self.db.close()
         self.db = None
 
+
     @inlineCallbacks
     def test_normalDB(self):
-    
+
         # Get the DB
         yield self.db.clean()
-        
+
         calendaruserproxy.ProxyDBService = self.db
         loader = XMLCalendarUserProxyLoader("/Volumes/Data/Users/cyrusdaboo/Documents/Development/Apple/eclipse/CalendarServer-3/conf/auth/proxies-test.xml")
         yield loader.updateProxyDB()
 
         yield self.db.setGroupMembers("A", ("B", "C", "D",))
-        
+
         membersA = yield self.db.getMembers("A")
         membershipsB = yield self.db.getMemberships("B")
-        
+
         self.assertEqual(membersA, set(("B", "C", "D",)))
         self.assertEqual(membershipsB, set(("A",)))
 
+
     @inlineCallbacks
     def test_DBIndexed(self):
-    
+
         # Get the DB
         yield self.db.clean()
         self.assertTrue((yield self.db.queryOne("select hasindexes from pg_tables where tablename = 'groups'")))
 
+
     @inlineCallbacks
     def test_cachingDBInsert(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             yield self.db.clean()
-            
+
             # Do one insert and check the result
             yield self.db.setGroupMembers("A", ("B", "C", "D",))
-    
+
             membersA = yield self.db.getMembers("A")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
             membershipsE = yield self.db.getMemberships("E")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membershipsB, set(("A",)))
             self.assertEqual(membershipsC, set(("A",)))
             self.assertEqual(membershipsD, set(("A",)))
             self.assertEqual(membershipsE, set(()))
-            
+
             # Change and check the result
             yield self.db.setGroupMembers("A", ("B", "C", "E",))
-    
+
             membersA = yield self.db.getMembers("A")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
             membershipsE = yield self.db.getMemberships("E")
-    
+
             self.assertEqual(membersA, set(("B", "C", "E",)))
             self.assertEqual(membershipsB, set(("A",)))
             self.assertEqual(membershipsC, set(("A",)))
             self.assertEqual(membershipsD, set())
             self.assertEqual(membershipsE, set(("A",)))
 
+
     @inlineCallbacks
     def test_cachingDBRemove(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             yield self.db.clean()
-            
+
             # Do one insert and check the result
             yield self.db.setGroupMembers("A", ("B", "C", "D",))
             yield self.db.setGroupMembers("X", ("B", "C",))
-    
+
             membersA = yield self.db.getMembers("A")
             membersX = yield self.db.getMembers("X")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set(("A", "X",)))
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",)))
-            
+
             # Remove and check the result
             yield self.db.removeGroup("A")
-    
+
             membersA = yield self.db.getMembers("A")
             membersX = yield self.db.getMembers("X")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set())
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set("X",))
             self.assertEqual(membershipsC, set("X",))
             self.assertEqual(membershipsD, set())
 
+
     @inlineCallbacks
     def test_cachingDBRemoveSpecial(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             yield self.db.clean()
-            
+
             # Do one insert and check the result
             yield self.db.setGroupMembers("A", ("B", "C", "D",))
             yield self.db.setGroupMembers("X", ("B", "C",))
-    
+
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-            
+
             # Remove and check the result
             yield self.db.removeGroup("A")
-    
+
             membersA = yield self.db.getMembers("A")
             membersX = yield self.db.getMembers("X")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set())
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set("X",))
             self.assertEqual(membershipsC, set("X",))
             self.assertEqual(membershipsD, set())
 
+
     @inlineCallbacks
     def test_cachingDBRemovePrincipal(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             yield self.db.clean()
-            
+
             # Do one insert and check the result
             yield self.db.setGroupMembers("A", ("B", "C", "D",))
             yield self.db.setGroupMembers("X", ("B", "C",))
-    
+
             membersA = yield self.db.getMembers("A")
             membersX = yield self.db.getMembers("X")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("B", "C", "D",)))
             self.assertEqual(membersX, set(("B", "C",)))
             self.assertEqual(membershipsB, set(("A", "X",)))
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",)))
-            
+
             # Remove and check the result
             yield self.db.removePrincipal("B")
-    
+
             membersA = yield self.db.getMembers("A")
             membersX = yield self.db.getMembers("X")
             membershipsB = yield self.db.getMemberships("B")
             membershipsC = yield self.db.getMemberships("C")
             membershipsD = yield self.db.getMemberships("D")
-    
+
             self.assertEqual(membersA, set(("C", "D",)))
             self.assertEqual(membersX, set(("C",)))
             self.assertEqual(membershipsB, set())
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",),))
 
+
     @inlineCallbacks
     def test_cachingDBInsertUncached(self):
-    
+
         for processType in ("Single", "Combined",):
             config.ProcessType = processType
 
             # Get the DB
             yield self.db.clean()
-            
+
             # Do one insert and check the result for the one we will remove
             yield self.db.setGroupMembers("AA", ("BB", "CC", "DD",))
             yield self.db.getMemberships("DD")
-    
+
             # Change and check the result
             yield self.db.setGroupMembers("AA", ("BB", "CC", "EE",))
-    
+
             membersAA = yield self.db.getMembers("AA")
             membershipsBB = yield self.db.getMemberships("BB")
             membershipsCC = yield self.db.getMemberships("CC")
             membershipsDD = yield self.db.getMemberships("DD")
             membershipsEE = yield self.db.getMemberships("EE")
-    
+
             self.assertEqual(membersAA, set(("BB", "CC", "EE",)))
             self.assertEqual(membershipsBB, set(("AA",)))
             self.assertEqual(membershipsCC, set(("AA",)))

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_resources.py
===================================================================
--- 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)
@@ -41,6 +41,7 @@
 #    def test_loadConfig(self):
 #        directory = getDirectory()
 
+
     def test_recordInPrimaryDirectory(self):
         directory = getDirectory()
 
@@ -48,6 +49,7 @@
         record = directory.recordWithUID("user01")
         self.assertNotEquals(record, None)
 
+
     def test_recordInSupplementalDirectory(self):
         directory = getDirectory()
 
@@ -55,6 +57,7 @@
         record = directory.recordWithUID("resource01")
         self.assertNotEquals(record, None)
 
+
     def test_augments(self):
         directory = getDirectory()
 

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- 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)
@@ -38,49 +38,50 @@
     ))
 
     users = {
-        "admin"      : { "password": "nimda",      "guid": "D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "addresses": () },
-        "wsanchez"   : { "password": "zehcnasw",   "guid": "6423F94A-6B76-4A3A-815B-D52CFD77935D", "addresses": ("mailto:wsanchez at example.com",) },
-        "cdaboo"     : { "password": "oobadc",     "guid": "5A985493-EE2C-4665-94CF-4DFEA3A89500", "addresses": ("mailto:cdaboo at example.com",)   },
-        "lecroy"     : { "password": "yorcel",     "guid": "8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "addresses": ("mailto:lecroy at example.com",)   },
-        "dreid"      : { "password": "dierd",      "guid": "5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "addresses": ("mailto:dreid at example.com",)    },
-        "nocalendar" : { "password": "radnelacon", "guid": "543D28BA-F74F-4D5F-9243-B3E3A61171E5", "addresses": () },
-        "user01"     : { "password": "01user",     "guid": None                                  , "addresses": ("mailto:c4ca4238a0 at example.com",) },
-        "user02"     : { "password": "02user",     "guid": None                                  , "addresses": ("mailto:c81e728d9d at example.com",) },
-    }
+        "admin"      : {"password": "nimda", "guid": "D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "addresses": ()},
+        "wsanchez"   : {"password": "zehcnasw", "guid": "6423F94A-6B76-4A3A-815B-D52CFD77935D", "addresses": ("mailto:wsanchez at example.com",)},
+        "cdaboo"     : {"password": "oobadc", "guid": "5A985493-EE2C-4665-94CF-4DFEA3A89500", "addresses": ("mailto:cdaboo at example.com",)  },
+        "lecroy"     : {"password": "yorcel", "guid": "8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "addresses": ("mailto:lecroy at example.com",)  },
+        "dreid"      : {"password": "dierd", "guid": "5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "addresses": ("mailto:dreid at example.com",)   },
+        "nocalendar" : {"password": "radnelacon", "guid": "543D28BA-F74F-4D5F-9243-B3E3A61171E5", "addresses": ()},
+        "user01"     : {"password": "01user", "guid": None, "addresses": ("mailto:c4ca4238a0 at example.com",)},
+        "user02"     : {"password": "02user", "guid": None, "addresses": ("mailto:c81e728d9d at example.com",)},
+   }
 
     groups = {
-        "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"),
+        "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"),
                                                                                                (DirectoryService.recordType_users , "cdaboo"),
                                                                                                (DirectoryService.recordType_users , "dreid"))},
-        "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"),
+        "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"),
                                                                                                (DirectoryService.recordType_users , "dreid"),
                                                                                                (DirectoryService.recordType_users , "lecroy"))},
-        "both_coasts": { "password": "both_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "right_coast"),
+        "both_coasts": {"password": "both_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "right_coast"),
                                                                                                (DirectoryService.recordType_groups, "left_coast"))},
-        "recursive1_coasts":  { "password": "recursive1_coasts",  "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive2_coasts"),
+        "recursive1_coasts": {"password": "recursive1_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive2_coasts"),
                                                                                                (DirectoryService.recordType_users, "wsanchez"))},
-        "recursive2_coasts":  { "password": "recursive2_coasts",  "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive1_coasts"),
+        "recursive2_coasts": {"password": "recursive2_coasts", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_groups, "recursive1_coasts"),
                                                                                                (DirectoryService.recordType_users, "cdaboo"))},
-        "non_calendar_group": { "password": "non_calendar_group", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),
+        "non_calendar_group": {"password": "non_calendar_group", "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users , "cdaboo"),
                                                                                                (DirectoryService.recordType_users , "lecroy"))},
-    }
+   }
 
     locations = {
-        "mercury": { "password": "mercury", "guid": None, "addresses": ("mailto:mercury at example.com",) },
-        "gemini" : { "password": "gemini",  "guid": None, "addresses": ("mailto:gemini at example.com",)  },
-        "apollo" : { "password": "apollo",  "guid": None, "addresses": ("mailto:apollo at example.com",)  },
-        "orion"  : { "password": "orion",   "guid": None, "addresses": ("mailto:orion at example.com",)   },
-    }
+        "mercury": {"password": "mercury", "guid": None, "addresses": ("mailto:mercury at example.com",)},
+        "gemini" : {"password": "gemini", "guid": None, "addresses": ("mailto:gemini at example.com",)},
+        "apollo" : {"password": "apollo", "guid": None, "addresses": ("mailto:apollo at example.com",)},
+        "orion"  : {"password": "orion", "guid": None, "addresses": ("mailto:orion at example.com",)},
+   }
 
     resources = {
-        "transporter"        : { "password": "transporter",        "guid": None,                 "addresses": ("mailto:transporter at example.com",)        },
-        "ftlcpu"             : { "password": "ftlcpu",             "guid": None,                 "addresses": ("mailto:ftlcpu at example.com",)             },
-        "non_calendar_proxy" : { "password": "non_calendar_proxy", "guid": "non_calendar_proxy", "addresses": ("mailto:non_calendar_proxy at example.com",) },
-    }
+        "transporter"        : {"password": "transporter", "guid": None, "addresses": ("mailto:transporter at example.com",)       },
+        "ftlcpu"             : {"password": "ftlcpu", "guid": None, "addresses": ("mailto:ftlcpu at example.com",)            },
+        "non_calendar_proxy" : {"password": "non_calendar_proxy", "guid": "non_calendar_proxy", "addresses": ("mailto:non_calendar_proxy at example.com",)},
+   }
 
+
     def xmlFile(self):
         """
         Create a L{FilePath} that points to a temporary file containing a copy
@@ -155,10 +156,10 @@
 """
         )
         for recordType, expectedRecords in (
-            ( DirectoryService.recordType_users     , ("admin",) ),
-            ( DirectoryService.recordType_groups    , ()         ),
-            ( DirectoryService.recordType_locations , ()         ),
-            ( DirectoryService.recordType_resources , ()         ),
+            (DirectoryService.recordType_users     , ("admin",)),
+            (DirectoryService.recordType_groups    , ()),
+            (DirectoryService.recordType_locations , ()),
+            (DirectoryService.recordType_resources , ()),
         ):
             # Fault records in
             for name in expectedRecords:
@@ -169,6 +170,7 @@
                 set(expectedRecords)
             )
 
+
     def test_okAutoSchedule(self):
         service = self.service()
 
@@ -201,10 +203,10 @@
         service.augmentService.refresh()
 
         for recordType, expectedRecords in (
-            ( DirectoryService.recordType_users     , ()             ),
-            ( DirectoryService.recordType_groups    , ()             ),
-            ( DirectoryService.recordType_locations , ("my office",) ),
-            ( DirectoryService.recordType_resources , ()             ),
+            (DirectoryService.recordType_users     , ()),
+            (DirectoryService.recordType_groups    , ()),
+            (DirectoryService.recordType_locations , ("my office",)),
+            (DirectoryService.recordType_resources , ()),
         ):
             # Fault records in
             for name in expectedRecords:
@@ -239,12 +241,12 @@
 </accounts>
 """
         )
-        
+
         for recordType, expectedRecords in (
-            ( DirectoryService.recordType_users     , ()                       ),
-            ( DirectoryService.recordType_groups    , ("enabled", "disabled")  ),
-            ( DirectoryService.recordType_locations , ()                       ),
-            ( DirectoryService.recordType_resources , ()                       ),
+            (DirectoryService.recordType_users     , ()),
+            (DirectoryService.recordType_groups    , ("enabled", "disabled")),
+            (DirectoryService.recordType_locations , ()),
+            (DirectoryService.recordType_resources , ()),
         ):
             # Fault records in
             for name in expectedRecords:
@@ -279,13 +281,14 @@
 </accounts>
 """
         )
-        
+
         record = service.recordWithShortName(
             DirectoryService.recordType_locations, "my office")
         self.assertEquals(record.guid, "myoffice")
         self.assertEquals(record.extras["comment"], "This is the comment")
         self.assertEquals(record.extras["capacity"], "40")
 
+
     def test_writeExtras(self):
         service = self.service()
 
@@ -302,7 +305,6 @@
         self.assertEquals(record.extras["comment"], "Test comment")
         self.assertEquals(record.extras["capacity"], "10")
 
-
         service.updateRecord(DirectoryService.recordType_locations, "newguid",
             shortNames=("New office",),
             fullName="My Newer Office",
@@ -333,6 +335,7 @@
         self.assertNotEquals(None, service._lookupInIndex(service.recordType_locations, service.INDEX_TYPE_SHORTNAME, "orion"))
         self.assertEquals(None, service._lookupInIndex(service.recordType_users, service.INDEX_TYPE_CUA, "mailto:nobody at example.com"))
 
+
     def test_repeat(self):
         service = self.service()
         record = service.recordWithShortName(
@@ -342,6 +345,8 @@
         self.assertEquals(record.lastName, "c4ca4238a User 01")
         self.assertEquals(record.emailAddresses, set(['c4ca4238a0 at example.com']))
 
+
+
 class XMLFileSubset (XMLFileBase, TestCase):
     """
     Test the recordTypes subset feature of XMLFile service.
@@ -351,6 +356,7 @@
         DirectoryService.recordType_groups,
     ))
 
+
     def test_recordTypesSubset(self):
         directory = XMLDirectoryService(
             {
@@ -366,4 +372,3 @@
             alwaysStat=True
         )
         self.assertEquals(set(("users", "groups")), set(directory.recordTypes()))
-    

Modified: CalendarServer/trunk/twistedcaldav/directory/test/util.py
===================================================================
--- 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)
@@ -54,12 +54,14 @@
     # For aggregator subclasses
     recordTypePrefixes = ("",)
 
+
     def test_realm(self):
         """
         IDirectoryService.realm
         """
         self.failUnless(self.service().realmName)
 
+
     def test_recordTypes(self):
         """
         IDirectoryService.recordTypes()
@@ -69,15 +71,16 @@
 
         self.assertEquals(set(self.service().recordTypes()), self.recordTypes)
 
+
     def test_recordWithShortName(self):
         """
         IDirectoryService.recordWithShortName()
         """
         for recordType, data in (
-            ( DirectoryService.recordType_users    , self.users     ),
-            ( DirectoryService.recordType_groups   , self.groups    ),
-            ( DirectoryService.recordType_locations, self.locations ),
-            ( DirectoryService.recordType_resources, self.resources ),
+            (DirectoryService.recordType_users    , self.users),
+            (DirectoryService.recordType_groups   , self.groups),
+            (DirectoryService.recordType_locations, self.locations),
+            (DirectoryService.recordType_resources, self.resources),
         ):
             if not data:
                 raise SkipTest("No %s" % (recordType,))
@@ -95,6 +98,7 @@
                     continue
                 self.assertEquals(record, None)
 
+
     def test_recordWithUID(self):
         service = self.service()
         record = None
@@ -108,6 +112,7 @@
         if record is None:
             raise SkipTest("No GUIDs provided to test")
 
+
     def test_recordWithCalendarUserAddress(self):
         service = self.service()
         record = None
@@ -120,6 +125,7 @@
         if record is None:
             raise SkipTest("No calendar user addresses provided to test")
 
+
     def test_groupMembers(self):
         """
         IDirectoryRecord.members()
@@ -138,6 +144,7 @@
                 "Wrong membership for group %r: %s != %s" % (group, result, expected)
             )
 
+
     def test_groupMemberships(self):
         """
         IDirectoryRecord.groups()
@@ -148,8 +155,8 @@
             raise SkipTest("No groups")
 
         for recordType, data in (
-            ( DirectoryService.recordType_users , self.users  ),
-            ( DirectoryService.recordType_groups, self.groups ),
+            (DirectoryService.recordType_users , self.users),
+            (DirectoryService.recordType_groups, self.groups),
         ):
             service = self.service()
             for shortName, info in data.iteritems():
@@ -162,6 +169,7 @@
                     "Wrong groups for %s %r: %s != %s" % (record.recordType, shortName, result, expected)
                 )
 
+
     def recordNames(self, recordType):
         service = self.service()
         names = set()
@@ -176,16 +184,18 @@
 
         return names
 
+
     def allEntries(self):
         for data, _ignore_recordType in (
-            (self.users,     DirectoryService.recordType_users    ),
-            (self.groups,    DirectoryService.recordType_groups   ),
+            (self.users, DirectoryService.recordType_users),
+            (self.groups, DirectoryService.recordType_groups),
             (self.locations, DirectoryService.recordType_locations),
             (self.resources, DirectoryService.recordType_resources),
         ):
             for item in data.iteritems():
                 yield item
 
+
     def compare(self, record, shortName, data):
         def value(key):
             if key in data:
@@ -217,6 +227,7 @@
         if value("name"):
             self.assertEquals(record.fullName, value("name"))
 
+
     def servicePrefix(self):
         service = self.service()
         if hasattr(service, "recordTypePrefix"):
@@ -224,6 +235,8 @@
         else:
             return ""
 
+
+
 class NonCachingTestCase (DirectoryTestCase):
 
     def test_listRecords_user(self):
@@ -235,6 +248,7 @@
 
         self.assertEquals(self.recordNames(DirectoryService.recordType_users), set(self.users.keys()))
 
+
     def test_listRecords_group(self):
         """
         IDirectoryService.listRecords(DirectoryService.recordType_groups)
@@ -244,6 +258,7 @@
 
         self.assertEquals(self.recordNames(DirectoryService.recordType_groups), set(self.groups.keys()))
 
+
     def test_listRecords_locations(self):
         """
         IDirectoryService.listRecords("locations")
@@ -253,6 +268,7 @@
 
         self.assertEquals(self.recordNames(DirectoryService.recordType_locations), set(self.locations.keys()))
 
+
     def test_listRecords_resources(self):
         """
         IDirectoryService.listRecords("resources")
@@ -263,6 +279,7 @@
         self.assertEquals(self.recordNames(DirectoryService.recordType_resources), set(self.resources.keys()))
 
 
+
 class BasicTestCase (DirectoryTestCase):
     """
     Tests a directory implementation with basic auth.
@@ -279,6 +296,8 @@
             userRecord = service.recordWithShortName(DirectoryService.recordType_users, user)
             self.failUnless(userRecord.verifyCredentials(UsernamePassword(user, self.users[user]["password"])))
 
+
+
 # authRequest = {
 #    username="username",
 #    realm="test realm",
@@ -351,6 +370,8 @@
                 else:
                     self.failIf(userRecord.verifyCredentials(credentials))
 
+
+
 def maybeCommit(req):
     class JustForCleanup(object):
         def newTransaction(self, *whatever):

Modified: CalendarServer/trunk/twistedcaldav/dropbox.py
===================================================================
--- 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)
@@ -44,12 +44,15 @@
     def resourceType(self):
         return davxml.ResourceType.dropboxhome #@UndefinedVariable
 
+
     def isCollection(self):
         return True
 
+
     def http_PUT(self, request):
         return responsecode.FORBIDDEN
 
+
     @inlineCallbacks
     def accessControlList(self, request, *args, **kwargs):
         """
@@ -57,7 +60,7 @@
         """
 
         acl = (yield super(DropBoxHomeResource, self).accessControlList(request, *args, **kwargs))
-        
+
         if config.EnableProxyPrincipals:
             owner = (yield self.ownerPrincipal(request))
 
@@ -75,10 +78,12 @@
             )
 
             returnValue(davxml.ACL(*newaces))
-        
+
         else:
             returnValue(acl)
 
+
+
 class DropBoxCollectionResource (DAVResource):
     """
     Drop box resource.
@@ -99,7 +104,7 @@
         calendar collection have the same privileges unless explicitly overridden. The same applies
         to drop box collections as we want all resources (attachments) to have the same privileges as
         the drop box collection.
-        
+
         @param newaces: C{list} of L{ACE} for ACL being set.
         """
         # Add inheritable option to each ACE in the list

Modified: CalendarServer/trunk/twistedcaldav/freebusyurl.py
===================================================================
--- 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)
@@ -47,8 +47,8 @@
 from txdav.caldav.datastore.scheduling.cuaddress import LocalCalendarUser
 from txdav.caldav.datastore.scheduling.scheduler import Scheduler
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
 
 log = Logger()
 
@@ -189,15 +189,15 @@
         # Start/end/duration must be valid iCalendar DATE-TIME UTC or DURATION values
         try:
             if self.start:
-                self.start = PyCalendarDateTime.parseText(self.start)
+                self.start = DateTime.parseText(self.start)
                 if not self.start.utc():
                     raise ValueError()
             if self.end:
-                self.end = PyCalendarDateTime.parseText(self.end)
+                self.end = DateTime.parseText(self.end)
                 if not self.end.utc():
                     raise ValueError()
             if self.duration:
-                self.duration = PyCalendarDuration.parseText(self.duration)
+                self.duration = Duration.parseText(self.duration)
         except ValueError:
             raise HTTPError(ErrorResponse(
                 responsecode.BAD_REQUEST,
@@ -225,12 +225,12 @@
 
         # Now fill in the missing pieces
         if self.start is None:
-            self.start = PyCalendarDateTime.getNowUTC()
+            self.start = DateTime.getNowUTC()
             self.start.setHHMMSS(0, 0, 0)
         if self.duration:
             self.end = self.start + self.duration
         if self.end is None:
-            self.end = self.start + PyCalendarDuration(days=config.FreeBusyURL.TimePeriod)
+            self.end = self.start + Duration(days=config.FreeBusyURL.TimePeriod)
 
         # End > start
         if self.end <= self.start:

Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- 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)
@@ -28,7 +28,6 @@
     "tzexpand",
 ]
 
-import cStringIO as StringIO
 import codecs
 from difflib import unified_diff
 import heapq
@@ -46,31 +45,34 @@
 from txdav.caldav.datastore.scheduling.cuaddress import normalizeCUAddr
 from twistedcaldav.timezones import hasTZ, TimezoneException
 
-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
+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
 
 log = Logger()
 
 iCalendarProductID = "-//CALENDARSERVER.ORG//NONSGML Version 1//EN"
 
-allowedComponents = (
-    "VEVENT",
-    "VTODO",
-    "VTIMEZONE",
-    # "VJOURNAL",
-    "VFREEBUSY",
-    # "VAVAILABILITY",
-)
+allowedStoreComponents = ("VEVENT", "VTODO", "VPOLL",)
+allowedSchedulingComponents = allowedStoreComponents + ("VFREEBUSY",)
+allowedComponents = allowedSchedulingComponents + ("VTIMEZONE",)
 
+def _updateAllowedComponents(allowed):
+    global allowedStoreComponents, allowedSchedulingComponents, allowedComponents
+    allowedStoreComponents = allowed
+    allowedSchedulingComponents = allowedStoreComponents + ("VFREEBUSY",)
+    allowedComponents = allowedSchedulingComponents + ("VTIMEZONE",)
+
+
 # Additional per-user data components - see datafilters.peruserdata.py for details
 PERUSER_COMPONENT = "X-CALENDARSERVER-PERUSER"
 PERUSER_UID = "X-CALENDARSERVER-PERUSER-UID"
@@ -134,19 +136,28 @@
     "LAST-MODIFIED": (None, {"VALUE": "DATE-TIME"}),
     "SEQUENCE": (0, {"VALUE": "INTEGER"}),
     "REQUEST-STATUS": (None, {"VALUE": "TEXT"}),
+
+    "VOTER": (None, {
+        "VALUE": "CAL-ADDRESS",
+        "CUTYPE": "INDIVIDUAL",
+        "ROLE": "REQ-PARTICIPANT",
+        "RSVP": "FALSE",
+        "SCHEDULE-AGENT": "SERVER",
+    }),
 }
 
 # transformations to apply to property values
 normalizePropsValue = {
     "ATTENDEE": normalizeCUAddr,
     "ORGANIZER": normalizeCUAddr,
+    "VOTER": normalizeCUAddr,
 }
 
 ignoredComponents = ("VTIMEZONE", PERUSER_COMPONENT,)
 
 # Used for min/max time-range query limits
-minDateTime = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-maxDateTime = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+minDateTime = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+maxDateTime = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
 
 class InvalidICalendarDataError(ValueError):
     pass
@@ -170,16 +181,16 @@
 
             pyobj = kwargs["pycalendar"]
 
-            if not isinstance(pyobj, PyCalendarProperty):
-                raise TypeError("Not a PyCalendarProperty: %r" % (property,))
+            if not isinstance(pyobj, PyProperty):
+                raise TypeError("Not a Property: %r" % (property,))
 
             self._pycalendar = pyobj
         else:
             # Convert params dictionary to list of lists format used by pycalendar
             valuetype = kwargs.get("valuetype")
-            self._pycalendar = PyCalendarProperty(name, value, valuetype=valuetype)
+            self._pycalendar = PyProperty(name, value, valuetype=valuetype)
             for attrname, attrvalue in params.items():
-                self._pycalendar.addAttribute(PyCalendarAttribute(attrname, attrvalue))
+                self._pycalendar.addParameter(Parameter(attrname, attrvalue))
 
         self._parent = parent
 
@@ -267,7 +278,7 @@
         Returns a set containing parameter names for this property.
         """
         result = set()
-        for pyattrlist in self._pycalendar.getAttributes().values():
+        for pyattrlist in self._pycalendar.getParameters().values():
             for pyattr in pyattrlist:
                 result.add(pyattr.getName())
         return result
@@ -279,27 +290,27 @@
         InvalidICalendarDataError if the parameter has more than one value.
         """
         try:
-            return self._pycalendar.getAttributeValue(name)
+            return self._pycalendar.getParameterValue(name)
         except KeyError:
             return default
 
 
     def hasParameter(self, paramname):
-        return self._pycalendar.hasAttribute(paramname)
+        return self._pycalendar.hasParameter(paramname)
 
 
     def setParameter(self, paramname, paramvalue):
-        self._pycalendar.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
+        self._pycalendar.replaceParameter(Parameter(paramname, paramvalue))
         self._markAsDirty()
 
 
     def removeParameter(self, paramname):
-        self._pycalendar.removeAttributes(paramname)
+        self._pycalendar.removeParameters(paramname)
         self._markAsDirty()
 
 
     def removeAllParameters(self):
-        self._pycalendar.setAttributes({})
+        self._pycalendar.setParameters({})
         self._markAsDirty()
 
 
@@ -308,11 +319,11 @@
         paramname = paramname.upper()
         for attrName in self.parameterNames():
             if attrName.upper() == paramname:
-                for attr in tuple(self._pycalendar.getAttributes()[attrName]):
+                for attr in tuple(self._pycalendar.getParameters()[attrName]):
                     for value in attr.getValues():
                         if value == paramvalue:
                             if not attr.removeValue(value):
-                                self._pycalendar.removeAttributes(paramname)
+                                self._pycalendar.removeParameters(paramname)
         self._markAsDirty()
 
 
@@ -322,8 +333,8 @@
         start/end period.
         The only properties allowed for this query are: COMPLETED, CREATED, DTSTAMP and
         LAST-MODIFIED (caldav -09).
-        @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.
+        @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.
             C{end} may be None, indicating that there is no end date.
         @param defaulttz: the default L{PyTimezone} to use in datetime comparisons.
         @return: True if the property's date/date-time value is within the given time range,
@@ -337,7 +348,7 @@
 
         # get date/date-time value
         dt = self._pycalendar.getValue().getValue()
-        assert isinstance(dt, PyCalendarDateTime), "Not a date/date-time value: %r" % (self,)
+        assert isinstance(dt, DateTime), "Not a date/date-time value: %r" % (self,)
 
         return timeRangesOverlap(dt, None, start, end, defaulttz)
 
@@ -375,66 +386,95 @@
     # Hidden instance.
     HIDDEN_INSTANCE_PROPERTY = "X-CALENDARSERVER-HIDDEN-INSTANCE"
 
+    allowedTypesList = None
+
+
     @classmethod
-    def allFromString(clazz, string):
+    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):
         """
         Just default to reading a single VCALENDAR
         """
-        return clazz.fromString(string)
+        return clazz.fromString(string, format)
 
 
     @classmethod
-    def allFromStream(clazz, stream):
+    def allFromStream(clazz, stream, format=None):
         """
         Just default to reading a single VCALENDAR
         """
-        return clazz.fromStream(stream)
+        return clazz.fromStream(stream, format)
 
 
     @classmethod
-    def fromString(clazz, string):
+    def fromString(clazz, string, format=None):
         """
         Construct a L{Component} from a string.
         @param string: a string containing iCalendar data.
         @return: a L{Component} representing the first component described by
             C{string}.
         """
-        if type(string) is unicode:
-            string = string.encode("utf-8")
-        else:
-            # Valid utf-8 please
-            string.decode("utf-8")
+        return clazz._fromData(string, False, format)
 
-        # No BOMs please
-        if string[:3] == codecs.BOM_UTF8:
-            string = string[3:]
 
-        return clazz.fromStream(StringIO.StringIO(string))
+    @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)
 
 
     @classmethod
-    def fromStream(clazz, stream):
+    def _fromData(clazz, data, isstream, format=None):
         """
         Construct a L{Component} from a stream.
         @param stream: a C{read()}able stream containing iCalendar data.
+        @param format: a C{str} indicating whether the data is iCalendar or jCal
         @return: a L{Component} representing the first component described by
             C{stream}.
         """
-        cal = PyCalendar()
+
+        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"
         try:
-            result = cal.parse(stream)
-        except PyCalendarError, e:
+            result = Calendar.parseData(data, format)
+        except ErrorBase, e:
             errmsg = "%s: %s" % (e.mReason, e.mData,)
             result = None
         if not result:
-            stream.seek(0)
-            raise InvalidICalendarDataError("%s\n%s" % (errmsg, stream.read(),))
-        return clazz(None, pycalendar=cal)
+            if isstream:
+                data.seek(0)
+                data = data.read()
+            raise InvalidICalendarDataError("%s\n%s" % (errmsg, data,))
+        return clazz(None, pycalendar=result)
 
 
     @classmethod
-    def fromIStream(clazz, stream):
+    def fromIStream(clazz, stream, format=None):
         """
         Construct a L{Component} from a stream.
         @param stream: an L{IStream} containing iCalendar data.
@@ -448,7 +488,7 @@
         #   request stream.
         #
         def parse(data):
-            return clazz.fromString(data)
+            return clazz.fromString(data, format)
         return allDataFromStream(IStream(stream), parse)
 
 
@@ -480,8 +520,8 @@
                 pyobj = kwargs["pycalendar"]
 
                 if pyobj is not None:
-                    if not isinstance(pyobj, PyCalendarComponentBase):
-                        raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
+                    if not isinstance(pyobj, ComponentBase):
+                        raise TypeError("Not a ComponentBase: %r" % (pyobj,))
 
                 self._pycalendar = pyobj
             else:
@@ -499,7 +539,7 @@
                 self._parent = None
         else:
             # FIXME: figure out creating an arbitrary component
-            self._pycalendar = PyCalendar(add_defaults=False) if name == "VCALENDAR" else PyCalendar.makeComponent(name, None)
+            self._pycalendar = Calendar(add_defaults=False) if name == "VCALENDAR" else PyComponent.makeComponent(name, None)
             self._parent = None
 
 
@@ -542,13 +582,20 @@
         return self._pycalendar == other._pycalendar
 
 
-    def getTextWithTimezones(self, includeTimezones):
+    def getText(self, format=None):
+        return self.getTextWithTimezones(False, format)
+
+
+    def getTextWithTimezones(self, includeTimezones, format=None):
         """
-        Return text representation and include timezones if the option is on
+        Return text representation and include timezones if the option is on.
         """
         assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (self,)
 
-        return self._pycalendar.getText(includeTimezones=includeTimezones)
+        result = self._pycalendar.getText(includeTimezones=includeTimezones, format=format)
+        if result is None:
+            raise ValueError("Unknown format requested for calendar data.")
+        return result
 
 
     # FIXME: Should this not be in __eq__?
@@ -627,14 +674,14 @@
         This also returns the matching master component if recurrence_id is C{None}.
 
         @param recurrence_id: The RECURRENCE-ID property value to match.
-        @type recurrence_id: L{PyCalendarDateTime}
+        @type recurrence_id: L{DateTime}
         @return: the L{Component} for the overridden component,
             or C{None} if there isn't one.
         """
         assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (self,)
 
         if isinstance(recurrence_id, str):
-            recurrence_id = PyCalendarDateTime.parseText(recurrence_id) if recurrence_id else None
+            recurrence_id = DateTime.parseText(recurrence_id) if recurrence_id else None
 
         for component in self.subcomponents():
             if component.name() in ignoredComponents:
@@ -760,7 +807,7 @@
         Return the start date or date-time for the specified component
         converted to UTC.
         @param component: the Component whose start should be returned.
-        @return: the L{PyCalendarDateTime} for the start.
+        @return: the L{DateTime} for the start.
         """
         dtstart = self.propertyValue("DTSTART")
         return dtstart.duplicateAsUTC() if dtstart is not None else None
@@ -772,7 +819,7 @@
         taking into account the presence or absence of DTEND/DURATION properties.
         The returned date-time is converted to UTC.
         @param component: the Component whose end should be returned.
-        @return: the L{PyCalendarDateTime} for the end.
+        @return: the L{DateTime} for the end.
         """
         dtend = self.propertyValue("DTEND")
         if dtend is None:
@@ -789,7 +836,7 @@
         Return the due date or date-time for the specified component
         converted to UTC. Use DTSTART/DURATION if no DUE property.
         @param component: the Component whose start should be returned.
-        @return: the L{PyCalendarDateTime} for the start.
+        @return: the L{DateTime} for the start.
         """
         due = self.propertyValue("DUE")
         if due is None:
@@ -827,7 +874,7 @@
         """
         Return the recurrence-id for the specified component.
         @param component: the Component whose r-id should be returned.
-        @return: the L{PyCalendarDateTime} for the r-id.
+        @return: the L{DateTime} for the r-id.
         """
         rid = self.propertyValue("RECURRENCE-ID")
         return rid.duplicateAsUTC() if rid is not None else None
@@ -1086,7 +1133,7 @@
         to match the new limit, remove RDATEs/EXDATEs and overridden components beyond the limit.
 
         @param rid: the recurrence-id limit
-        @type rid: L{PyCalendarDateTime}
+        @type rid: L{DateTime}
         """
 
         if not self.isRecurring():
@@ -1148,7 +1195,7 @@
         match any RRULE pattern.
 
         @param rid: the recurrence-id limit
-        @type rid: L{PyCalendarDateTime}
+        @type rid: L{DateTime}
         """
 
         if not self.isRecurring():
@@ -1169,7 +1216,7 @@
                     rrule_expanded = []
                     rrule.expand(
                         master.propertyValue("DTSTART"),
-                        PyCalendarPeriod(PyCalendarDateTime(1900, 1, 1), upperlimit),
+                        Period(DateTime(1900, 1, 1), upperlimit),
                         rrule_expanded,
                     )
                     for i in sorted(rrule_expanded):
@@ -1244,14 +1291,14 @@
         instance in the specified range. Date-times are converted to UTC. A
         new calendar object is returned.
 
-        @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.
+        @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.
         @return: the L{Component} for the new calendar with expanded instances.
         """
 
         if timezone is not None and isinstance(timezone, Component):
-            pytz = PyCalendarTimezone(tzid=timezone.propertyValue("TZID"))
+            pytz = Timezone(tzid=timezone.propertyValue("TZID"))
         else:
             pytz = timezone
 
@@ -1297,7 +1344,7 @@
         # Convert all datetime properties to UTC unless they are floating
         for property in newcomp.properties():
             value = property.value()
-            if isinstance(value, PyCalendarDateTime) and value.local():
+            if isinstance(value, DateTime) and value.local():
                 property.removeParameter("TZID")
                 property.setValue(value.duplicateAsUTC())
 
@@ -1324,7 +1371,7 @@
         breathing room to return results for future instances.
 
         @param limit: the max datetime to cache up to.
-        @type limit: L{PyCalendarDateTime}
+        @type limit: L{DateTime}
         """
 
         # Checked for cached values first
@@ -1335,7 +1382,7 @@
                 # so return cached instances
                 return self.cachedInstances
 
-        lookAheadLimit = limit + PyCalendarDuration(days=365)
+        lookAheadLimit = limit + Duration(days=365)
         self.cachedInstances = self.expandTimeRanges(
             lookAheadLimit,
             ignoreInvalidInstances=ignoreInvalidInstances
@@ -1349,7 +1396,7 @@
         contained within this VCALENDAR component. We will assume
         that this component has already been validated as a CalDAV resource
         (i.e. only one type of component, all with the same UID)
-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
+        @param limit: L{DateTime} value representing the end of the expansion.
         @param ignoreInvalidInstances: C{bool} whether to ignore instance errors.
         @return: a set of Instances for each recurrence in the set.
         """
@@ -1368,14 +1415,14 @@
         @param componentSet: the set of components that are to make up the
                 recurrence set. These MUST all be components with the same UID
                 and type, forming a proper recurring set.
-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
+        @param limit: L{DateTime} value representing the end of the expansion.
 
         @param componentSet: the set of components that are to make up the recurrence set.
             These MUST all be components with the same UID and type, forming a proper
             recurring set.
         @type componentSet: C{list}
         @param limit: the end of the expansion
-        @type limit: L{PyCalendarDateTime}
+        @type limit: L{DateTime}
         @param ignoreInvalidInstances: whether or not invalid recurrences raise an exception
         @type ignoreInvalidInstances: C{bool}
         @param normalizeFunction: a function used to normalize date/time values in instances
@@ -1451,7 +1498,7 @@
         There is always some new thing that will surprise you.
 
         @param rid: recurrence-id value
-        @type rid: L{PyCalendarDateTime} or C{str}
+        @type rid: L{DateTime} or C{str}
         @param allowCancelled: whether to allow a STATUS:CANCELLED override
         @type allowCancelled: C{bool}
         @param allowExcluded: whether to derive an instance for an existing EXDATE
@@ -1469,7 +1516,7 @@
             return None
 
         if isinstance(rid, str):
-            rid = PyCalendarDateTime.parseText(rid) if rid else None
+            rid = DateTime.parseText(rid) if rid else None
 
         # TODO: Check that the recurrence-id is a valid instance
         # For now we just check that there is no matching EXDATE
@@ -1586,7 +1633,7 @@
             # Pre-cache instance expansion up to the highest rid
             highest_rid = max(non_master_rids)
             self.cacheExpandedTimeRanges(
-                highest_rid + PyCalendarDuration(days=1),
+                highest_rid + Duration(days=1),
                 ignoreInvalidInstances=ignoreInvalidInstances
             )
         for rid in rids:
@@ -1600,7 +1647,7 @@
         Test whether the specified recurrence-id is a valid instance in this event.
 
         @param rid: recurrence-id value
-        @type rid: L{PyCalendarDateTime}
+        @type rid: L{DateTime}
 
         @return: C{bool}
         """
@@ -1984,12 +2031,12 @@
 
     def gettimezone(self):
         """
-        Get the PyCalendarTimezone for a Timezone component.
+        Get the Timezone for a Timezone component.
 
-        @return: L{PyCalendarTimezone} if this is a VTIMEZONE, otherwise None.
+        @return: L{Timezone} if this is a VTIMEZONE, otherwise None.
         """
         if self.name() == "VTIMEZONE":
-            return PyCalendarTimezone(tzid=self._pycalendar.getID())
+            return Timezone(tzid=self._pycalendar.getID())
         elif self.name() == "VCALENDAR":
             for component in self.subcomponents():
                 if component.name() == "VTIMEZONE":
@@ -2137,6 +2184,10 @@
         return is_server
 
 
+    def recipientPropertyName(self):
+        return "VOTER" if self.name() == "VPOLL" else "ATTENDEE"
+
+
     def getAttendees(self):
         """
         Get the attendee value. Works on either a VCALENDAR or on a component.
@@ -2152,7 +2203,7 @@
                     return component.getAttendees()
         else:
             # Find the property values
-            return [p.value() for p in self.properties("ATTENDEE")]
+            return [p.value() for p in self.properties(self.recipientPropertyName())]
 
         return None
 
@@ -2179,7 +2230,7 @@
             result = ()
             attendees = set()
             rid = self.getRecurrenceIDUTC()
-            for attendee in tuple(self.properties("ATTENDEE")):
+            for attendee in tuple(self.properties(self.recipientPropertyName())):
 
                 if onlyScheduleAgentServer:
                     if attendee.hasParameter("SCHEDULE-AGENT"):
@@ -2195,6 +2246,27 @@
             return result
 
 
+    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
+
+
     def getAttendeeProperty(self, match):
         """
         Get the attendees matching a value. Works on either a VCALENDAR or on a component.
@@ -2217,7 +2289,7 @@
                         return attendee
         else:
             # Find the primary subcomponent
-            for attendee in self.properties("ATTENDEE"):
+            for attendee in self.properties(self.recipientPropertyName()):
                 if normalizeCUAddr(attendee.value()) in test:
                     return attendee
 
@@ -2260,7 +2332,7 @@
                         yield attendee
         else:
             # Find the primary subcomponent
-            for attendee in self.properties("ATTENDEE"):
+            for attendee in self.properties(self.recipientPropertyName()):
                 yield attendee
 
 
@@ -2641,7 +2713,7 @@
         for component in self.subcomponents():
             if component.name() in ignoredComponents:
                 continue
-            [component.removeProperty(p) for p in tuple(component.properties("ATTENDEE")) if p.value().lower() != attendee.lower()]
+            [component.removeProperty(p) for p in tuple(component.properties(component.recipientPropertyName())) if p.value().lower() != attendee.lower()]
 
 
     def removeAllButTheseAttendees(self, attendees):
@@ -2656,7 +2728,7 @@
         for component in self.subcomponents():
             if component.name() in ignoredComponents:
                 continue
-            [component.removeProperty(p) for p in tuple(component.properties("ATTENDEE")) if p.value().lower() not in attendees]
+            [component.removeProperty(p) for p in tuple(component.properties(component.recipientPropertyName())) if p.value().lower() not in attendees]
 
 
     def hasAlarm(self):
@@ -2977,7 +3049,7 @@
             # Bump all components
             self.replacePropertyInAllComponents(Property("SEQUENCE", newseq))
 
-        self.replacePropertyInAllComponents(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+        self.replacePropertyInAllComponents(Property("DTSTAMP", DateTime.getNowUTC()))
 
 
     def sequenceInSync(self, oldcalendar):
@@ -3059,7 +3131,7 @@
             dtend = self.getProperty("DTEND")
             duration = self.getProperty("DURATION")
 
-            timeRange = PyCalendarPeriod(
+            timeRange = Period(
                 start=dtstart.value(),
                 end=dtend.value()    if dtend is not None else None,
                 duration=duration.value() if duration is not None else None,
@@ -3163,7 +3235,8 @@
                 continue
             for prop in itertools.chain(
                 component.properties("ORGANIZER"),
-                component.properties("ATTENDEE")
+                component.properties("ATTENDEE"),
+                component.properties("VOTER")
             ):
 
                 # Check that we can lookup this calendar user address - if not
@@ -3261,7 +3334,11 @@
                     else:
                         prop.removeParameter("EMAIL")
 
+            # For VPOLL also do immediate children
+            if component.name() == "VPOLL":
+                component.normalizeCalendarUserAddresses(lookupFunction, principalFunction, toUUID)
 
+
     def allPerUserUIDs(self):
 
         results = set()
@@ -3311,7 +3388,7 @@
         Determine whether an event exists completely prior to a given moment.
 
         @param limit: the moment to compare against.
-        @type limit: L{PyCalendarDateTime}
+        @type limit: L{DateTime}
 
         @return: a C{bool}, True if the event has any instances occurring after
         limit, False otherwise.
@@ -3369,13 +3446,13 @@
     start.setDateOnly(False)
     if tzexpanded:
         if start != tzexpanded[0][0]:
-            results.append((str(start), PyCalendarUTCOffsetValue(tzexpanded[0][1]).getText(),))
+            results.append((str(start), UTCOffsetValue(tzexpanded[0][1]).getText(),))
     else:
-        results.append((str(start), PyCalendarUTCOffsetValue(tzcomp._pycalendar.getTimezoneOffsetSeconds(start)).getText(),))
+        results.append((str(start), UTCOffsetValue(tzcomp._pycalendar.getTimezoneOffsetSeconds(start)).getText(),))
     for tzstart, _ignore_tzoffsetfrom, tzoffsetto in tzexpanded:
         results.append((
             tzstart.getText(),
-            PyCalendarUTCOffsetValue(tzoffsetto).getText(),
+            UTCOffsetValue(tzoffsetto).getText(),
         ))
 
     return results
@@ -3388,7 +3465,7 @@
     time range.
 
     @param tzdata: the iCalendar data containing a VTIMEZONE.
-    @type tzdata: L{PyCalendar}
+    @type tzdata: L{Calendar}
     @param start: date for the start of the expansion.
     @type start: C{date}
     @param end: date for the end of the expansion.

Modified: CalendarServer/trunk/twistedcaldav/icaldav.py
===================================================================
--- 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)
@@ -29,14 +29,14 @@
     """
     CalDAV resource.
     """
-    def isCalendarCollection():
+    def isCalendarCollection(): #@NoSelf
         """
         (CalDAV-access-10, Section 4.2)
         @return: True if this resource is a calendar collection, False
             otherwise.
         """
 
-    def isSpecialCollection(collectiontype):
+    def isSpecialCollection(collectiontype): #@NoSelf
         """
         (CalDAV-access-10, Section 4.2)
         @param collectiontype: L{WebDAVElement} for the collection type to test for.
@@ -44,30 +44,30 @@
             False otherwise.
         """
 
-    def isPseudoCalendarCollection():
+    def isPseudoCalendarCollection(): #@NoSelf
         """
         @return: True if this resource is a calendar collection like (e.g.
             a regular calendar collection or schedule inbox/outbox), False
             otherwise.
         """
 
-    def findCalendarCollections(depth):
+    def findCalendarCollections(depth): #@NoSelf
         """
         Returns an iterable of child calendar collection resources for the given
         depth.
-        Because resources do not know their request URIs, chidren are returned
+        Because resources do not know their request URIs, children are returned
         as tuples C{(resource, uri)}, where C{resource} is the child resource
         and C{uri} is a URL path relative to this resource.
         @param depth: the search depth (one of "0", "1", or "infinity")
         @return: an iterable of tuples C{(resource, uri)}.
         """
 
-    def createCalendar(request):
+    def createCalendar(request): #@NoSelf
         """
         Create a calendar collection for this resource.
         """
 
-    def iCalendar():
+    def iCalendar(): #@NoSelf
         """
         Instantiate an iCalendar component object representing this resource or
         its child with the given name.
@@ -78,52 +78,42 @@
         @return: a L{twistedcaldav.ical.Component} of type C{"VCALENDAR"}.
         """
 
-    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.
 
-        @return: a string containing iCalendar text with a top-level component
-            of type C{"VCALENDAR"}.
-        """
 
 class ICalendarPrincipalResource(IDAVResource):
     """
     CalDAV principle resource.
     """
-    def principalUID():
+    def principalUID(): #@NoSelf
         """
         @return: the user id for this principal.
         """
 
-    def calendarHomeURLs():
+    def calendarHomeURLs(): #@NoSelf
         """
         @return: a list of calendar home URLs for this principal's calendar user.
         """
 
-    def calendarUserAddresses():
+    def calendarUserAddresses(): #@NoSelf
         """
         @return: a list of calendar user addresses for this principal's calendar
             user.
         """
 
-    def calendarFreeBusyURIs(self, request):
+    def calendarFreeBusyURIs(request): #@NoSelf
         """
         @param request: the request being processed.
         @return: a L{Deferred} list of URIs for calendars that contribute to
             free-busy for this principal's calendar user.
         """
 
-    def scheduleInboxURL():
+    def scheduleInboxURL(): #@NoSelf
         """
         Get the schedule INBOX URL for this principal's calendar user.
         @return: a string containing the URL from the schedule-inbox-URL property.
         """
 
-    def scheduleOutboxURL():
+    def scheduleOutboxURL(): #@NoSelf
         """
         Get the schedule OUTBOX URL for this principal's calendar user.
         @return: a string containing the URL from the schedule-outbox-URL property.

Modified: CalendarServer/trunk/twistedcaldav/instance.py
===================================================================
--- 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)
@@ -21,10 +21,10 @@
 from twistedcaldav.config import config
 from twistedcaldav.dateops import normalizeForIndex, differenceDateTime
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.period import Period
+from pycalendar.timezone import Timezone
 
 class TooManyInstancesError(Exception):
 
@@ -80,7 +80,7 @@
             (trigger, related, repeat, duration) = alarm.getTriggerDetails()
 
             # Handle relative vs absolute triggers
-            if isinstance(trigger, PyCalendarDateTime):
+            if isinstance(trigger, DateTime):
                 # Absolute trigger
                 start = trigger
             else:
@@ -135,7 +135,7 @@
         @param componentSet: the set of components that are to make up the
                 recurrence set. These MUST all be components with the same UID
                 and type, forming a proper recurring set.
-        @param limit: L{PyCalendarDateTime} value representing the end of the expansion.
+        @param limit: L{DateTime} value representing the end of the expansion.
         """
 
         # Look at each component type
@@ -232,10 +232,10 @@
         if end is None:
             if not start.isDateOnly():
                 # Timed event with zero duration
-                duration = PyCalendarDuration(days=0)
+                duration = Duration(days=0)
             else:
                 # All day event default duration is one day
-                duration = PyCalendarDuration(days=1)
+                duration = Duration(days=1)
             end = start + duration
         else:
             duration = differenceDateTime(start, end)
@@ -248,7 +248,7 @@
         Add the specified master VEVENT Component to the instance list, expanding it
         within the supplied time range.
         @param component: the Component to expand
-        @param limit: the end L{PyCalendarDateTime} for expansion
+        @param limit: the end L{DateTime} for expansion
         """
 
         details = self._getMasterEventDetails(component)
@@ -330,7 +330,7 @@
         Add the specified master VTODO Component to the instance list, expanding it
         within the supplied time range.
         @param component: the Component to expand
-        @param limit: the end L{PyCalendarDateTime} for expansion
+        @param limit: the end L{DateTime} for expansion
         """
         details = self._getMasterToDoDetails(component)
         if details is None:
@@ -370,7 +370,7 @@
             # than the master DTSTART, and if we exclude those, the associated
             # overridden instances will cause an InvalidOverriddenInstance.
             limited = rrules.expand(rulestart,
-                PyCalendarPeriod(PyCalendarDateTime(1900, 1, 1), upperlimit), expanded)
+                Period(DateTime(1900, 1, 1), upperlimit), expanded)
             for startDate in expanded:
                 startDate = self.normalizeFunction(startDate)
                 endDate = startDate + duration
@@ -478,7 +478,7 @@
         Add the specified master VFREEBUSY Component to the instance list, expanding it
         within the supplied time range.
         @param component: the Component to expand
-        @param limit: the end L{PyCalendarDateTime} for expansion
+        @param limit: the end L{DateTime} for expansion
         """
 
         start = component.getStartDateUTC()
@@ -519,7 +519,7 @@
         depending on the presence of the properties. If unbounded at one or both ends, we will
         set the time to 1/1/1900 in the past and 1/1/3000 in the future.
         @param component: the Component to expand
-        @param limit: the end L{PyCalendarDateTime} for expansion
+        @param limit: the end L{DateTime} for expansion
         """
 
         start = component.getStartDateUTC()
@@ -531,7 +531,7 @@
             # If the availability is beyond the end of the range we want, ignore it
             return
         if start is None:
-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         start = self.normalizeFunction(start)
 
         end = component.getEndDateUTC()
@@ -539,7 +539,7 @@
             # If the availability is before the start of the range we want, ignore it
             return
         if end is None:
-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         end = self.normalizeFunction(end)
 
         self.addInstance(Instance(component, start, end))

Modified: CalendarServer/trunk/twistedcaldav/linkresource.py
===================================================================
--- 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)
@@ -47,16 +47,17 @@
     case of a missing underlying resource (broken link) as indicated by self._linkedResource being None.
     """
     log = Logger()
-    
+
     def __init__(self, parent, link_url):
         self.parent = parent
         self.linkURL = link_url
         self.loopDetect = set()
         super(LinkResource, self).__init__(self.parent.principalCollections())
 
+
     @inlineCallbacks
     def linkedResource(self, request):
-        
+
         if not hasattr(self, "_linkedResource"):
             if self.linkURL in self.loopDetect:
                 raise HTTPError(StatusResponse(responsecode.LOOP_DETECTED, "Recursive link target: %s" % (self.linkURL,)))
@@ -67,17 +68,20 @@
 
         if self._linkedResource is None:
             raise HTTPError(StatusResponse(responsecode.NOT_FOUND, "Missing link target: %s" % (self.linkURL,)))
-            
+
         returnValue(self._linkedResource)
 
+
     def isCollection(self):
         return True if hasattr(self, "_linkedResource") else False
 
+
     def resourceType(self):
         return self._linkedResource.resourceType() if hasattr(self, "_linkedResource") else davxml.ResourceType.link
-        
+
+
     def locateChild(self, request, segments):
-        
+
         def _defer(result):
             if result is None:
                 return (self, server.StopTraversal)
@@ -87,6 +91,7 @@
         d.addCallback(_defer)
         return d
 
+
     @inlineCallbacks
     def renderHTTP(self, request):
         linked_to = (yield self.linkedResource(request))
@@ -95,27 +100,33 @@
         else:
             returnValue(http.StatusResponse(responsecode.OK, "Link resource with missing target: %s" % (self.linkURL,)))
 
+
     def getChild(self, name):
         return self._linkedResource.getChild(name) if hasattr(self, "_linkedResource") else None
 
+
     @inlineCallbacks
     def hasProperty(self, property, request):
         hosted = (yield self.linkedResource(request))
         result = (yield hosted.hasProperty(property, request)) if hosted else False
         returnValue(result)
 
+
     @inlineCallbacks
     def readProperty(self, property, request):
         hosted = (yield self.linkedResource(request))
         result = (yield hosted.readProperty(property, request)) if hosted else None
         returnValue(result)
 
+
     @inlineCallbacks
     def writeProperty(self, property, request):
         hosted = (yield self.linkedResource(request))
         result = (yield hosted.writeProperty(property, request)) if hosted else None
         returnValue(result)
 
+
+
 class LinkFollowerMixIn(object):
 
     @inlineCallbacks
@@ -128,6 +139,5 @@
             if linked_to is None:
                 break
             resource = linked_to
-        
+
         returnValue((resource, path))
-        

Modified: CalendarServer/trunk/twistedcaldav/localization.py
===================================================================
--- 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)
@@ -24,7 +24,7 @@
 from locale import normalize
 
 from twext.python.log import Logger
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.duration import Duration
 
 try:
     from Foundation import (
@@ -89,12 +89,12 @@
 helper methods for date formatting:
 
     with translationTo('en') as trans:
-        print(trans.dtDate(PyCalendarDateTime.getToday()))
+        print(trans.dtDate(DateTime.getToday()))
 
     ... Thursday, October 23, 2008
 
     with translationTo('fr') as trans:
-        print(trans.dtDate(PyCalendarDateTime.getToday()))
+        print(trans.dtDate(DateTime.getToday()))
 
     ... Jeudi, Octobre 23, 2008
 
@@ -124,12 +124,13 @@
                 localedir=localeDir, languages=[lang, 'en'], fallback=True)
             self.translations[key] = self.translation
 
+
     def __enter__(self):
         # Get the caller's globals so we can rebind their '_' to our translator
         caller_globals = inspect.stack()[1][0].f_globals
 
         # Store whatever '_' is already bound to so we can restore it later
-        if caller_globals.has_key('_'):
+        if '_' in caller_globals:
             self.prev = caller_globals['_']
 
         # Rebind '_' to our translator
@@ -138,6 +139,7 @@
         # What we return here is accessible to the caller via the 'as' clause
         return self
 
+
     def __exit__(self, type, value, traceback):
         # Restore '_' if it previously had a value
         if hasattr(self, 'prev'):
@@ -146,13 +148,16 @@
         # Don't swallow exceptions
         return False
 
+
     def monthAbbreviation(self, monthNumber):
         return self.translation.ugettext(monthsAbbrev[monthNumber])
 
+
     def date(self, component):
         dtStart = component.propertyValue("DTSTART")
         return self.dtDate(dtStart)
 
+
     def time(self, component):
         """
         Examples:
@@ -191,9 +196,9 @@
             else:
                 if dtStart.isDateOnly():
                     dtEnd = None
-                    duration = PyCalendarDuration(days=1)
+                    duration = Duration(days=1)
                 else:
-                    dtEnd = dtStart + PyCalendarDuration(days=1)
+                    dtEnd = dtStart + Duration(days=1)
                     dtEnd.setHHMMSS(0, 0, 0)
                     duration = dtEnd - dtStart
 
@@ -225,6 +230,7 @@
             }
         )
 
+
     def dtTime(self, val, includeTimezone=True):
         if val.isDateOnly():
             return ""
@@ -252,6 +258,7 @@
 
         return result
 
+
     def dtDuration(self, val):
 
         # Bind to '_' so pygettext.py will pick this up for translation
@@ -265,7 +272,7 @@
             parts.append(_("1 day"))
         elif days > 1:
             parts.append(_("%(dayCount)d days") %
-                { 'dayCount' : days })
+                {'dayCount' : days})
 
         hours = divmod(total / 3600, 24)[1]
         minutes = divmod(total / 60, 60)[1]
@@ -275,19 +282,19 @@
             parts.append(_("1 hour"))
         elif hours > 1:
             parts.append(_("%(hourCount)d hours") %
-                { 'hourCount' : hours })
+                {'hourCount' : hours})
 
         if minutes == 1:
             parts.append(_("1 minute"))
         elif minutes > 1:
             parts.append(_("%(minuteCount)d minutes") %
-                { 'minuteCount' : minutes })
+                {'minuteCount' : minutes})
 
         if seconds == 1:
             parts.append(_("1 second"))
         elif seconds > 1:
             parts.append(_("%(secondCount)d seconds") %
-                { 'secondCount' : seconds })
+                {'secondCount' : seconds})
 
         return " ".join(parts)
 
@@ -398,12 +405,14 @@
                     else:
                         log.info("%s is up to date" % (moFile,))
 
+
+
 class ParseError(Exception):
     pass
 
 
+
 def convertStringsFile(src, dest):
-    strings = { }
 
     dir = os.path.dirname(dest)
 
@@ -458,13 +467,13 @@
 
     result = struct.pack(
         "Iiiiiii",
-        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
+        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
     )
     result += array.array("i", keyDescriptors).tostring()
     result += array.array("i", valueDescriptors).tostring()
@@ -475,6 +484,7 @@
         outFile.write(result)
 
 
+
 def getLanguage(config):
     """
     If the language has been specified explicitly in the config, return it.  Otherwise

Modified: CalendarServer/trunk/twistedcaldav/memcachelock.py
===================================================================
--- 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)
@@ -15,7 +15,7 @@
 ##
 
 from twistedcaldav.memcacher import Memcacher
-from twisted.internet.defer import inlineCallbacks, Deferred, returnValue,\
+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue, \
     succeed
 from twisted.internet import reactor
 import time
@@ -24,7 +24,7 @@
 
     def __init__(self, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
         """
-        
+
         @param namespace: a unique namespace for this lock's tokens
         @type namespace: C{str}
         @param locktoken: the name of the locktoken
@@ -44,31 +44,33 @@
         self._expire_time = expire_time
         self._hasLock = False
 
+
     def _getMemcacheProtocol(self):
-        
+
         result = super(MemcacheLock, self)._getMemcacheProtocol()
 
         if isinstance(result, Memcacher.nullCacher):
             raise AssertionError("No implementation of shared locking without memcached")
-        
+
         return result
 
+
     @inlineCallbacks
     def acquire(self):
-        
+
         assert not self._hasLock, "Lock already acquired."
-    
+
         timeout_at = time.time() + self._timeout
         waiting = False
         while True:
-            
+
             result = (yield self.add(self._locktoken, "1", expireTime=self._expire_time))
             if result:
                 self._hasLock = True
                 if waiting:
                     self.log.debug("Got lock after waiting on %s" % (self._locktoken,))
                 break
-            
+
             if self._timeout and time.time() < timeout_at:
                 waiting = True
                 self.log.debug("Waiting for lock on %s" % (self._locktoken,))
@@ -80,13 +82,14 @@
             else:
                 self.log.debug("Timed out lock after waiting on %s" % (self._locktoken,))
                 raise MemcacheLockTimeoutError()
-        
+
         returnValue(True)
 
+
     def release(self):
-        
+
         assert self._hasLock, "Lock not acquired."
-    
+
         def _done(result):
             self._hasLock = False
             return result
@@ -95,18 +98,20 @@
         d.addCallback(_done)
         return d
 
+
     def clean(self):
-        
+
         if self._hasLock:
             return self.release()
         else:
             return succeed(True)
 
+
     def locked(self):
         """
         Test if the lock is currently being held.
         """
-        
+
         def _gotit(value):
             return value is not None
 
@@ -114,5 +119,7 @@
         d.addCallback(_gotit)
         return d
 
+
+
 class MemcacheLockTimeoutError(Exception):
     pass

Modified: CalendarServer/trunk/twistedcaldav/memcachepool.py
===================================================================
--- 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)
@@ -99,6 +99,7 @@
             connector,
             reason)
 
+
     def buildProtocol(self, addr):
         """
         Attach the C{self.connectionPool} to the protocol so it can tell it,
@@ -167,6 +168,7 @@
         self._pendingConnects = 0
         self._commands = []
 
+
     def _isIdle(self):
         return (
             len(self._busyClients) == 0 and
@@ -174,6 +176,7 @@
             self._pendingConnects == 0
         )
 
+
     def _shutdownCallback(self):
         self.shutdown_requested = True
         if self._isIdle():
@@ -181,13 +184,14 @@
         self.shutdown_deferred = Deferred()
         return self.shutdown_deferred
 
+
     def _newClientConnection(self):
         """
         Create a new client connection.
 
         @return: A L{Deferred} that fires with the L{IProtocol} instance.
         """
-        self.log.debug("Initating new client connection to: %r" % (
+        self.log.debug("Initiating new client connection to: %r" % (
                 self._endpoint,))
         self._logClientStats()
 
@@ -219,7 +223,7 @@
 
         @param command: A C{str} representing an attribute of
             L{MemCacheProtocol}.
-        @parma args: Any positional arguments that should be passed to
+        @param args: Any positional arguments that should be passed to
             C{command}.
         @param kwargs: Any keyword arguments that should be passed to
             C{command}.
@@ -258,7 +262,7 @@
 
         @param command: A C{str} representing an attribute of
             L{MemCacheProtocol}.
-        @parma args: Any positional arguments that should be passed to
+        @param args: Any positional arguments that should be passed to
             C{command}.
         @param kwargs: Any keyword arguments that should be passed to
             C{command}.
@@ -371,24 +375,31 @@
     def get(self, *args, **kwargs):
         return self.performRequest('get', *args, **kwargs)
 
+
     def set(self, *args, **kwargs):
         return self.performRequest('set', *args, **kwargs)
 
+
     def checkAndSet(self, *args, **kwargs):
         return self.performRequest('checkAndSet', *args, **kwargs)
 
+
     def delete(self, *args, **kwargs):
         return self.performRequest('delete', *args, **kwargs)
 
+
     def add(self, *args, **kwargs):
         return self.performRequest('add', *args, **kwargs)
 
+
     def incr(self, *args, **kwargs):
         return self.performRequest('increment', *args, **kwargs)
 
+
     def decr(self, *args, **kwargs):
         return self.performRequest('decrement', *args, **kwargs)
 
+
     def flushAll(self, *args, **kwargs):
         return self.performRequest('flushAll', *args, **kwargs)
 

Modified: CalendarServer/trunk/twistedcaldav/method/get.py
===================================================================
--- 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)
@@ -25,7 +25,7 @@
 from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import parentForURL
-from twext.web2.http import HTTPError
+from twext.web2.http import HTTPError, StatusResponse
 from twext.web2.http import Response
 from twext.web2.http_headers import MimeType
 from twext.web2.stream import MemoryStream
@@ -34,8 +34,10 @@
 from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.datafilters.hiddeninstance import HiddenInstanceFilter
 from twistedcaldav.datafilters.privateevents import PrivateEventFilter
+from twistedcaldav.ical import Component
 from twistedcaldav.resource import isPseudoCalendarCollectionResource, \
     CalDAVResource
+from twistedcaldav.util import bestAcceptType
 
 @inlineCallbacks
 def http_GET(self, request):
@@ -70,6 +72,8 @@
                 returnValue(response)
 
         else:
+            # FIXME: this should be implemented in storebridge.CalendarObject.render
+
             # Look for calendar access restriction on existing resource.
             parentURL = parentForURL(request.uri)
             parent = (yield request.locateResource(parentURL))
@@ -78,6 +82,11 @@
                 # Check authorization first
                 yield self.authorize(request, (davxml.Read(),))
 
+                # 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"))
+
                 caldata = (yield self.iCalendarForUser(request))
 
                 # Filter any attendee hidden instances
@@ -92,8 +101,8 @@
                     caldata = PrivateEventFilter(self.accessMode, isowner).filter(caldata)
 
                 response = Response()
-                response.stream = MemoryStream(caldata.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference))
-                response.headers.setHeader("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
+                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,)))
 
                 # Add Schedule-Tag header if property is present
                 if self.scheduleTag:

Modified: CalendarServer/trunk/twistedcaldav/method/propfind.py
===================================================================
--- 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)
@@ -98,7 +98,7 @@
             search_properties = "names"
         elif isinstance(container, davxml.PropertyContainer):
             properties = container.children
-            search_properties = [(p.namespace, p.name) for p in properties]
+            search_properties = properties
         else:
             raise AssertionError("Unexpected element type in %s: %s"
                                  % (davxml.PropertyFind.sname(), container))
@@ -245,7 +245,11 @@
 # Utilities
 ##
 
-def propertyName(name):
+def propertyName(prop):
+    if type(prop) is tuple:
+        name = prop
+    else:
+        name = prop.qname()
     property_namespace, property_name = name
     pname = davxml.WebDAVUnknownElement()
     pname.namespace = property_namespace

Modified: CalendarServer/trunk/twistedcaldav/method/report_calendar_query.py
===================================================================
--- 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)
@@ -32,7 +32,8 @@
 from twext.web2.http import HTTPError, StatusResponse
 
 from twistedcaldav import caldavxml
-from twistedcaldav.caldavxml import caldav_namespace, MaxInstances
+from twistedcaldav.caldavxml import caldav_namespace, MaxInstances, \
+    CalendarTimeZone
 from twistedcaldav.config import config
 from txdav.common.icommondatastore import IndexedSearchException, \
     ConcurrentModification
@@ -171,10 +172,10 @@
         if calresource.isPseudoCalendarCollection():
             # Get the timezone property from the collection if one was not set in the query,
             # and store in the query filter for later use
-            has_prop = (yield calresource.hasProperty((caldav_namespace, "calendar-timezone"), request))
+            has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
             timezone = query_timezone
             if query_tz is None and has_prop:
-                tz = (yield calresource.readProperty((caldav_namespace, "calendar-timezone"), request))
+                tz = (yield calresource.readProperty(CalendarTimeZone(), request))
                 filter.settimezone(tz)
                 timezone = tuple(tz.calendar().subcomponents())[0]
 
@@ -233,9 +234,9 @@
                 parent = (yield calresource.locateParent(request, uri))
                 assert parent is not None and parent.isPseudoCalendarCollection()
 
-                has_prop = (yield parent.hasProperty((caldav_namespace, "calendar-timezone"), request))
+                has_prop = (yield parent.hasProperty(CalendarTimeZone(), request))
                 if has_prop:
-                    tz = (yield parent.readProperty((caldav_namespace, "calendar-timezone"), request))
+                    tz = (yield parent.readProperty(CalendarTimeZone(), request))
                     filter.settimezone(tz)
                     timezone = tuple(tz.calendar().subcomponents())[0]
 

Modified: CalendarServer/trunk/twistedcaldav/method/report_common.py
===================================================================
--- 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)
@@ -52,7 +52,7 @@
 
 from twistedcaldav import caldavxml
 from twistedcaldav import carddavxml
-from twistedcaldav.caldavxml import caldav_namespace, CalendarData, TimeRange
+from twistedcaldav.caldavxml import CalendarData, CalendarTimeZone, TimeRange
 from twistedcaldav.carddavxml import AddressData
 from twistedcaldav.config import config
 from twistedcaldav.datafilters.calendardata import CalendarDataFilter
@@ -69,10 +69,10 @@
 
 from txdav.common.icommondatastore import IndexedSearchException
 
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.period import PyCalendarPeriod
+from pycalendar.duration import Duration
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
+from pycalendar.period import Period
 
 log = Logger()
 
@@ -299,7 +299,7 @@
     generate_calendar_data = False
     for property in prop.children:
         if isinstance(property, caldavxml.CalendarData):
-            if not property.verifyTypeVersion([("text/calendar", "2.0")]):
+            if not property.verifyTypeVersion():
                 result = False
                 message = "Calendar-data element type/version not supported: content-type: %s, version: %s" % (property.content_type, property.version)
             generate_calendar_data = True
@@ -324,7 +324,7 @@
     generate_address_data = False
     for property in prop.children:
         if isinstance(property, carddavxml.AddressData):
-            if not property.verifyTypeVersion([("text/vcard", "3.0")]):
+            if not property.verifyTypeVersion():
                 result = False
                 message = "Address-data element type/version not supported: content-type: %s, version: %s" % (property.content_type, property.version)
             generate_address_data = True
@@ -371,7 +371,7 @@
             filtered = HiddenInstanceFilter().filter(calendar)
             filtered = PrivateEventFilter(resource.accessMode, isowner).filter(filtered)
             filtered = CalendarDataFilter(property, timezone).filter(filtered)
-            propvalue = CalendarData().fromCalendar(filtered)
+            propvalue = CalendarData.fromCalendar(filtered, format=property.content_type)
             properties_by_status[responsecode.OK].append(propvalue)
             continue
 
@@ -379,7 +379,7 @@
             if vcard is None:
                 vcard = (yield resource.vCard())
             filtered = AddressDataFilter(property).filter(vcard)
-            propvalue = AddressData().fromAddress(filtered)
+            propvalue = AddressData.fromAddress(filtered, format=property.content_type)
             properties_by_status[responsecode.OK].append(propvalue)
             continue
 
@@ -392,7 +392,7 @@
 
         if has:
             try:
-                prop = (yield resource.readProperty(qname, request))
+                prop = (yield resource.readProperty(property, request))
                 if prop is not None:
                     properties_by_status[responsecode.OK].append(prop)
                 elif not returnMinimal:
@@ -436,8 +436,8 @@
         if entry:
 
             # Offset one day at either end to account for floating
-            cached_start = entry.timerange.start + PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
-            cached_end = entry.timerange.end - PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_start = entry.timerange.start + Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_end = entry.timerange.end - Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
 
             # Verify that the requested timerange lies within the cache timerange
             if compareDateTime(timerange.end, cached_end) <= 0 and compareDateTime(timerange.start, cached_start) >= 0:
@@ -515,9 +515,9 @@
         useruid = ""
 
     # Get the timezone property from the collection.
-    has_prop = (yield calresource.hasProperty((caldav_namespace, "calendar-timezone"), request))
+    has_prop = (yield calresource.hasProperty(CalendarTimeZone(), request))
     if has_prop:
-        tz = (yield calresource.readProperty((caldav_namespace, "calendar-timezone"), request))
+        tz = (yield calresource.readProperty(CalendarTimeZone(), request))
     else:
         tz = None
 
@@ -559,8 +559,8 @@
             request.extendedLogItems["fb-uncached"] = request.extendedLogItems.get("fb-uncached", 0) + 1
 
             # We want to cache a large range of time based on the current date
-            cache_start = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=0 - config.FreeBusyCacheDaysBack))
-            cache_end = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=config.FreeBusyCacheDaysForward))
+            cache_start = normalizeToUTC(DateTime.getToday() + Duration(days=0 - config.FreeBusyCacheDaysBack))
+            cache_end = normalizeToUTC(DateTime.getToday() + Duration(days=config.FreeBusyCacheDaysForward))
 
             # If the requested timerange would fit in our allowed cache range, trigger the cache creation
             if compareDateTime(timerange.start, cache_start) >= 0 and compareDateTime(timerange.end, cache_end) <= 0:
@@ -602,7 +602,7 @@
         request.extendedLogItems["fb-cached"] = request.extendedLogItems.get("fb-cached", 0) + 1
 
         # Determine appropriate timezone (UTC is the default)
-        tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
+        tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
 
     # We care about separate instances for VEVENTs only
     aggregated_resources = {}
@@ -645,15 +645,15 @@
                 if float == 'Y':
                     fbstart.setTimezone(tzinfo)
                 else:
-                    fbstart.setTimezone(PyCalendarTimezone(utc=True))
+                    fbstart.setTimezone(Timezone(utc=True))
                 fbend = parseSQLTimestampToPyCalendar(end)
                 if float == 'Y':
                     fbend.setTimezone(tzinfo)
                 else:
-                    fbend.setTimezone(PyCalendarTimezone(utc=True))
+                    fbend.setTimezone(Timezone(utc=True))
 
                 # Clip instance to time range
-                clipped = clipPeriod(PyCalendarPeriod(fbstart, duration=fbend - fbstart), PyCalendarPeriod(timerange.start, timerange.end))
+                clipped = clipPeriod(Period(fbstart, duration=fbend - fbstart), Period(timerange.start, timerange.end))
 
                 # Double check for overlap
                 if clipped:
@@ -735,7 +735,7 @@
     @param timerange: the time-range in which to expand
     @type timerange: L{TimeRange}
     @param tzinfo: timezone for floating time calculations
-    @type tzinfo: L{PyCalendarTimezone}
+    @type tzinfo: L{Timezone}
     """
 
     # First expand the component
@@ -775,7 +775,7 @@
     @param calendar: the L{Component} that is the VCALENDAR containing the VEVENT's.
     @param fbinfo: the tuple used to store the three types of fb data.
     @param timerange: the time range to restrict free busy data to.
-    @param tzinfo: the L{PyCalendarTimezone} for the timezone to use for floating/all-day events.
+    @param tzinfo: the L{Timezone} for the timezone to use for floating/all-day events.
     """
 
     # Expand out the set of instances for the event with in the required range
@@ -820,10 +820,10 @@
         # Clip period for this instance - use duration for period end if that
         # is what original component used
         if instance.component.hasProperty("DURATION"):
-            period = PyCalendarPeriod(fbstart, duration=fbend - fbstart)
+            period = Period(fbstart, duration=fbend - fbstart)
         else:
-            period = PyCalendarPeriod(fbstart, fbend)
-        clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+            period = Period(fbstart, fbend)
+        clipped = clipPeriod(period, Period(timerange.start, timerange.end))
 
         # Double check for overlap
         if clipped:
@@ -861,7 +861,7 @@
             assert isinstance(fb.value(), list), "FREEBUSY property does not contain a list of values: %r" % (fb,)
             for period in fb.value():
                 # Clip period for this instance
-                clipped = clipPeriod(period.getValue(), PyCalendarPeriod(timerange.start, timerange.end))
+                clipped = clipPeriod(period.getValue(), Period(timerange.start, timerange.end))
                 if clipped:
                     fbinfo[fbtype_mapper.get(fbtype, 0)].append(clipped)
 
@@ -880,12 +880,12 @@
         # Get overall start/end
         start = vav.getStartDateUTC()
         if start is None:
-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         end = vav.getEndDateUTC()
         if end is None:
-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        period = PyCalendarPeriod(start, end)
-        overall = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        period = Period(start, end)
+        overall = clipPeriod(period, Period(timerange.start, timerange.end))
         if overall is None:
             continue
 
@@ -897,10 +897,10 @@
         last_end = timerange.start
         for period in periods:
             if last_end < period.getStart():
-                busyperiods.append(PyCalendarPeriod(last_end, period.getStart()))
+                busyperiods.append(Period(last_end, period.getStart()))
             last_end = period.getEnd()
         if last_end < timerange.end:
-            busyperiods.append(PyCalendarPeriod(last_end, timerange.end))
+            busyperiods.append(Period(last_end, timerange.end))
 
         # Add to actual results mapped by busy type
         fbtype = vav.propertyValue("BUSYTYPE")
@@ -947,10 +947,10 @@
             # Clip period for this instance - use duration for period end if that
             # is what original component used
             if instance.component.hasProperty("DURATION"):
-                period = PyCalendarPeriod(start, duration=end - start)
+                period = Period(start, duration=end - start)
             else:
-                period = PyCalendarPeriod(start, end)
-            clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+                period = Period(start, end)
+            clipped = clipPeriod(period, Period(timerange.start, timerange.end))
             if clipped:
                 periods.append(clipped)
 
@@ -993,7 +993,7 @@
         fb.addProperty(attendee)
     fb.addProperty(Property("DTSTART", timerange.start))
     fb.addProperty(Property("DTEND", timerange.end))
-    fb.addProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+    fb.addProperty(Property("DTSTAMP", DateTime.getNowUTC()))
     if len(fbinfo[0]) != 0:
         fb.addProperty(Property("FREEBUSY", fbinfo[0], {"FBTYPE": "BUSY"}))
     if len(fbinfo[1]) != 0:

Modified: CalendarServer/trunk/twistedcaldav/method/report_freebusy.py
===================================================================
--- 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)
@@ -31,7 +31,9 @@
 from twext.web2.stream import MemoryStream
 
 from twistedcaldav import caldavxml
+from twistedcaldav.ical import Component
 from twistedcaldav.method import report_common
+from twistedcaldav.util import bestAcceptType
 
 from txdav.caldav.icalendarstore import TimeRangeLowerLimit, TimeRangeUpperLimit
 from txdav.xml import element as davxml
@@ -60,6 +62,11 @@
 
     matchcount = [0]
 
+    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"))
+
+
     def generateFreeBusyInfo(calresource, uri): #@UnusedVariable
         """
         Run a free busy report on the specified calendar collection
@@ -104,7 +111,7 @@
     fbcalendar = report_common.buildFreeBusyResult(fbinfo, timerange)
 
     response = Response()
-    response.stream = MemoryStream(str(fbcalendar))
-    response.headers.setHeader("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
+    response.stream = MemoryStream(fbcalendar.getText(accepted_type))
+    response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (accepted_type,)))
 
     returnValue(response)

Modified: CalendarServer/trunk/twistedcaldav/mkcolxml.py
===================================================================
--- 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)
@@ -45,11 +45,12 @@
     """
     name = "mkcol"
 
-    allowed_children = { (davxml.dav_namespace, "set"): (0, 1) }
+    allowed_children = {(davxml.dav_namespace, "set"): (0, 1)}
 
-    child_types = { "WebDAVUnknownElement": (0, None) }
+    child_types = {"WebDAVUnknownElement": (0, None)}
 
 
+
 @registerElement
 class MakeCollectionResponse (davxml.WebDAVElement):
     """
@@ -58,4 +59,4 @@
     """
     name = "mkcol-response"
 
-    allowed_children = { davxml.WebDAVElement: (0, None) }
+    allowed_children = {davxml.WebDAVElement: (0, None)}

Modified: CalendarServer/trunk/twistedcaldav/notifications.py
===================================================================
--- 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)
@@ -48,43 +48,53 @@
         self._parent = parent
         CalDAVResource.__init__(self)
 
+
     def principalCollections(self):
         return self._parent.principalCollections()
 
+
     def isCollection(self):
         return False
 
+
     def resourceName(self):
         raise NotImplementedError
-        
+
+
     def http_PUT(self, request):
         return responsecode.FORBIDDEN
 
+
     @inlineCallbacks
     def http_DELETE(self, request):
-        
+
         response = (yield super(NotificationResource, self).http_DELETE(request))
         if response == responsecode.NO_CONTENT:
             yield self._parent.removedNotifictionMessage(request, self.resourceName())
         returnValue(response)
-    
+
+
+
 class NotificationCollectionResource(ReadOnlyNoCopyResourceMixIn, CalDAVResource):
 
     def notificationsDB(self):
-        
+
         if not hasattr(self, "_notificationsDB"):
             self._notificationsDB = NotificationsDatabase(self)
         return self._notificationsDB
 
+
     def isCollection(self):
         return True
 
+
     def resourceType(self):
         return davxml.ResourceType.notification
 
+
     @inlineCallbacks
     def addNotification(self, request, uid, xmltype, xmldata):
-        
+
         # Write data to file
         rname = uid + ".xml"
         yield self._writeNotification(request, uid, rname, xmltype, xmldata)
@@ -103,7 +113,7 @@
 
     @inlineCallbacks
     def deleteNotifictionMessageByUID(self, request, uid):
-        
+
         # See if it exists and delete the resource
         record = yield self.notificationsDB().recordForUID(uid)
         if record:
@@ -117,7 +127,7 @@
         record = yield self.notificationsDB().recordForName(rname)
         if record:
             yield self.deleteNotification(request, record)
-        
+
         returnValue(None)
 
 
@@ -131,13 +141,16 @@
         return maybeDeferred(self.notificationsDB().removeRecordForName, rname)
 
 
+
 class NotificationRecord(object):
-    
+
     def __init__(self, uid, name, xmltype):
         self.uid = uid
         self.name = name
         self.xmltype = xmltype
 
+
+
 class NotificationsDatabase(AbstractSQLDatabase):
     log = Logger()
 
@@ -154,35 +167,40 @@
         db_filename = os.path.join(self.resource.fp.path, NotificationsDatabase.db_basename)
         super(NotificationsDatabase, self).__init__(db_filename, True, autocommit=True)
 
+
     def allRecords(self):
-        
+
         records = self._db_execute("select * from NOTIFICATIONS")
         return [self._makeRecord(row) for row in (records if records is not None else ())]
-    
+
+
     def recordForUID(self, uid):
-        
+
         row = self._db_execute("select * from NOTIFICATIONS where UID = :1", uid)
         return self._makeRecord(row[0]) if row else None
-    
+
+
     def addOrUpdateRecord(self, record):
 
         self._db_execute("""insert or replace into NOTIFICATIONS (UID, NAME, TYPE)
             values (:1, :2, :3)
             """, record.uid, record.name, record.xmltype,
         )
-            
+
         self._db_execute(
             """
             insert or replace into REVISIONS (NAME, REVISION, DELETED)
             values (:1, :2, :3)
             """, record.name, self.bumpRevision(fast=True), 'N',
         )
-    
+
+
     def removeRecordForUID(self, uid):
 
         record = self.recordForUID(uid)
         self.removeRecordForName(record.name)
-    
+
+
     def removeRecordForName(self, rname):
 
         self._db_execute("delete from NOTIFICATIONS where NAME = :1", rname)
@@ -192,12 +210,13 @@
             where NAME = :3
             """, self.bumpRevision(fast=True), 'Y', rname
         )
-    
+
+
     def whatchanged(self, revision):
 
         results = [(name.encode("utf-8"), deleted) for name, deleted in self._db_execute("select NAME, DELETED from REVISIONS where REVISION > :1", revision)]
-        results.sort(key=lambda x:x[1])
-        
+        results.sort(key=lambda x: x[1])
+
         changed = []
         deleted = []
         for name, wasdeleted in results:
@@ -209,14 +228,16 @@
                     changed.append(name)
             else:
                 raise SyncTokenValidException
-        
+
         return changed, deleted,
 
+
     def lastRevision(self):
         return self._db_value_for_sql(
             "select REVISION from REVISION_SEQUENCE"
         )
 
+
     def bumpRevision(self, fast=False):
         self._db_execute(
             """
@@ -230,18 +251,21 @@
             """,
         )
 
+
     def _db_version(self):
         """
         @return: the schema version assigned to this index.
         """
         return NotificationsDatabase.schema_version
 
+
     def _db_type(self):
         """
         @return: the collection type assigned to this index.
         """
         return NotificationsDatabase.db_type
 
+
     def _db_init_data_tables(self, q):
         """
         Initialise the underlying database tables.
@@ -302,6 +326,7 @@
             """
         )
 
+
     def _db_upgrade_data_tables(self, q, old_version):
         """
         Upgrade the data from an older version of the DB.
@@ -310,7 +335,7 @@
         # Nothing to do as we have not changed the schema
         pass
 
+
     def _makeRecord(self, row):
-        
+
         return NotificationRecord(*[str(item) if type(item) == types.UnicodeType else item for item in row])
-

Modified: CalendarServer/trunk/twistedcaldav/query/calendarqueryfilter.py
===================================================================
--- 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)
@@ -28,8 +28,8 @@
 from twistedcaldav.dateops import timeRangesOverlap
 from twistedcaldav.ical import Component, Property
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 log = Logger()
 
@@ -89,7 +89,7 @@
                     instances = None
                 else:
                     # Expand the instances up to infinity
-                    instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), ignoreInvalidInstances=True)
+                    instances = component.expandTimeRanges(DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True)), ignoreInvalidInstances=True)
             else:
                 instances = component.expandTimeRanges(maxend, ignoreInvalidInstances=True)
         else:
@@ -117,7 +117,7 @@
         Set the default timezone to use with this query.
         @param calendar: a L{Component} for the VCALENDAR containing the one
             VTIMEZONE that we want
-        @return: the L{PyCalendarTimezone} derived from the VTIMEZONE or utc.
+        @return: the L{Timezone} derived from the VTIMEZONE or utc.
         """
 
         if tzelement is None:
@@ -127,7 +127,7 @@
         elif isinstance(tzelement, Component):
             tz = tzelement.gettimezone()
         if tz is None:
-            tz = PyCalendarTimezone(utc=True)
+            tz = Timezone(utc=True)
         self.child.settzinfo(tz)
         return tz
 
@@ -357,7 +357,7 @@
     def settzinfo(self, tzinfo):
         """
         Set the default timezone to use with this query.
-        @param tzinfo: a L{PyCalendarTimezone} to use.
+        @param tzinfo: a L{Timezone} to use.
         """
 
         # Give tzinfo to any TimeRange we have
@@ -374,7 +374,7 @@
         Get the date farthest into the future in any time-range elements
 
         @param currentMaximum: current future value to compare with
-        @type currentMaximum: L{PyCalendarDateTime}
+        @type currentMaximum: L{DateTime}
         """
 
         # Give tzinfo to any TimeRange we have
@@ -471,7 +471,7 @@
     def settzinfo(self, tzinfo):
         """
         Set the default timezone to use with this query.
-        @param tzinfo: a L{PyCalendarTimezone} to use.
+        @param tzinfo: a L{Timezone} to use.
         """
 
         # Give tzinfo to any TimeRange we have
@@ -484,7 +484,7 @@
         Get the date farthest into the future in any time-range elements
 
         @param currentMaximum: current future value to compare with
-        @type currentMaximum: L{PyCalendarDateTime}
+        @type currentMaximum: L{DateTime}
         """
 
         # Give tzinfo to any TimeRange we have
@@ -652,15 +652,15 @@
         if "start" not in xml_element.attributes and "end" not in xml_element.attributes:
             raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
 
-        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
+        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
         self.tzinfo = None
 
 
     def settzinfo(self, tzinfo):
         """
         Set the default timezone to use with this query.
-        @param tzinfo: a L{PyCalendarTimezone} to use.
+        @param tzinfo: a L{Timezone} to use.
         """
 
         # Give tzinfo to any TimeRange we have

Modified: CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py
===================================================================
--- 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)
@@ -17,7 +17,7 @@
 from twistedcaldav import caldavxml
 from twistedcaldav.query import calendarqueryfilter
 import twistedcaldav.test.util
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.timezone import Timezone
 from twistedcaldav.query.calendarquery import sqlcalendarquery
 
 class Tests(twistedcaldav.test.util.TestCase):
@@ -36,7 +36,7 @@
             )
         )
         filter = calendarqueryfilter.Filter(filter)
-        filter.child.settzinfo(PyCalendarTimezone(tzid="America/New_York"))
+        filter.child.settzinfo(Timezone(tzid="America/New_York"))
 
         sql, args = sqlcalendarquery(filter)
         self.assertTrue(sql.find("RESOURCE") != -1)
@@ -60,7 +60,7 @@
             )
         )
         filter = calendarqueryfilter.Filter(filter)
-        filter.child.settzinfo(PyCalendarTimezone(tzid="America/New_York"))
+        filter.child.settzinfo(Timezone(tzid="America/New_York"))
 
         sql, args = sqlcalendarquery(filter)
         self.assertTrue(sql.find("RESOURCE") != -1)
@@ -88,7 +88,7 @@
             )
         )
         filter = calendarqueryfilter.Filter(filter)
-        filter.child.settzinfo(PyCalendarTimezone(tzid="America/New_York"))
+        filter.child.settzinfo(Timezone(tzid="America/New_York"))
 
         sql, args = sqlcalendarquery(filter)
         self.assertTrue(sql.find("RESOURCE") != -1)
@@ -119,7 +119,7 @@
             )
         )
         filter = calendarqueryfilter.Filter(filter)
-        filter.child.settzinfo(PyCalendarTimezone(tzid="America/New_York"))
+        filter.child.settzinfo(Timezone(tzid="America/New_York"))
 
         sql, args = sqlcalendarquery(filter)
         self.assertTrue(sql.find("RESOURCE") != -1)

Modified: CalendarServer/trunk/twistedcaldav/query/test/test_queryfilter.py
===================================================================
--- 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)
@@ -18,7 +18,7 @@
 from twistedcaldav.query import calendarqueryfilter
 import twistedcaldav.test.util
 from twistedcaldav.caldavxml import TimeZone
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.timezone import Timezone
 
 class Tests(twistedcaldav.test.util.TestCase):
 
@@ -227,4 +227,4 @@
 END:VCALENDAR
 """))
 
-        self.assertTrue(isinstance(tz, PyCalendarTimezone))
+        self.assertTrue(isinstance(tz, Timezone))

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- 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)
@@ -71,6 +71,7 @@
 from twistedcaldav.directory.internal import InternalDirectoryRecord
 from twistedcaldav.extensions import DAVResource, DAVPrincipalResource, \
     DAVResourceWithChildrenMixin
+from twistedcaldav import ical
 from twistedcaldav.ical import Component
 
 from twistedcaldav.icaldav import ICalDAVResource, ICalendarPrincipalResource
@@ -257,10 +258,11 @@
                 # Redirect to include trailing '/' in URI
                 return RedirectResponse(request.unparseURL(path=urllib.quote(urllib.unquote(request.path), safe=':/') + '/'))
 
-            def _defer(data):
+            def _defer(result):
+                data, accepted_type = result
                 response = Response()
-                response.stream = MemoryStream(str(data))
-                response.headers.setHeader("content-type", MimeType.fromString("text/calendar"))
+                response.stream = MemoryStream(data.getText(accepted_type))
+                response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (accepted_type,)))
                 return response
 
             d = self.iCalendarRolledup(request)
@@ -375,7 +377,7 @@
                                   (self,))
 
 
-    def storeStream(self, stream):
+    def storeStream(self, stream, format):
         """
         Store the content of the stream in this resource, as it would via a PUT.
 
@@ -385,8 +387,7 @@
         @return: a L{Deferred} which fires with an HTTP response.
         @rtype: L{Deferred}
         """
-        raise NotImplementedError("%s does not implement storeStream" %
-                                  (self,))
+        raise NotImplementedError("%s does not implement storeStream" % (self,))
 
     # End transitional new-store interface
 
@@ -605,12 +606,21 @@
             returnValue(self.getSupportedComponentSet())
 
         elif qname == caldavxml.SupportedCalendarData.qname() and self.isPseudoCalendarCollection():
-            returnValue(caldavxml.SupportedCalendarData(
+            dataTypes = []
+            dataTypes.append(
                 caldavxml.CalendarData(**{
                     "content-type": "text/calendar",
                     "version"     : "2.0",
                 }),
-            ))
+            )
+            if config.EnableJSONData:
+                dataTypes.append(
+                    caldavxml.CalendarData(**{
+                        "content-type": "application/calendar+json",
+                        "version"     : "2.0",
+                    }),
+                )
+            returnValue(caldavxml.SupportedCalendarData(*dataTypes))
 
         elif qname == caldavxml.MaxResourceSize.qname() and self.isPseudoCalendarCollection():
             if config.MaxResourceSize:
@@ -642,12 +652,21 @@
 
         elif qname == carddavxml.SupportedAddressData.qname() and self.isAddressBookCollection():
             # CardDAV, section 6.2.2
-            returnValue(carddavxml.SupportedAddressData(
+            dataTypes = []
+            dataTypes.append(
                 carddavxml.AddressDataType(**{
                     "content-type": "text/vcard",
                     "version"     : "3.0",
                 }),
-            ))
+            )
+            if config.EnableJSONData:
+                dataTypes.append(
+                    carddavxml.AddressDataType(**{
+                        "content-type": "application/vcard+json",
+                        "version"     : "3.0",
+                    }),
+                )
+            returnValue(carddavxml.SupportedAddressData(*dataTypes))
 
         elif qname == carddavxml.MaxResourceSize.qname() and self.isAddressBookCollection() and not self.isDirectoryBackedAddressBookCollection():
             # CardDAV, section 6.2.3
@@ -1446,11 +1465,6 @@
         returnValue(caldata)
 
 
-    def iCalendarText(self):
-        # storebridge handles this method
-        raise NotImplementedError()
-
-
     def iCalendar(self):
         # storebridge handles this method
         raise NotImplementedError()
@@ -2446,18 +2460,13 @@
 
         if qname == caldavxml.SupportedCalendarComponentSets.qname():
             if config.RestrictCalendarsToOneComponentType:
-                prop = caldavxml.SupportedCalendarComponentSets(
+                prop = caldavxml.SupportedCalendarComponentSets(*[
                     caldavxml.SupportedCalendarComponentSet(
                         caldavxml.CalendarComponent(
-                            name="VEVENT",
+                            name=name,
                         ),
-                    ),
-                    caldavxml.SupportedCalendarComponentSet(
-                        caldavxml.CalendarComponent(
-                            name="VTODO",
-                        ),
-                    ),
-                )
+                    ) for name in ical.allowedStoreComponents
+                ])
             else:
                 prop = caldavxml.SupportedCalendarComponentSets()
             returnValue(prop)

Modified: CalendarServer/trunk/twistedcaldav/scheduling_store/caldav/resource.py
===================================================================
--- 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)
@@ -45,7 +45,7 @@
 from twistedcaldav import caldavxml, customxml
 from twistedcaldav.caldavxml import caldav_namespace, CalendarFreeBusySet
 from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.ical import allowedComponents, Component
+from twistedcaldav.ical import Component, allowedSchedulingComponents
 from twistedcaldav.resource import CalDAVResource
 from twistedcaldav.resource import isCalendarCollectionResource
 
@@ -300,8 +300,14 @@
         """
         Write either the default VEVENT or VTODO calendar property, validating and canonicalizing the value
         """
-        tasks = property.qname() == customxml.ScheduleDefaultTasksURL
-        error_element = (calendarserver_namespace, "valid-schedule-default-tasks-URL") if tasks else (caldav_namespace, "valid-schedule-default-calendar-URL")
+        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)
 
         # Verify that the calendar added in the PROPPATCH is valid.
         property.children = [davxml.HRef(normalizeURL(str(href))) for href in property.children]
@@ -325,7 +331,7 @@
 
         try:
             # Now set it on the new store object
-            yield self.parent._newStoreHome.setDefaultCalendar(cal._newStoreObject, tasks)
+            yield self.parent._newStoreHome.setDefaultCalendar(cal._newStoreObject, ctype)
         except InvalidDefaultCalendar as e:
             raise HTTPError(ErrorResponse(
                 responsecode.CONFLICT,
@@ -390,7 +396,7 @@
 
     def getSupportedComponentSet(self):
         return caldavxml.SupportedCalendarComponentSet(
-            *[caldavxml.CalendarComponent(name=item) for item in allowedComponents]
+            *[caldavxml.CalendarComponent(name=item) for item in allowedSchedulingComponents]
         )
 
 
@@ -407,7 +413,7 @@
         # Check authentication and access controls
         yield self.authorize(request, (caldavxml.ScheduleSend(),))
 
-        calendar = (yield self.loadCalendarFromRequest(request))
+        calendar, format = (yield self.loadCalendarFromRequest(request))
         originator = (yield self.loadOriginatorFromRequestDetails(request))
         recipients = self.loadRecipientsFromCalendarData(calendar)
 
@@ -431,14 +437,25 @@
 
         # Do the POST processing treating
         result = (yield scheduler.doSchedulingViaPOST(originator, recipients, calendar))
-        returnValue(result.response())
+        returnValue(result.response(format=format))
 
 
+    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
+
+
     @inlineCallbacks
     def loadCalendarFromRequest(self, request):
         # Must be content-type text/calendar
         contentType = request.headers.getHeader("content-type")
-        if contentType is not None and (contentType.mediaType, contentType.mediaSubtype) != ("text", "calendar"):
+        format = self.determineType(contentType)
+        if format is None:
             self.log.error("MIME type %s not allowed in calendar collection" % (contentType,))
             raise HTTPError(ErrorResponse(
                 responsecode.FORBIDDEN,
@@ -448,7 +465,7 @@
 
         # Parse the calendar object from the HTTP request stream
         try:
-            calendar = (yield Component.fromIStream(request.stream))
+            calendar = (yield Component.fromIStream(request.stream, format=format))
         except:
             # FIXME: Bare except
             self.log.error("Error while handling POST: %s" % (Failure(),))
@@ -458,7 +475,7 @@
                 description="Can't parse calendar data"
             ))
 
-        returnValue(calendar)
+        returnValue((calendar, format,))
 
 
     @inlineCallbacks

Modified: CalendarServer/trunk/twistedcaldav/sharing.py
===================================================================
--- 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)
@@ -46,7 +46,7 @@
 from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
 from twistedcaldav.linkresource import LinkFollowerMixIn
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 
 # FIXME: Get rid of these imports
@@ -740,7 +740,7 @@
         typeAttr = {'shared-type': self.sharedResourceType()}
         xmltype = customxml.InviteNotification(**typeAttr)
         xmldata = customxml.Notification(
-            customxml.DTStamp.fromString(PyCalendarDateTime.getNowUTC().getText()),
+            customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
             customxml.InviteNotification(
                 customxml.UID.fromString(invitation.uid()),
                 element.HRef.fromString(userid),
@@ -1362,7 +1362,7 @@
         record = shareePrincipal.record
 
         xmldata = customxml.Notification(
-            customxml.DTStamp.fromString(PyCalendarDateTime.getNowUTC().getText()),
+            customxml.DTStamp.fromString(DateTime.getNowUTC().getText()),
             customxml.InviteReply(
                 *(
                     (

Modified: CalendarServer/trunk/twistedcaldav/sql.py
===================================================================
--- 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)
@@ -18,7 +18,7 @@
 Generic SQL database access object.
 """
 
-__all__ = [ 
+__all__ = [
     "db_prefix",
     "DatabaseError",
     "AbstractSQLDatabase",
@@ -50,7 +50,7 @@
 
     def __init__(self, dbpath, persistent, autocommit=False):
         """
-        
+
         @param dbpath: the path where the db file is stored.
         @type dbpath: str
         @param persistent: C{True} if the data in the DB must be perserved during upgrades,
@@ -63,21 +63,25 @@
         self.persistent = persistent
         self.autocommit = autocommit
 
+
     def __repr__(self):
         return "<%s %r>" % (self.__class__.__name__, self.dbpath)
 
+
     def _db_version(self):
         """
         @return: the schema version assigned to this index.
         """
         raise NotImplementedError
-        
+
+
     def _db_type(self):
         """
         @return: the collection type assigned to this index.
         """
         raise NotImplementedError
-        
+
+
     def _db(self):
         """
         Access the underlying database.
@@ -108,7 +112,7 @@
                 # Create CALDAV table if needed
 
                 if self._test_schema_table(q):
-                    
+
                     version, dbtype = self._get_schema_version(q)
 
                     if (version != self._db_version()) or (dbtype != self._db_type()):
@@ -130,7 +134,7 @@
                         if version != self._db_version():
                             log.error("Database %s has different schema (v.%s vs. v.%s)"
                                       % (db_filename, version, self._db_version()))
-                            
+
                             # Upgrade the DB
                             return self._db_upgrade(version)
 
@@ -139,9 +143,11 @@
 
                 self._db_connection.commit()
             finally:
-                if q is not None: q.close()
+                if q is not None:
+                    q.close()
         return self._db_connection
 
+
     def _test_schema_table(self, q):
         q.execute("""
         select (1) from SQLITE_MASTER
@@ -149,6 +155,7 @@
         """)
         return q.fetchone()
 
+
     def _get_schema_version(self, q):
         q.execute(
             """
@@ -157,7 +164,8 @@
             """)
         version = q.fetchone()
 
-        if version is not None: version = version[0]
+        if version is not None:
+            version = version[0]
 
         q.execute(
             """
@@ -166,10 +174,12 @@
             """)
         dbtype = q.fetchone()
 
-        if dbtype is not None: dbtype = dbtype[0]
+        if dbtype is not None:
+            dbtype = dbtype[0]
 
         return version, dbtype
 
+
     def _db_init(self, db_filename, q):
         """
         Initialise the underlying database tables.
@@ -183,7 +193,7 @@
         old_isolation = self._db_connection.isolation_level
         self._db_connection.isolation_level = None
         q.execute("begin exclusive transaction")
-        
+
         # We re-check whether the schema table is present again AFTER we've got an exclusive
         # lock as some other server process may have snuck in and already created it
         # before we got the lock, or whilst we were waiting for it.
@@ -199,6 +209,7 @@
 
         self._db_connection.isolation_level = old_isolation
 
+
     def _db_init_schema_table(self, q):
         """
         Initialise the underlying database tables.
@@ -229,6 +240,7 @@
             """, [self._db_type()]
         )
 
+
     def _db_init_data_tables(self, q):
         """
         Initialise the underlying database tables.
@@ -237,6 +249,7 @@
         """
         raise NotImplementedError
 
+
     def _db_recreate(self, do_commit=True):
         """
         Recreate the database tables.
@@ -246,15 +259,17 @@
         if do_commit:
             self._db_commit()
 
+
     def _db_can_upgrade(self, old_version):
-        
+
         return self.persistent
 
+
     def _db_upgrade(self, old_version):
         """
         Upgrade the database tables.
         """
-        
+
         if self._db_can_upgrade(old_version):
             self._db_connection = sqlite.connect(self.dbpath, isolation_level=None)
             q = self._db_connection.cursor()
@@ -278,6 +293,7 @@
 
         return self._db()
 
+
     def _db_upgrade_data_tables(self, q, old_version):
         """
         Upgrade the data from an older version of the DB.
@@ -286,6 +302,7 @@
         # cannot be thrown away.
         raise NotImplementedError("Persistent databases MUST support an upgrade method.")
 
+
     def _db_upgrade_schema(self, q):
         """
         Upgrade the stored schema version to the current one.
@@ -297,11 +314,13 @@
             """, [self._db_version()]
         )
 
+
     def _db_close(self):
         if hasattr(self, "_db_connection"):
             self._db_connection.close()
             del self._db_connection
 
+
     def _db_values_for_sql(self, sql, *query_params):
         """
         Execute an SQL query and obtain the resulting values.
@@ -313,6 +332,7 @@
         """
         return (row[0] for row in self._db_execute(sql, *query_params))
 
+
     def _db_value_for_sql(self, sql, *query_params):
         """
         Execute an SQL query and obtain a single value.
@@ -328,6 +348,7 @@
             value = row
         return value
 
+
     def _db_execute(self, sql, *query_params):
         """
         Execute an SQL query and obtain the resulting values.
@@ -347,5 +368,10 @@
         finally:
             q.close()
 
-    def _db_commit  (self): self._db_connection.commit()
-    def _db_rollback(self): self._db_connection.rollback()
+
+    def _db_commit(self):
+        self._db_connection.commit()
+
+
+    def _db_rollback(self):
+        self._db_connection.rollback()

Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- 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)
@@ -36,6 +36,7 @@
 from twistedcaldav.util import computeProcessCount
 
 from calendarserver.push.util import getAPNTopicFromCertificate
+from twistedcaldav import ical
 
 log = Logger()
 
@@ -545,6 +546,11 @@
     "EnableManagedAttachments"    : False, # Support Managed Attachments
 
     #
+    # Generic CalDAV/CardDAV extensions
+    #
+    "EnableJSONData"          : True, # Allow clients to send/receive JSON jCal and jCard format data
+
+    #
     # Non-standard CalDAV extensions
     #
     "EnableDropBox"           : False, # Calendar Drop Box
@@ -594,6 +600,12 @@
                                                    # If on, it will also cause new accounts to provision with separate
                                                    # calendars for events and tasks.
 
+    "SupportedComponents" : [                      # Set of supported iCalendar components
+        "VEVENT",
+        "VTODO",
+        #"VPOLL",
+    ],
+
     "ParallelUpgrades" : False, # Perform upgrades - currently only the
                                    # database -> filesystem migration - but in
                                    # the future, hopefully all relevant
@@ -1502,6 +1514,14 @@
 
 
 
+def _updateICalendar(configDict, reloading=False):
+    """
+    Updated support iCalendar components.
+    """
+    ical._updateAllowedComponents(tuple(configDict.SupportedComponents))
+
+
+
 def _updateScheduling(configDict, reloading=False):
     #
     # Scheduling
@@ -1612,6 +1632,7 @@
     _updateRejectClients,
     _updateLogLevels,
     _updateNotifications,
+    _updateICalendar,
     _updateScheduling,
     _updateServers,
     _updateCompliance,

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- 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)
@@ -15,7 +15,7 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twext.python.log import Logger
 from twext.web2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
@@ -36,14 +36,14 @@
 from twisted.python.hashlib import md5
 from twisted.python.util import FancyEqMixin
 
-from twistedcaldav import customxml, carddavxml, caldavxml
+from twistedcaldav import customxml, carddavxml, caldavxml, ical
 from twistedcaldav.caldavxml import caldav_namespace, MaxAttendeesPerInstance, \
     MaxInstances, NoUIDConflict
 from twistedcaldav.carddavxml import carddav_namespace, NoUIDConflict as NovCardUIDConflict
 from twistedcaldav.config import config
 from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
 from twistedcaldav.ical import Component as VCalendar, Property as VProperty, \
-    InvalidICalendarDataError, iCalendarProductID, allowedComponents, Component
+    InvalidICalendarDataError, iCalendarProductID, Component
 from twistedcaldav.memcachelock import MemcacheLockTimeoutError
 from twistedcaldav.notifications import NotificationCollectionResource, NotificationResource
 from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource, \
@@ -82,6 +82,7 @@
 from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.instance import InvalidOverriddenInstanceError, \
     TooManyInstancesError
+from twistedcaldav.util import bestAcceptType
 import collections
 
 """
@@ -626,14 +627,17 @@
         # Read in all data
         data = (yield allDataFromStream(request.stream))
 
-        components = self.componentsFromData(data)
+        format = request.headers.getHeader("content-type")
+        if format:
+            format = "%s/%s" % (format.mediaType, format.mediaSubtype,)
+        components = self.componentsFromData(data, format)
         if components is None:
             raise HTTPError(StatusResponse(BAD_REQUEST, "Could not parse valid data from request body"))
 
         # Build response
         xmlresponses = [None] * len(components)
         indexedComponents = [idxComponent for idxComponent in enumerate(components)]
-        yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
+        yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses, format)
 
         result = MultiStatusResponse(xmlresponses)
 
@@ -650,7 +654,7 @@
 
 
     @inlineCallbacks
-    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses, format):
         """
         Do create from simpleBatchPOST or crudCreate()
         Subclasses may override
@@ -664,7 +668,7 @@
                 # Get a resource for the new item
                 newchildURL = joinURL(request.path, name)
                 newchild = (yield request.locateResource(newchildURL))
-                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
+                changedComponent = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
 
             except HTTPError, e:
                 # Extract the pre-condition
@@ -674,30 +678,30 @@
                     error = (error.namespace, error.name,)
 
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error, format)
                 )
 
             except Exception:
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, BAD_REQUEST, None, format)
                 )
 
             else:
                 if not return_changed:
-                    changedData = None
+                    changedComponent = None
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
                 )
 
 
     @inlineCallbacks
-    def bulkCreateResponse(self, component, newchildURL, newchild, changedData, code, error):
+    def bulkCreateResponse(self, component, newchildURL, newchild, changedComponent, code, error, format):
         """
         generate one xmlresponse for bulk create
         """
         if code is None:
             etag = (yield newchild.etag())
-            if changedData is None:
+            if changedComponent is None:
                 returnValue(
                     davxml.PropertyStatusResponse(
                         davxml.HRef.fromString(newchildURL),
@@ -717,7 +721,7 @@
                         davxml.PropertyStatus(
                             davxml.PropertyContainer(
                                 davxml.GETETag.fromString(etag.generate()),
-                                self.xmlDataElementType().fromTextData(changedData),
+                                self.xmlDataElementType().fromComponent(changedComponent, format),
                             ),
                             davxml.Status.fromResponseCode(OK),
                         )
@@ -822,6 +826,7 @@
             for index, xmldata in crudCreateInfo:
 
                 component = xmldata.generateComponent()
+                format = xmldata.content_type
 
                 if hasPrivilege is not True:
                     e = hasPrivilege # use same code pattern as exception
@@ -830,13 +835,13 @@
                         error = e.response.error
                         error = (error.namespace, error.name,)
 
-                    xmlresponse = yield self.bulkCreateResponse(component, None, None, None, code, error)
+                    xmlresponse = yield self.bulkCreateResponse(component, None, None, None, code, error, format)
                     xmlresponses[index] = xmlresponse
 
                 else:
                     indexedComponents.append((index, component,))
 
-            yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
+            yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses, format)
 
 
     @inlineCallbacks
@@ -847,8 +852,8 @@
             code = None
             error = None
             try:
-                componentdata = xmldata.textData()
                 component = xmldata.generateComponent()
+                format = xmldata.content_type
 
                 updateResource = (yield request.locateResource(href))
                 if not updateResource.exists():
@@ -862,7 +867,7 @@
                 if ifmatch and ifmatch != etag.generate():
                     raise HTTPError(PRECONDITION_FAILED)
 
-                changedData = yield self.storeResourceData(updateResource, component, componentdata)
+                changedComponent = yield self.storeResourceData(updateResource, component, returnChangedData=return_changed)
 
             except HTTPError, e:
                 # Extract the pre-condition
@@ -875,7 +880,7 @@
                 code = BAD_REQUEST
 
             if code is None:
-                if not return_changed or changedData is None:
+                if changedComponent is None:
                     xmlresponses[index] = davxml.PropertyStatusResponse(
                         davxml.HRef.fromString(href),
                         davxml.PropertyStatus(
@@ -891,7 +896,7 @@
                         davxml.PropertyStatus(
                             davxml.PropertyContainer(
                                 davxml.GETETag.fromString(etag.generate()),
-                                self.xmlDataElementType().fromTextData(changedData),
+                                self.xmlDataElementType().fromComponentData(changedComponent, format),
                             ),
                             davxml.Status.fromResponseCode(OK),
                         )
@@ -989,7 +994,7 @@
         if comps:
             comps = comps.split(",")
         else:
-            comps = allowedComponents
+            comps = ical.allowedStoreComponents
         return caldavxml.SupportedCalendarComponentSet(
             *[caldavxml.CalendarComponent(name=item) for item in comps]
         )
@@ -1016,7 +1021,7 @@
         if comps:
             comps = comps.split(",")
         else:
-            comps = allowedComponents
+            comps = ical.allowedStoreComponents
         return comps
 
 
@@ -1053,6 +1058,8 @@
 
         if config.EnableBatchUpload:
             self._postHandlers[("text", "calendar")] = _CommonHomeChildCollectionMixin.simpleBatchPOST
+            if config.EnableJSONData:
+                self._postHandlers[("application", "calendar+json")] = _CommonHomeChildCollectionMixin.simpleBatchPOST
             self.xmlDocHandlers[customxml.Multiput] = _CommonHomeChildCollectionMixin.crudBatchPOST
 
 
@@ -1088,6 +1095,11 @@
     def iCalendarRolledup(self, request):
         # FIXME: uncached: implement cache in the storage layer
 
+        # 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"))
+
         # Generate a monolithic calendar
         calendar = VCalendar("VCALENDAR")
         calendar.addProperty(VProperty("VERSION", "2.0"))
@@ -1138,17 +1150,13 @@
 
                     calendar.addComponent(component)
 
-        # Cache the data
-        data = str(calendar)
-        data = (yield self.getInternalSyncToken()) + "\r\n" + data
+        returnValue((calendar, accepted_type,))
 
-        returnValue(calendar)
-
     createCalendarCollection = _CommonHomeChildCollectionMixin.createCollection
 
 
     @classmethod
-    def componentsFromData(cls, data):
+    def componentsFromData(cls, data, format):
         """
         Need to split a single VCALENDAR into separate ones based on UID with the
         appropriate VTIEMZONES included.
@@ -1158,7 +1166,7 @@
 
         # Split into components by UID and TZID
         try:
-            vcal = VCalendar.fromString(data)
+            vcal = VCalendar.fromString(data, format)
         except InvalidICalendarDataError:
             return None
 
@@ -1242,7 +1250,8 @@
 
         elif qname == caldavxml.CalendarTimeZone.qname():
             timezone = self._newStoreObject.getTimezone()
-            returnValue(caldavxml.CalendarTimeZone.fromString(str(timezone)) if timezone else None)
+            format = property.content_type if isinstance(property, caldavxml.CalendarTimeZone) else None
+            returnValue(caldavxml.CalendarTimeZone.fromCalendar(timezone, format=format) if timezone else None)
 
         result = (yield super(CalendarCollectionResource, self).readProperty(property, request))
         returnValue(result)
@@ -1288,7 +1297,7 @@
         yield newchild.storeComponent(component)
         if returnChangedData and newchild._newStoreObject._componentChanged:
             result = (yield newchild.componentForUser())
-            returnValue(str(result))
+            returnValue(result)
         else:
             returnValue(None)
 
@@ -2210,16 +2219,38 @@
         return self._newStoreObject.component()
 
 
+    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
+
+
     @inlineCallbacks
     def render(self, request):
         if not self.exists():
             log.debug("Resource not found: %s" % (self,))
             raise HTTPError(NOT_FOUND)
 
+        # 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"))
+
         output = yield self.component()
 
-        response = Response(OK, {}, str(output))
-        response.headers.setHeader("content-type", self.contentType())
+        response = Response(OK, {}, output.getText(accepted_type))
+        response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (accepted_type,)))
         returnValue(response)
 
 
@@ -2379,10 +2410,10 @@
 
 
     @inlineCallbacks
-    def storeStream(self, stream):
+    def storeStream(self, stream, format):
 
         # FIXME: direct tests
-        component = self._componentFromStream((yield allDataFromStream(stream)))
+        component = self._componentFromStream((yield allDataFromStream(stream)), format)
         result = (yield self.storeComponent(component))
         returnValue(result)
 
@@ -2514,6 +2545,13 @@
 
     _componentFromStream = VCalendar.fromString
 
+    def allowedTypes(self):
+        """
+        Return a tuple of allowed MIME types for storing.
+        """
+        return Component.allowedTypes()
+
+
     @inlineCallbacks
     def inNewTransaction(self, request, label=""):
         """
@@ -2541,12 +2579,6 @@
         self._initializeWithObject(newObject, newParent)
         returnValue(txn)
 
-
-    @inlineCallbacks
-    def iCalendarText(self):
-        data = yield self.iCalendar()
-        returnValue(str(data))
-
     iCalendar = _CommonObjectResource.component
 
 
@@ -2710,7 +2742,8 @@
 
         # Content-type check
         content_type = request.headers.getHeader("content-type")
-        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "calendar"):
+        format = self.determineType(content_type)
+        if format is None:
             log.error("MIME type %s not allowed in calendar collection" % (content_type,))
             raise HTTPError(ErrorResponse(
                 responsecode.FORBIDDEN,
@@ -2745,13 +2778,13 @@
                 ))
 
             try:
-                component = Component.fromString(calendardata)
+                component = Component.fromString(calendardata, format)
             except ValueError, e:
                 log.error(str(e))
                 raise HTTPError(ErrorResponse(
                     responsecode.FORBIDDEN,
                     (caldav_namespace, "valid-calendar-data"),
-                    "Can't parse calendar data"
+                    "Can't parse calendar data: %s" % (str(e),)
                 ))
 
             # storeComponent needs to know who the auth'd user is for access control
@@ -2864,7 +2897,7 @@
             if rids is not None:
                 rids = rids[0].split(",")
                 try:
-                    rids = [PyCalendarDateTime.parseText(rid) if rid != "M" else None for rid in rids]
+                    rids = [DateTime.parseText(rid) if rid != "M" else None for rid in rids]
                 except ValueError:
                     raise HTTPError(ErrorResponse(
                         FORBIDDEN,
@@ -3001,6 +3034,8 @@
 
         if config.EnableBatchUpload:
             self._postHandlers[("text", "vcard")] = AddressBookCollectionResource.simpleBatchPOST
+            if config.EnableJSONData:
+                self._postHandlers[("application", "vcard+json")] = _CommonHomeChildCollectionMixin.simpleBatchPOST
             self.xmlDocHandlers[customxml.Multiput] = AddressBookCollectionResource.crudBatchPOST
 
 
@@ -3032,9 +3067,9 @@
 
 
     @classmethod
-    def componentsFromData(cls, data):
+    def componentsFromData(cls, data, format):
         try:
-            return VCard.allFromString(data)
+            return VCard.allFromString(data, format)
         except InvalidVCardDataError:
             return None
 
@@ -3055,7 +3090,7 @@
         yield newchild.storeComponent(component)
         if returnChangedData and newchild._newStoreObject._componentChanged:
             result = (yield newchild.component())
-            returnValue(str(result))
+            returnValue(result)
         else:
             returnValue(None)
 
@@ -3096,7 +3131,7 @@
 
 
     @inlineCallbacks
-    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses, format):
         """
         bulk create allowing groups to contain member UIDs added during the same bulk create
         """
@@ -3111,7 +3146,7 @@
                 # Get a resource for the new item
                 newchildURL = joinURL(request.path, name)
                 newchild = (yield request.locateResource(newchildURL))
-                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
+                changedComponent = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
 
             except GroupWithUnsharedAddressNotAllowedError, e:
                 # save off info and try again below
@@ -3126,20 +3161,20 @@
                     error = (error.namespace, error.name,)
 
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error, format)
                 )
 
             except Exception:
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, BAD_REQUEST, None, format)
                 )
 
             else:
                 if not return_changed:
-                    changedData = None
+                    changedComponent = None
                 coaddedUIDs |= set([component.resourceUID()])
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
                 )
 
         if groupRetries:
@@ -3157,7 +3192,7 @@
                 # give FORBIDDEN response
                 index, component, newchildURL, newchild, missingUIDs = groupRetry
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData=None, code=FORBIDDEN, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, FORBIDDEN, None, format)
                 )
                 coaddedUIDs -= set([component.resourceUID()]) # group uid not added
                 groupRetries.remove(groupRetry) # remove this retry
@@ -3167,11 +3202,11 @@
                 newchild._metadata["coaddedUIDs"] = coaddedUIDs
 
                 # don't catch errors, abort the whole transaction
-                changedData = yield self.storeResourceData(newchild, component, returnChangedData=return_changed)
+                changedComponent = yield self.storeResourceData(newchild, component, returnChangedData=return_changed)
                 if not return_changed:
-                    changedData = None
+                    changedComponent = None
                 xmlresponses[index] = (
-                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedComponent, None, None, format)
                 )
 
 
@@ -3266,6 +3301,13 @@
 
     _componentFromStream = VCard.fromString
 
+    def allowedTypes(self):
+        """
+        Return a tuple of allowed MIME types for storing.
+        """
+        return VCard.allowedTypes()
+
+
     @inlineCallbacks
     def vCardText(self):
         data = yield self.vCard()
@@ -3340,7 +3382,8 @@
 
         # Content-type check
         content_type = request.headers.getHeader("content-type")
-        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "vcard"):
+        format = self.determineType(content_type)
+        if format is None:
             log.error("MIME type %s not allowed in vcard collection" % (content_type,))
             raise HTTPError(ErrorResponse(
                 responsecode.FORBIDDEN,
@@ -3365,7 +3408,7 @@
                 ))
 
             try:
-                component = VCard.fromString(vcarddata)
+                component = VCard.fromString(vcarddata, format)
             except ValueError, e:
                 log.error(str(e))
                 raise HTTPError(ErrorResponse(

Modified: CalendarServer/trunk/twistedcaldav/test/test_addressbookmultiget.py
===================================================================
--- 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)
@@ -19,17 +19,19 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from txdav.xml import element as davxml
 from twext.web2.dav.util import davXMLFromStream, joinURL
+from twext.web2.http_headers import Headers, MimeType
 
 from twistedcaldav import carddavxml
 from twistedcaldav import vcard
-
 from twistedcaldav.config import config
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
+
 from twisted.python.filepath import FilePath
 from twisted.internet.defer import inlineCallbacks, returnValue
 
+from txdav.xml import element as davxml
+
 class AddressBookMultiget (StoreTestCase):
     """
     addressbook-multiget REPORT
@@ -214,7 +216,13 @@
             '''
             if data:
                 for filename, icaldata in data.iteritems():
-                    request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, filename + ".vcf"), authid="wsanchez")
+                    request = SimpleStoreRequest(
+                        self,
+                        "PUT",
+                        joinURL(addressbook_uri, filename + ".vcf"),
+                        headers=Headers({"content-type": MimeType.fromString("text/vcard")}),
+                        authid="wsanchez"
+                    )
                     request.stream = MemoryStream(icaldata)
                     yield self.send(request)
             else:
@@ -222,7 +230,13 @@
                 for child in FilePath(self.vcards_dir).children():
                     if os.path.splitext(child.basename())[1] != ".vcf":
                         continue
-                    request = SimpleStoreRequest(self, "PUT", joinURL(addressbook_uri, child.basename()), authid="wsanchez")
+                    request = SimpleStoreRequest(
+                        self,
+                        "PUT",
+                        joinURL(addressbook_uri, child.basename()),
+                        headers=Headers({"content-type": MimeType.fromString("text/vcard")}),
+                        authid="wsanchez"
+                    )
                     request.stream = MemoryStream(child.getContent())
                     yield self.send(request)
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_caldavxml.py
===================================================================
--- 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)
@@ -14,9 +14,16 @@
 # limitations under the License.
 ##
 
+import twistedcaldav.test.util
 from twistedcaldav import caldavxml
-import twistedcaldav.test.util
+from twistedcaldav.caldavxml import CalendarData
+from twistedcaldav.ical import normalize_iCalStr, Component
 
+def normalizeJSON(j):
+    return "".join(map(str.strip, j.splitlines())).replace(", ", ",").replace(": ", ":")
+
+
+
 class CustomXML (twistedcaldav.test.util.TestCase):
 
 
@@ -50,3 +57,99 @@
 
         tr = caldavxml.CalDAVTimeRangeElement(start="20110201T120000Z", end="20110202")
         self.assertFalse(tr.valid())
+
+
+    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 at example.com
+ATTENDEE:mailto:user2 at example.com
+DTSTAMP:20080601T120000Z
+EXDATE:20080602T120000Z
+EXDATE:20080603T120000Z
+ORGANIZER;CN=User 01:mailto:user1 at 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 at example.com"],
+        ["attendee", {}, "cal-address", "mailto:user2 at 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 at 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))

Modified: CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
===================================================================
--- 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)
@@ -32,7 +32,7 @@
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
 from twisted.internet.defer import inlineCallbacks, returnValue
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twistedcaldav.ical import Component
 from txdav.caldav.icalendarstore import ComponentUpdateState
 from twistedcaldav.directory.directory import DirectoryService
@@ -124,8 +124,8 @@
         )
 
         query_timerange = caldavxml.TimeRange(
-            start="%04d1001T000000Z" % (PyCalendarDateTime.getToday().getYear(),),
-            end="%04d1101T000000Z" % (PyCalendarDateTime.getToday().getYear(),),
+            start="%04d1001T000000Z" % (DateTime.getToday().getYear(),),
+            end="%04d1101T000000Z" % (DateTime.getToday().getYear(),),
         )
 
         query = caldavxml.CalendarQuery(

Modified: CalendarServer/trunk/twistedcaldav/test/test_dateops.py
===================================================================
--- 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)
@@ -16,7 +16,7 @@
 
 import twistedcaldav.test.util
 from twisted.trial.unittest import SkipTest
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twistedcaldav.dateops import parseSQLTimestampToPyCalendar, \
     parseSQLDateToPyCalendar, pyCalendarTodatetime, \
@@ -24,7 +24,7 @@
 
 import datetime
 import dateutil
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.timezone import Timezone
 from twistedcaldav.timezones import TimezoneCache
 
 class Dateops(twistedcaldav.test.util.TestCase):
@@ -43,10 +43,10 @@
         """
 
         data = (
-            (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))),
+            (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))),
         )
 
         for value, result in data:
@@ -59,10 +59,10 @@
         """
 
         data = (
-            (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))),
+            (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))),
         )
 
         for value, result in data:
@@ -75,10 +75,10 @@
         """
 
         data = (
-            (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))),
+            (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))),
         )
 
         for value, result in data:
@@ -107,132 +107,132 @@
             # Timed
             (
                 "Start within, end within - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "Start before, end before - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "Start before, end right before - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "Start before, end within - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "Start after, end after - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "Start right after, end after - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "Start within, end after - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "Start before, end after - overlap",
-                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)),
+                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)),
                 True,
             ),
 
             # All day
             (
                 "All day: Start within, end within - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "All day: Start before, end before - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "All day: Start before, end right before - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "All day: Start before, end within - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "All day: Start after, end after - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "All day: Start right after, end after - no overlap",
-                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)),
+                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)),
                 False,
             ),
             (
                 "All day: Start within, end after - overlap",
-                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)),
+                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)),
                 True,
             ),
             (
                 "All day: Start before, end after - overlap",
-                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)),
+                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)),
                 True,
             ),
         )
@@ -254,8 +254,8 @@
         dateops.pyCalendarTodatetime
         """
         tests = (
-            (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)),
+            (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)),
         )
 
         for pycal, result in tests:
@@ -267,8 +267,8 @@
         dateops.parseSQLTimestampToPyCalendar
         """
         tests = (
-            ("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)),
+            ("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)),
         )
 
         for sqlStr, result in tests:
@@ -281,8 +281,8 @@
         """
 
         tests = (
-            ("2012-04-04", PyCalendarDateTime(2012, 4, 4)),
-            ("2012-12-31 00:00:00", PyCalendarDateTime(2012, 12, 31)),
+            ("2012-04-04", DateTime(2012, 4, 4)),
+            ("2012-12-31 00:00:00", DateTime(2012, 12, 31)),
         )
 
         for sqlStr, result in tests:

Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
===================================================================
--- 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)
@@ -25,12 +25,12 @@
 from twistedcaldav.instance import InvalidOverriddenInstanceError
 import twistedcaldav.test.util
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 from twistedcaldav.ical import iCalendarProductID
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.duration import Duration
 from twistedcaldav.dateops import normalizeForExpand
-from pycalendar.value import PyCalendarValue
+from pycalendar.value import Value
 
 class iCalendar (twistedcaldav.test.util.TestCase):
     """
@@ -469,7 +469,7 @@
         calendar.validCalendarData(doFix=False, validateRecurrences=True)
 
         # Verify expansion works, even for an RDATE prior to master DTSTART:
-        calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        calendar.expandTimeRanges(DateTime(2100, 1, 1))
 
         # Test EXDATEs *prior* to master (as the result of client splitting a
         # a recurring event and copying *all* EXDATEs to new event):
@@ -568,13 +568,13 @@
 
         year = 2004
 
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
-            self.assertEqual(start, PyCalendarDateTime(year, 7, 4))
-            self.assertEqual(end  , PyCalendarDateTime(year, 7, 5))
+            self.assertEqual(start, DateTime(year, 7, 4))
+            self.assertEqual(end  , DateTime(year, 7, 5))
             if year == 2050:
                 break
             year += 1
@@ -594,14 +594,14 @@
         }
         year = 2004
 
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
             if year in results:
-                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
+                self.assertEqual(start, DateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , DateTime(year, results[year][0], results[year][2]))
             if year == 2050:
                 break
             year += 1
@@ -621,14 +621,14 @@
         }
         year = 2002
 
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
             if year in results:
-                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
+                self.assertEqual(start, DateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , DateTime(year, results[year][0], results[year][2]))
             if year == 2050:
                 break
             year += 1
@@ -642,13 +642,13 @@
         """
         calendar = Component.fromStream(file(os.path.join(self.data_dir, "Holidays", "C318ABFE-1ED0-11D9-A5E0-000A958A3252.ics")))
 
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
-            self.assertEqual(start, PyCalendarDateTime(2004, 11, 25))
-            self.assertEqual(end, PyCalendarDateTime(2004, 11, 27))
+            self.assertEqual(start, DateTime(2004, 11, 25))
+            self.assertEqual(end, DateTime(2004, 11, 27))
             break
 
     # test_component_timerange.todo = "recurrence expansion should give us no end date here"
@@ -658,44 +658,44 @@
         """
         parse_date()
         """
-        self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
+        self.assertEqual(DateTime.parseText("19970714"), DateTime(1997, 7, 14))
 
 
     def test_parse_datetime(self):
         """
         parse_datetime()
         """
-        dt = PyCalendarDateTime.parseText("19980118T230000")
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+        dt = DateTime.parseText("19980118T230000")
+        self.assertEqual(dt, DateTime(1998, 1, 18, 23, 0, 0))
         self.assertTrue(dt.floating())
 
-        dt = PyCalendarDateTime.parseText("19980119T070000Z")
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        dt = DateTime.parseText("19980119T070000Z")
+        self.assertEqual(dt, DateTime(1998, 1, 19, 7, 0, 0, tzid=Timezone(utc=True)))
 
 
     def test_parse_date_or_datetime(self):
         """
         parse_date_or_datetime()
         """
-        self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
+        self.assertEqual(DateTime.parseText("19970714"), DateTime(1997, 7, 14))
 
-        dt = PyCalendarDateTime.parseText("19980118T230000")
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+        dt = DateTime.parseText("19980118T230000")
+        self.assertEqual(dt, DateTime(1998, 1, 18, 23, 0, 0))
         self.assertTrue(dt.floating())
 
-        dt = PyCalendarDateTime.parseText("19980119T070000Z")
-        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        dt = DateTime.parseText("19980119T070000Z")
+        self.assertEqual(dt, DateTime(1998, 1, 19, 7, 0, 0, tzid=Timezone(utc=True)))
 
 
     def test_parse_duration(self):
         """
         parse_duration()
         """
-        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))
+        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))
 
-        self.assertEqual(PyCalendarDuration.parseText("P7W"), PyCalendarDuration(weeks=7))
+        self.assertEqual(Duration.parseText("P7W"), Duration(weeks=7))
 
 
     def test_correct_attendee_properties(self):
@@ -807,7 +807,7 @@
 """,
                 (
                     ("mailto:user1 at example.com", None),
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+                    ("mailto:user1 at example.com", DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
                 )
             ),
             (
@@ -833,7 +833,7 @@
 """,
                 (
                     ("mailto:user1 at example.com", None),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+                    ("mailto:user3 at example.com", DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
                 )
             ),
             (
@@ -946,8 +946,8 @@
                 False,
                 (
                     ("mailto:user2 at example.com", None),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+                    ("mailto:user2 at example.com", DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)))
                 )
             ),
             (
@@ -1177,7 +1177,7 @@
 
         component = Component.fromString(data)
         vevent = component.mainComponent()
-        vevent.addProperty(Property("ATTACH", "foobar", valuetype=PyCalendarValue.VALUETYPE_BINARY))
+        vevent.addProperty(Property("ATTACH", "foobar", valuetype=Value.VALUETYPE_BINARY))
         self.assertEqual(str(component), result)
 
 
@@ -2277,8 +2277,8 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2299,12 +2299,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2326,16 +2326,16 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 2, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2357,12 +2357,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2384,12 +2384,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2417,12 +2417,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 2, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2474,12 +2474,12 @@
                 True,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2488,9 +2488,9 @@
         for description, original, ignoreInvalidInstances, results in data:
             component = Component.fromString(original)
             if results is None:
-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
             else:
-                instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
+                instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
                 self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
                 periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
                 self.assertEqual(periods, results)
@@ -2518,8 +2518,8 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2539,8 +2539,8 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
                     ),
                 )
             ),
@@ -2561,12 +2561,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2587,12 +2587,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 17),
+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 17),
                     ),
                 )
             ),
@@ -2614,16 +2614,16 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 2, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2645,16 +2645,16 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 17),
+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 17),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 18),
-                        PyCalendarDateTime(2007, 11, 19),
+                        DateTime(2007, 11, 18),
+                        DateTime(2007, 11, 19),
                     ),
                 )
             ),
@@ -2676,12 +2676,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 16, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 16, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2703,12 +2703,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 17),
-                        PyCalendarDateTime(2007, 11, 18),
+                        DateTime(2007, 11, 17),
+                        DateTime(2007, 11, 18),
                     ),
                 )
             ),
@@ -2736,12 +2736,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 2, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -2769,12 +2769,12 @@
                 False,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 15),
-                        PyCalendarDateTime(2007, 11, 16),
+                        DateTime(2007, 11, 15),
+                        DateTime(2007, 11, 16),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 16),
-                        PyCalendarDateTime(2007, 11, 18),
+                        DateTime(2007, 11, 16),
+                        DateTime(2007, 11, 18),
                     ),
                 )
             ),
@@ -2831,9 +2831,9 @@
         for description, original, ignoreInvalidInstances, results in data:
             component = Component.fromString(original)
             if results is None:
-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances)
             else:
-                instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances, normalizeFunction=normalizeForExpand)
+                instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=ignoreInvalidInstances, normalizeFunction=normalizeForExpand)
                 self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
                 periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
                 self.assertEqual(periods, results)
@@ -2861,8 +2861,8 @@
                 None,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -2880,11 +2880,11 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2007, 1, 1),
+                DateTime(2007, 1, 1),
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -2902,9 +2902,9 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
                 (),
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
             ),
             (
                 "Simple recurring - no limit",
@@ -2923,20 +2923,20 @@
                 None,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -2955,23 +2955,23 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2007, 1, 1),
+                DateTime(2007, 1, 1),
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -2990,14 +2990,14 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
                 (
                     (
-                        PyCalendarDateTime(2010, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
             ),
             (
                 "Simple recurring - limit effective full",
@@ -3013,9 +3013,9 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2012, 1, 1),
+                DateTime(2012, 1, 1),
                 (),
-                PyCalendarDateTime(2012, 1, 1),
+                DateTime(2012, 1, 1),
             ),
             (
                 "Complex recurring - no limit",
@@ -3048,20 +3048,20 @@
                 None,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2008, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2008, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -3094,23 +3094,23 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2007, 1, 1),
+                DateTime(2007, 1, 1),
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2008, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2008, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2008, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2008, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2009, 11, 14, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2009, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2009, 11, 14, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
                 None,
@@ -3143,14 +3143,14 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
                 (
                     (
-                        PyCalendarDateTime(2010, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2010, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2010, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2010, 11, 15, 1, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 ),
-                PyCalendarDateTime(2010, 1, 1),
+                DateTime(2010, 1, 1),
             ),
             (
                 "Complex recurring - limit effective full",
@@ -3180,15 +3180,15 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2012, 1, 1),
+                DateTime(2012, 1, 1),
                 (),
-                PyCalendarDateTime(2012, 1, 1),
+                DateTime(2012, 1, 1),
             ),
         )
 
         for description, original, lowerLimit, results, limited in data:
             component = Component.fromString(original)
-            instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), lowerLimit=lowerLimit)
+            instances = component.expandTimeRanges(DateTime(2100, 1, 1), lowerLimit=lowerLimit)
             self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
             periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
             self.assertEqual(periods, results)
@@ -4040,7 +4040,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T080000Z
@@ -4065,7 +4065,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 18, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T180000Z
@@ -4091,7 +4091,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 3, 18, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090103T180000Z
@@ -4115,7 +4115,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 9, 0, 0, tzid=Timezone(utc=True)),
                 None,
             ),
             (
@@ -4133,7 +4133,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 19, 0, 0, tzid=Timezone(utc=True)),
                 None,
             ),
             (
@@ -4152,7 +4152,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 3, 19, 0, 0, tzid=Timezone(utc=True)),
                 None,
             ),
             (
@@ -4169,7 +4169,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 8),
+                DateTime(2009, 1, 8),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090108
@@ -4194,7 +4194,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 3),
+                DateTime(2009, 1, 3),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090103
@@ -4220,7 +4220,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 10),
+                DateTime(2009, 1, 10),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090110
@@ -4244,7 +4244,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 3),
+                DateTime(2009, 1, 3),
                 None,
             ),
             (
@@ -4262,7 +4262,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 5),
+                DateTime(2009, 1, 5),
                 None,
             ),
             (
@@ -4281,7 +4281,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 19),
+                DateTime(2009, 1, 19),
                 None,
             ),
         )
@@ -4311,8 +4311,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 4, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -4349,8 +4349,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 2, 18, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 4, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -4388,8 +4388,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 5, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 3, 18, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 5, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -4425,8 +4425,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 2, 9, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     None,
@@ -4456,8 +4456,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 2, 19, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     None,
@@ -4488,8 +4488,8 @@
 END:VCALENDAR
 """,
                 (
-                    PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    DateTime(2009, 1, 3, 19, 0, 0, tzid=Timezone(utc=True)),
+                    DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)),
                 ),
                 (
                     None,
@@ -4534,7 +4534,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T080000Z
@@ -4561,7 +4561,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T080000Z
@@ -4604,19 +4604,19 @@
         self.assertFalse(hasattr(ical, "cachedInstances"))
 
         # Derive one day apart - no re-cache
-        ical.deriveInstance(PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        ical.deriveInstance(DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)))
         self.assertTrue(hasattr(ical, "cachedInstances"))
         oldLimit = ical.cachedInstances.limit
-        ical.deriveInstance(PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        ical.deriveInstance(DateTime(2009, 1, 3, 8, 0, 0, tzid=Timezone(utc=True)))
         self.assertEqual(ical.cachedInstances.limit, oldLimit)
 
         # Derive several years ahead - re-cached
-        ical.deriveInstance(PyCalendarDateTime(2011, 1, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        ical.deriveInstance(DateTime(2011, 1, 1, 8, 0, 0, tzid=Timezone(utc=True)))
         self.assertNotEqual(ical.cachedInstances.limit, oldLimit)
         oldLimit = ical.cachedInstances.limit
 
         # Check one day ahead again - no re-cache
-        ical.deriveInstance(PyCalendarDateTime(2011, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+        ical.deriveInstance(DateTime(2011, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)))
         self.assertEqual(ical.cachedInstances.limit, oldLimit)
 
 
@@ -4661,13 +4661,13 @@
         masterDerived = ical.masterDerived()
 
         # Derive one day apart - no re-cache
-        result = ical.deriveInstance(PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
+        result = ical.deriveInstance(DateTime(2009, 1, 2, 8, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
         self.assertEqual(str(result), derived1)
 
-        result = ical.deriveInstance(PyCalendarDateTime(2009, 2, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
+        result = ical.deriveInstance(DateTime(2009, 2, 3, 8, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
         self.assertEqual(str(result), derived2)
 
-        result = ical.deriveInstance(PyCalendarDateTime(2009, 3, 3, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)), newcomp=masterDerived)
+        result = ical.deriveInstance(DateTime(2009, 3, 3, 9, 0, 0, tzid=Timezone(utc=True)), newcomp=masterDerived)
         self.assertEqual(result, None)
 
         self.assertEqual(str(ical), event)
@@ -4847,8 +4847,8 @@
 """,
                 (
                     (None, True),
-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
-                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
+                    (DateTime(2009, 10, 4, 0, 0, 0, tzid=Timezone(utc=True)), False),
                 )
             ),
             (
@@ -4866,9 +4866,9 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -4886,10 +4886,10 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -4908,11 +4908,11 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -4932,12 +4932,12 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -4960,11 +4960,11 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -4989,12 +4989,12 @@
 """,
                 (
                     (None, True),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -5012,9 +5012,9 @@
 """,
                 (
                     (None, False),
-                    (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),
+                    (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),
                 )
             ),
             (
@@ -5046,7 +5046,7 @@
 END:VCALENDAR
 """,
                 (
-                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (DateTime(2007, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)), True),
                 )
             ),
             (
@@ -5062,7 +5062,7 @@
 END:VCALENDAR
 """,
                 (
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), False),
                 )
             ),
             (
@@ -5084,7 +5084,7 @@
 END:VCALENDAR
 """,
                 (
-                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (DateTime(2007, 11, 15, 0, 0, 0, tzid=Timezone(utc=True)), False),
                 )
             ),
         )
@@ -5396,12 +5396,12 @@
 """,
                 (
                     (
-                        PyCalendarDateTime(2007, 11, 14, 20, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 14, 21, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 14, 20, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 14, 21, 0, 0, tzid=Timezone(utc=True)),
                     ),
                     (
-                        PyCalendarDateTime(2007, 11, 15, 21, 0, 0, tzid=PyCalendarTimezone(utc=True)),
-                        PyCalendarDateTime(2007, 11, 15, 22, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                        DateTime(2007, 11, 15, 21, 0, 0, tzid=Timezone(utc=True)),
+                        DateTime(2007, 11, 15, 22, 0, 0, tzid=Timezone(utc=True)),
                     ),
                 )
             ),
@@ -5409,7 +5409,7 @@
 
         for description, original, fixed, results in data:
             component = Component.fromString(original)
-            instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances=False)
+            instances = component.expandTimeRanges(DateTime(2100, 1, 1), ignoreInvalidInstances=False)
             self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
             periods = tuple([(instance.start, instance.end) for instance in sorted(instances.instances.values(), key=lambda x:x.start)])
             self.assertEqual(periods, results)
@@ -5696,7 +5696,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                 ),
@@ -5741,7 +5741,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -5795,7 +5795,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -5841,19 +5841,19 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", True,),
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", True,),
                                 ),
@@ -5916,21 +5916,21 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -6015,7 +6015,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 2, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
@@ -6023,7 +6023,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 3, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
@@ -6031,7 +6031,7 @@
                                 ),
                             ),
                             (
-                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                                DateTime(2008, 6, 4, 12, 0, 0, tzid=Timezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -7415,7 +7415,7 @@
 """,
             ),
         )
-        cutoff = PyCalendarDateTime(2011, 11, 30, 0, 0, 0)
+        cutoff = DateTime(2011, 11, 30, 0, 0, 0)
         for _ignore_title, expected, body in data:
             ical = Component.fromString(body)
             self.assertEquals(expected, ical.hasInstancesAfter(cutoff))
@@ -9437,7 +9437,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9505,7 +9505,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9577,7 +9577,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9626,7 +9626,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9676,7 +9676,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 31, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 31, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9725,7 +9725,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 1, 31, 6, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 1, 31, 6, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9795,7 +9795,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -9944,7 +9944,7 @@
 END:X-CALENDARSERVER-PERUSER
 END:VCALENDAR
 """,
-                PyCalendarDateTime(2009, 2, 1, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                DateTime(2009, 2, 1, 8, 0, 0, tzid=Timezone(utc=True)),
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN

Modified: CalendarServer/trunk/twistedcaldav/test/test_localization.py
===================================================================
--- 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)
@@ -20,7 +20,8 @@
 from twistedcaldav.ical import Component
 from twistedcaldav.test.util import TestCase
 from twistedcaldav.config import ConfigDict
-from pycalendar.datetime import PyCalendarDateTime
+from twistedcaldav.timezones import TimezoneCache
+from pycalendar.datetime import DateTime
 
 import os
 
@@ -52,6 +53,11 @@
 
 class LocalizationTests(TestCase):
 
+    def setUp(self):
+        super(LocalizationTests, self).setUp()
+        TimezoneCache.create()
+
+
     def test_BasicStringLocalization(self):
 
         with translationTo('pig', localeDir=localeDir):
@@ -68,22 +74,22 @@
 
         with translationTo('en', localeDir=localeDir) as t:
 
-            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")
+            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")
 
 
     def test_TimeFormatting24Hour(self):
 
         with translationTo('pig', localeDir=localeDir) as t:
 
-            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")
+            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")
 
 
     def test_CalendarFormatting(self):

Modified: CalendarServer/trunk/twistedcaldav/test/test_multiget.py
===================================================================
--- 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)
@@ -16,6 +16,7 @@
 from twext.python.filepath import CachingFilePath as FilePath
 from twext.web2 import responsecode
 from twext.web2.dav.util import davXMLFromStream, joinURL
+from twext.web2.http_headers import Headers, MimeType
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
 
@@ -268,7 +269,13 @@
 
             if data:
                 for filename, icaldata in data.iteritems():
-                    request = SimpleStoreRequest(self, "PUT", joinURL(calendar_uri, filename + ".ics"), authid="wsanchez")
+                    request = SimpleStoreRequest(
+                        self,
+                        "PUT",
+                        joinURL(calendar_uri, filename + ".ics"),
+                        headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+                        authid="wsanchez"
+                    )
                     request.stream = MemoryStream(icaldata)
                     yield self.send(request)
             else:
@@ -276,7 +283,13 @@
                 for child in FilePath(self.holidays_dir).children():
                     if os.path.splitext(child.basename())[1] != ".ics":
                         continue
-                    request = SimpleStoreRequest(self, "PUT", joinURL(calendar_uri, child.basename()), authid="wsanchez")
+                    request = SimpleStoreRequest(
+                        self,
+                        "PUT",
+                        joinURL(calendar_uri, child.basename()),
+                        headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+                        authid="wsanchez"
+                    )
                     request.stream = MemoryStream(child.getContent())
                     yield self.send(request)
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_props.py
===================================================================
--- 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)
@@ -88,7 +88,7 @@
                         self.fail("Expected CalDAV:supported-calendar-data element; but got none.")
 
                     for calendar in supported_calendar.children:
-                        if calendar.content_type != "text/calendar":
+                        if calendar.content_type not in ("text/calendar", "application/calendar+json"):
                             self.fail("Expected a text/calendar calendar-data type restriction")
                         if calendar.version != "2.0":
                             self.fail("Expected a version 2.0 calendar-data restriction")

Modified: CalendarServer/trunk/twistedcaldav/test/test_timezones.py
===================================================================
--- 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)
@@ -19,8 +19,8 @@
 from twistedcaldav.ical import Component
 from twistedcaldav.timezones import TimezoneCache, TimezoneException
 from twistedcaldav.timezones import readTZ, listTZs
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 import os
 import threading
@@ -49,7 +49,7 @@
         if calendar.name() != "VCALENDAR":
             self.fail("Calendar is not a VCALENDAR")
 
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
@@ -69,8 +69,8 @@
 
         self.doTest(
             "TruncatedApr01.ics",
-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True))
+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True))
         )
 
 
@@ -84,8 +84,8 @@
 
         self.doTest(
             "TruncatedDec10.ics",
-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True))
+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True))
         )
 
 
@@ -99,13 +99,13 @@
 
         self.doTest(
             "TruncatedApr01.ics",
-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True)),
+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True)),
         )
         self.doTest(
             "TruncatedDec10.ics",
-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True)),
+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True)),
             testEqual=False
         )
 
@@ -119,13 +119,13 @@
 
         self.doTest(
             "TruncatedApr01.ics",
-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True)),
+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True)),
         )
         self.doTest(
             "TruncatedDec10.ics",
-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True)),
+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True)),
         )
 
 
@@ -139,13 +139,13 @@
 
         self.doTest(
             "TruncatedDec10.ics",
-            PyCalendarDateTime(2007, 12, 10, 17, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 12, 10, 18, 0, 0, PyCalendarTimezone(utc=True))
+            DateTime(2007, 12, 10, 17, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 12, 10, 18, 0, 0, Timezone(utc=True))
         )
         self.doTest(
             "TruncatedApr01.ics",
-            PyCalendarDateTime(2007, 04, 01, 16, 0, 0, PyCalendarTimezone(utc=True)),
-            PyCalendarDateTime(2007, 04, 01, 17, 0, 0, PyCalendarTimezone(utc=True))
+            DateTime(2007, 04, 01, 16, 0, 0, Timezone(utc=True)),
+            DateTime(2007, 04, 01, 17, 0, 0, Timezone(utc=True))
         )
 
 
@@ -201,13 +201,13 @@
         calendar = Component.fromString(data)
         if calendar.name() != "VCALENDAR":
             self.fail("Calendar is not a VCALENDAR")
-        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
+        instances = calendar.expandTimeRanges(DateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
-            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)))
+            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)))
             break
 
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_upgrade.py
===================================================================
--- 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)
@@ -1675,8 +1675,8 @@
 ATTENDEE;CN=Double 'quotey' Quotes;CUTYPE=INDIVIDUAL;EMAIL=doublequotes at ex
  ample.com;PARTSTAT=ACCEPTED:urn:uuid:8E04787E-336D-41ED-A70B-D233AD0DCE6F
 ATTENDEE;CN=Cyrus Daboo;CUTYPE=INDIVIDUAL;EMAIL=cdaboo at example.com;PARTSTA
- T=ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89
- 500
+ T=ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A8
+ 9500
 CREATED:20090203T181910Z
 DESCRIPTION:This has " Bad Quotes " in it
 DTSTAMP:20090203T181924Z

Copied: CalendarServer/trunk/twistedcaldav/test/test_util.py (from rev 11912, CalendarServer/branches/users/cdaboo/json/twistedcaldav/test/test_util.py)
===================================================================
--- 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)
@@ -0,0 +1,144 @@
+##
+# 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,))

Modified: CalendarServer/trunk/twistedcaldav/timezones.py
===================================================================
--- 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)
@@ -22,7 +22,7 @@
 
 from twistedcaldav.config import config
 
-from pycalendar.timezonedb import PyCalendarTimezoneDatabase
+from pycalendar.timezonedb import TimezoneDatabase
 
 log = Logger()
 
@@ -95,7 +95,7 @@
             TimezoneCache.dirName = None
             TimezoneCache.validatePath()
         TimezoneCache.version = TimezoneCache.getTZVersion(TimezoneCache.getDBPath())
-        PyCalendarTimezoneDatabase.createTimezoneDatabase(TimezoneCache.getDBPath())
+        TimezoneDatabase.createTimezoneDatabase(TimezoneCache.getDBPath())
 
 
     @staticmethod
@@ -171,7 +171,7 @@
 
     @staticmethod
     def clear():
-        PyCalendarTimezoneDatabase.clearTimezoneDatabase()
+        TimezoneDatabase.clearTimezoneDatabase()
 
 # zoneinfo never changes in a running instance so cache all this data as we use it
 cachedTZs = {}
@@ -207,7 +207,7 @@
 
     if tzid not in cachedVTZs:
 
-        tzcal = PyCalendarTimezoneDatabase.getTimezoneInCalendar(tzid)
+        tzcal = TimezoneDatabase.getTimezoneInCalendar(tzid)
         if tzcal:
             cachedVTZs[tzid] = tzcal
         else:

Modified: CalendarServer/trunk/twistedcaldav/timezoneservice.py
===================================================================
--- 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)
@@ -46,7 +46,7 @@
 from twistedcaldav.timezones import listTZs
 from twistedcaldav.timezones import readTZ
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 class TimezoneServiceResource (ReadOnlyNoCopyResourceMixIn, DAVResourceWithoutChildrenMixin, DAVResource):
     """
@@ -66,20 +66,25 @@
         self.parent = parent
         self.cache = {}
 
+
     def deadProperties(self):
         if not hasattr(self, "_dead_properties"):
             self._dead_properties = NonePropertyStore(self)
         return self._dead_properties
 
+
     def etag(self):
         return succeed(None)
 
+
     def checkPreconditions(self, request):
         return None
 
+
     def checkPrivileges(self, request, privileges, recurse=False, principal=None, inherited_aces=None):
         return succeed(None)
 
+
     def defaultAccessControlList(self):
         return davxml.ACL(
             # DAV:Read for all principals (includes anonymous)
@@ -92,21 +97,27 @@
             ),
         )
 
+
     def contentType(self):
         return MimeType.fromString("text/xml")
 
+
     def resourceType(self):
         return davxml.ResourceType.timezones
 
+
     def isCollection(self):
         return False
 
+
     def isCalendarCollection(self):
         return False
 
+
     def isPseudoCalendarCollection(self):
         return False
 
+
     def render(self, request):
         output = """<html>
 <head>
@@ -127,10 +138,11 @@
         """
         The timezone service POST method.
         """
-        
+
         # GET and POST do the same thing
         return self.http_POST(request)
 
+
     def http_POST(self, request):
         """
         The timezone service POST method.
@@ -138,11 +150,11 @@
 
         # Check authentication and access controls
         def _gotResult(_):
-            
+
             if not request.args:
                 # Do normal GET behavior
                 return self.render(request)
-    
+
             method = request.args.get("method", ("",))
             if len(method) != 1:
                 raise HTTPError(ErrorResponse(
@@ -151,41 +163,43 @@
                     "Invalid method query parameter",
                 ))
             method = method[0]
-                
+
             action = {
                 "list"   : self.doPOSTList,
                 "get"    : self.doPOSTGet,
                 "expand" : self.doPOSTExpand,
             }.get(method, None)
-            
+
             if action is None:
                 raise HTTPError(ErrorResponse(
                     responsecode.BAD_REQUEST,
                     (calendarserver_namespace, "supported-method"),
                     "Unknown method query parameter",
                 ))
-    
+
             return action(request)
-            
+
         d = self.authorize(request, (davxml.Read(),))
         d.addCallback(_gotResult)
         return d
 
+
     def doPOSTList(self, request):
         """
         Return a list of all timezones known to the server.
         """
-        
+
         tzids = listTZs()
         tzids.sort()
         result = customxml.TZIDs(*[customxml.TZID(tzid) for tzid in tzids])
         return XMLResponse(responsecode.OK, result)
 
+
     def doPOSTGet(self, request):
         """
         Return the specified timezone data.
         """
-        
+
         tzid = request.args.get("tzid", ())
         if len(tzid) != 1:
             raise HTTPError(ErrorResponse(
@@ -209,6 +223,7 @@
         response.headers.setHeader("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
         return response
 
+
     def doPOSTExpand(self, request):
         """
         Expand a timezone within specified start/end dates.
@@ -235,7 +250,7 @@
             start = request.args.get("start", ())
             if len(start) != 1:
                 raise ValueError()
-            start = PyCalendarDateTime.parseText(start[0])
+            start = DateTime.parseText(start[0])
         except ValueError:
             raise HTTPError(ErrorResponse(
                 responsecode.BAD_REQUEST,
@@ -247,7 +262,7 @@
             end = request.args.get("end", ())
             if len(end) != 1:
                 raise ValueError()
-            end = PyCalendarDateTime.parseText(end[0])
+            end = DateTime.parseText(end[0])
             if end <= start:
                 raise ValueError()
         except ValueError:

Modified: CalendarServer/trunk/twistedcaldav/timezonestdservice.py
===================================================================
--- 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)
@@ -49,9 +49,9 @@
     addVTZ
 from twistedcaldav.xmlutil import addSubElement
 
-from pycalendar.calendar import PyCalendar
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.exceptions import PyCalendarInvalidData
+from pycalendar.icalendar.calendar import Calendar
+from pycalendar.datetime import DateTime
+from pycalendar.exceptions import InvalidData
 
 import hashlib
 import itertools
@@ -89,7 +89,13 @@
         else:
             raise ValueError("Invalid TimezoneService mode: %s" % (config.TimezoneService.Mode,))
 
+        self.formats = []
+        self.formats.append("text/calendar")
+        self.formats.append("text/plain")
+        if config.EnableJSONData:
+            self.formats.append("application/calendar+json")
 
+
     def _initPrimaryService(self):
         tzpath = TimezoneCache.getDBPath()
         xmlfile = os.path.join(tzpath, "timezones.xml")
@@ -268,7 +274,7 @@
                 {
                     "name": "get",
                     "parameters": [
-                        {"name": "format", "required": False, "multi": False, "values": ["text/calendar", "text/plain", ], },
+                        {"name": "format", "required": False, "multi": False, "values": self.formats, },
                         {"name": "tzid", "required": True, "multi": False, },
                     ],
                 },
@@ -303,7 +309,7 @@
             # Validate a date-time stamp
             changedsince = changedsince[0]
             try:
-                dt = PyCalendarDateTime.parseText(changedsince)
+                dt = DateTime.parseText(changedsince)
             except ValueError:
                 raise HTTPError(JSONResponse(
                     responsecode.BAD_REQUEST,
@@ -348,7 +354,7 @@
             ))
 
         format = request.args.get("format", ("text/calendar",))
-        if len(format) != 1 or format[0] not in ("text/calendar", "text/plain",):
+        if len(format) != 1 or format[0] not in self.formats:
             raise HTTPError(JSONResponse(
                 responsecode.BAD_REQUEST,
                 {
@@ -368,7 +374,7 @@
                 }
             ))
 
-        tzdata = calendar.getText()
+        tzdata = calendar.getText(format=format if format != "text/plain" else None)
 
         response = Response()
         response.stream = MemoryStream(tzdata)
@@ -396,9 +402,9 @@
             if len(start) > 1:
                 raise ValueError()
             elif len(start) == 1:
-                start = PyCalendarDateTime.parseText(start[0])
+                start = DateTime.parseText(start[0])
             else:
-                start = PyCalendarDateTime.getToday()
+                start = DateTime.getToday()
                 start.setDay(1)
                 start.setMonth(1)
         except ValueError:
@@ -415,9 +421,9 @@
             if len(end) > 1:
                 raise ValueError()
             elif len(end) == 1:
-                end = PyCalendarDateTime.parseText(end[0])
+                end = DateTime.parseText(end[0])
             else:
-                end = PyCalendarDateTime.getToday()
+                end = DateTime.getToday()
                 end.setDay(1)
                 end.setMonth(1)
                 end.offsetYear(10)
@@ -558,7 +564,7 @@
         Generate a PyCalendar containing the requested timezone.
         """
         # We will just use our existing TimezoneCache here
-        calendar = PyCalendar()
+        calendar = Calendar()
         try:
             vtz = readVTZ(tzid)
             calendar.addComponent(vtz.getComponents()[0].duplicate())
@@ -618,7 +624,7 @@
         Create a new DB xml file from scratch by scanning zoneinfo.
         """
 
-        self.dtstamp = PyCalendarDateTime.getNowUTC().getXMLText()
+        self.dtstamp = DateTime.getNowUTC().getXMLText()
         self._scanTZs("")
         self._dumpTZs()
 
@@ -672,7 +678,7 @@
         """
         Update existing DB info by comparing md5's.
         """
-        self.dtstamp = PyCalendarDateTime.getNowUTC().getXMLText()
+        self.dtstamp = DateTime.getNowUTC().getXMLText()
         self.changeCount = 0
         self.changed = set()
         self._scanTZs("", checkIfChanged=True)
@@ -847,8 +853,8 @@
 
         ical = response.data
         try:
-            calendar = PyCalendar.parseText(ical)
-        except PyCalendarInvalidData:
+            calendar = Calendar.parseText(ical)
+        except InvalidData:
             log.error("Invalid calendar data for tzid: %s" % (tzinfo.tzid,))
             returnValue(None)
         ical = calendar.getText()

Modified: CalendarServer/trunk/twistedcaldav/upgrade.py
===================================================================
--- 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)
@@ -1065,7 +1065,6 @@
             # Migrate mail tokens from sqlite to store
             yield migrateTokensToStore(self.config.DataRoot, self.store)
 
-            
 
     @inlineCallbacks
     def processInboxItems(self):

Modified: CalendarServer/trunk/twistedcaldav/util.py
===================================================================
--- 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)
@@ -517,3 +517,52 @@
         cuas = principal.record.calendarUserAddresses
 
         return (fullName, rec.guid, cuas)
+
+
+
+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

Modified: CalendarServer/trunk/twistedcaldav/vcard.py
===================================================================
--- 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)
@@ -31,9 +31,11 @@
 from twext.web2.stream import IStream
 from twext.web2.dav.util import allDataFromStream
 
-from pycalendar.attribute import PyCalendarAttribute
-from pycalendar.componentbase import PyCalendarComponentBase
-from pycalendar.exceptions import PyCalendarError
+from twistedcaldav.config import config
+
+from pycalendar.parameter import Parameter
+from pycalendar.componentbase import ComponentBase
+from pycalendar.exceptions import ErrorBase
 from pycalendar.vcard.card import Card
 from pycalendar.vcard.property import Property as pyProperty
 
@@ -44,6 +46,8 @@
 class InvalidVCardDataError(ValueError):
     pass
 
+
+
 class Property (object):
     """
     vCard Property
@@ -73,31 +77,55 @@
             for attrname, attrvalue in params.items():
                 if isinstance(attrvalue, unicode):
                     attrvalue = attrvalue.encode("utf-8")
-                self._pycard.addAttribute(PyCalendarAttribute(attrname, attrvalue))
+                self._pycard.addParameter(Parameter(attrname, attrvalue))
 
-    def __str__ (self): return str(self._pycard)
-    def __repr__(self): return "<%s: %r: %r>" % (self.__class__.__name__, self.name(), self.value())
 
-    def __hash__(self): return hash(str(self))
+    def __str__(self):
+        return str(self._pycard)
 
-    def __ne__(self, other): return not self.__eq__(other)
+
+    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)
+
+
     def __eq__(self, other):
-        if not isinstance(other, Property): return False
+        if not isinstance(other, Property):
+            return False
         return self._pycard == other._pycard
 
-    def __gt__(self, other): return not (self.__eq__(other) or self.__lt__(other))
+
+    def __gt__(self, other):
+        return not (self.__eq__(other) or self.__lt__(other))
+
+
     def __lt__(self, other):
         my_name = self.name()
         other_name = other.name()
 
-        if my_name < other_name: return True
-        if my_name > other_name: return False
+        if my_name < other_name:
+            return True
+        if my_name > other_name:
+            return False
 
         return self.value() < other.value()
 
-    def __ge__(self, other): return self.__eq__(other) or self.__gt__(other)
-    def __le__(self, other): return self.__eq__(other) or self.__lt__(other)
 
+    def __ge__(self, other):
+        return self.__eq__(other) or self.__gt__(other)
+
+
+    def __le__(self, other):
+        return self.__eq__(other) or self.__lt__(other)
+
+
     def duplicate(self):
         """
         Duplicate this object and all its contents.
@@ -105,35 +133,45 @@
         """
         return Property(None, None, params=None, pycard=self._pycard.duplicate())
 
-    def name  (self): return self._pycard.getName()
 
-    def value (self): return self._pycard.getValue().getValue()
+    def name(self):
+        return self._pycard.getName()
 
-    def strvalue (self): return str(self._pycard.getValue())
 
+    def value(self):
+        return self._pycard.getValue().getValue()
+
+
+    def strvalue(self):
+        return str(self._pycard.getValue())
+
+
     def setValue(self, value):
         self._pycard.setValue(value)
 
+
     def parameterNames(self):
         """
         Returns a set containing parameter names for this property.
         """
         result = set()
-        for pyattrlist in self._pycard.getAttributes().values():
+        for pyattrlist in self._pycard.getParameters().values():
             for pyattr in pyattrlist:
                 result.add(pyattr.getName())
         return result
 
+
     def parameterValue(self, name, default=None):
         """
         Returns a single value for the given parameter.  Raises
         InvalidICalendarDataError if the parameter has more than one value.
         """
         try:
-            return self._pycard.getAttributeValue(name)
+            return self._pycard.getParameterValue(name)
         except KeyError:
             return default
 
+
     def parameterValues(self, name):
         """
         Returns a single value for the given parameter.  Raises
@@ -141,7 +179,7 @@
         """
         results = []
         try:
-            attrs = self._pycard.getAttributes()[name.upper()]
+            attrs = self._pycard.getParameters()[name.upper()]
         except KeyError:
             return []
 
@@ -149,28 +187,33 @@
             results.extend(attr.getValues())
         return results
 
+
     def hasParameter(self, paramname):
-        return self._pycard.hasAttribute(paramname)
+        return self._pycard.hasParameter(paramname)
 
+
     def setParameter(self, paramname, paramvalue):
-        self._pycard.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
+        self._pycard.replaceParameter(Parameter(paramname, paramvalue))
 
+
     def removeParameter(self, paramname):
-        self._pycard.removeAttributes(paramname)
+        self._pycard.removeParameters(paramname)
 
+
     def removeAllParameters(self):
-        self._pycard.setAttributes({})
+        self._pycard.setParameters({})
 
+
     def removeParameterValue(self, paramname, paramvalue):
 
         paramname = paramname.upper()
         for attrName in self.parameterNames():
             if attrName.upper() == paramname:
-                for attr in tuple(self._pycard.getAttributes()[attrName]):
+                for attr in tuple(self._pycard.getParameters()[attrName]):
                     for value in attr.getValues():
                         if value == paramvalue:
                             if not attr.removeValue(value):
-                                self._pycard.removeAttributes(paramname)
+                                self._pycard.removeParameters(paramname)
 
 
 
@@ -178,8 +221,20 @@
     """
     X{vCard} component.
     """
+    allowedTypesList = None
+
+
     @classmethod
-    def allFromString(clazz, string):
+    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):
         """
         FIXME: Just default to reading a single VCARD - actually need more
         """
@@ -193,62 +248,85 @@
         if string[:3] == codecs.BOM_UTF8:
             string = string[3:]
 
-        return clazz.allFromStream(StringIO.StringIO(string))
+        return clazz.allFromStream(StringIO.StringIO(string), format)
 
+
     @classmethod
-    def allFromStream(clazz, stream):
+    def allFromStream(clazz, stream, format=None):
         """
         FIXME: Just default to reading a single VCARD - actually need more
         """
         try:
-            results = Card.parseMultiple(stream)
-        except PyCalendarError:
+            results = Card.parseMultipleData(stream, format)
+        except ErrorBase:
             results = None
         if not results:
             stream.seek(0)
             raise InvalidVCardDataError("%s" % (stream.read(),))
         return [clazz(None, pycard=result) for result in results]
 
+
     @classmethod
-    def fromString(clazz, string):
+    def fromString(clazz, string, format=None):
         """
         Construct a L{Component} from a string.
         @param string: a string containing vCard data.
         @return: a L{Component} representing the first component described by
             C{string}.
         """
-        if type(string) is unicode:
-            string = string.encode("utf-8")
-        else:
-            # Valid utf-8 please
-            string.decode("utf-8")
+        return clazz._fromData(string, False, format)
 
-        # No BOMs please
-        if string[:3] == codecs.BOM_UTF8:
-            string = string[3:]
 
-        return clazz.fromStream(StringIO.StringIO(string))
+    @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)
 
+
     @classmethod
-    def fromStream(clazz, stream):
+    def _fromData(clazz, data, isstream, format=None):
         """
         Construct a L{Component} from a stream.
         @param stream: a C{read()}able stream containing vCard data.
+        @param format: a C{str} indicating whether the data is vCard or jCard
         @return: a L{Component} representing the first component described by
             C{stream}.
         """
-        cal = Card()
+
+        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"
         try:
-            result = cal.parse(stream)
-        except PyCalendarError:
+            result = Card.parseData(data, format)
+        except ErrorBase, e:
+            errmsg = "%s: %s" % (e.mReason, e.mData,)
             result = None
         if not result:
-            stream.seek(0)
-            raise InvalidVCardDataError("%s" % (stream.read(),))
-        return clazz(None, pycard=cal)
+            if isstream:
+                data.seek(0)
+                data = data.read()
+            raise InvalidVCardDataError("%s\n%s" % (errmsg, data,))
+        return clazz(None, pycard=result)
 
+
     @classmethod
-    def fromIStream(clazz, stream):
+    def fromIStream(clazz, stream, format=None):
         """
         Construct a L{Component} from a stream.
         @param stream: an L{IStream} containing vCard data.
@@ -261,9 +339,11 @@
         #   A better solution would parse directly and incrementally from the
         #   request stream.
         #
-        def parse(data): return clazz.fromString(data)
+        def parse(data):
+            return clazz.fromString(data, format)
         return allDataFromStream(IStream(stream), parse)
 
+
     def __init__(self, name, **kwargs):
         """
         Use this constructor to initialize an empty L{Component}.
@@ -277,8 +357,8 @@
                 pyobj = kwargs["pycard"]
 
                 if pyobj is not None:
-                    if not isinstance(pyobj, PyCalendarComponentBase):
-                        raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
+                    if not isinstance(pyobj, ComponentBase):
+                        raise TypeError("Not a ComponentBase: %r" % (pyobj,))
 
                 self._pycard = pyobj
             else:
@@ -302,28 +382,53 @@
         else:
             raise ValueError("VCards have no child components")
 
-    def __str__ (self): return str(self._pycard)
-    def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, str(self._pycard))
 
+    def __str__(self):
+        return str(self._pycard)
+
+
+    def __repr__(self):
+        return "<%s: %r>" % (self.__class__.__name__, str(self._pycard))
+
+
     def __hash__(self):
         return hash(str(self))
 
-    def __ne__(self, other): return not self.__eq__(other)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+
     def __eq__(self, other):
         if not isinstance(other, Component):
             return False
         return self._pycard == other._pycard
 
+
+    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
+
+
     # FIXME: Should this not be in __eq__?
     def same(self, other):
         return self._pycard == other._pycard
 
+
     def name(self):
         """
-        @return: the name of the iCalendar type of this component.
+        @return: the name of the vCard type of this component.
         """
         return self._pycard.getType()
 
+
     def duplicate(self):
         """
         Duplicate this object and all its contents.
@@ -331,6 +436,7 @@
         """
         return Component(None, pycard=self._pycard.duplicate())
 
+
     def hasProperty(self, name):
         """
         @param name: the name of the property whose existence is being tested.
@@ -338,6 +444,7 @@
         """
         return self._pycard.hasProperty(name)
 
+
     def getProperty(self, name):
         """
         Get one property from the property list.
@@ -346,10 +453,13 @@
         @raise: L{ValueError} if there is more than one property of the given name.
         """
         properties = tuple(self.properties(name))
-        if len(properties) == 1: return properties[0]
-        if len(properties) > 1: raise InvalidVCardDataError("More than one %s property in component %r" % (name, self))
+        if len(properties) == 1:
+            return properties[0]
+        if len(properties) > 1:
+            raise InvalidVCardDataError("More than one %s property in component %r" % (name, self))
         return None
 
+
     def properties(self, name=None):
         """
         @param name: if given and not C{None}, restricts the returned properties
@@ -368,6 +478,7 @@
             for p in properties
         )
 
+
     def propertyValue(self, name):
         properties = tuple(self.properties(name))
         if len(properties) == 1:
@@ -385,6 +496,7 @@
         self._pycard.addProperty(property._pycard)
         self._pycard.finalise()
 
+
     def removeProperty(self, property):
         """
         Remove a property from this component.
@@ -393,6 +505,7 @@
         self._pycard.removeProperty(property._pycard)
         self._pycard.finalise()
 
+
     def removeProperties(self, name):
         """
         remove all properties with name
@@ -400,6 +513,7 @@
         """
         self._pycard.removeProperties(name)
 
+
     def replaceProperty(self, property):
         """
         Add or replace a property in this component.
@@ -410,6 +524,7 @@
         self._pycard.removeProperties(property.name())
         self.addProperty(property)
 
+
     def resourceUID(self):
         """
         @return: the UID of the subcomponents in this component.
@@ -421,6 +536,7 @@
 
         return self._resource_uid
 
+
     def resourceKind(self):
         """
         @return: the kind of the subcomponents in this component.
@@ -432,6 +548,7 @@
 
         return self._resource_kind
 
+
     def resourceMemberAddresses(self):
         """
         @return: an iterable of X-ADDRESSBOOKSERVER-MEMBER property values
@@ -440,6 +557,7 @@
 
         return [prop.value() for prop in list(self.properties("X-ADDRESSBOOKSERVER-MEMBER"))]
 
+
     def validVCardData(self, doFix=True, doRaise=True):
         """
         @return: tuple of fixed, unfixed issues
@@ -454,17 +572,19 @@
         if unfixed:
             log.debug("vCard data had unfixable problems:\n  %s" % ("\n  ".join(unfixed),))
             if doRaise:
-                raise InvalidVCardDataError("Calendar data had unfixable problems:\n  %s" % ("\n  ".join(unfixed),))
+                raise InvalidVCardDataError("Address data had unfixable problems:\n  %s" % ("\n  ".join(unfixed),))
         if fixed:
             log.debug("vCard data had fixable problems:\n  %s" % ("\n  ".join(fixed),))
 
         return fixed, unfixed
 
+
     def validForCardDAV(self):
         """
         @raise ValueError: if the given vcard data is not valid.
         """
-        if self.name() != "VCARD": raise InvalidVCardDataError("Not a vcard")
+        if self.name() != "VCARD":
+            raise InvalidVCardDataError("Not a vcard")
 
         version = self.propertyValue("VERSION")
         if version != "3.0":

Modified: CalendarServer/trunk/twistedcaldav/xmlutil.py
===================================================================
--- 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)
@@ -24,17 +24,21 @@
 except ImportError:
     from xml.parsers.expat import ExpatError as XMLParseError
 
+
+
 # Utilities for working with ElementTree
 
 def readXMLString(xmldata, expectedRootTag=None):
     io = StringIO.StringIO(xmldata)
     return readXML(io, expectedRootTag)
 
+
+
 def readXML(xmlfile, expectedRootTag=None):
     """
     Read in XML data from a file and parse into ElementTree. Optionally verify
     the root node is what we expect.
-    
+
     @param xmlfile: file to read from
     @type xmlfile: C{File}
     @param expectedRootTag: root tag (qname) to test or C{None}
@@ -52,14 +56,18 @@
         root = etree.getroot()
         if root.tag != expectedRootTag:
             raise ValueError("Ignoring file '%s' because it is not a %s file" % (xmlfile, expectedRootTag,))
-    
+
     return etree, etree.getroot()
 
+
+
 def elementToXML(element):
     return XML.tostring(element, "utf-8")
 
+
+
 def writeXML(xmlfile, root):
-    
+
     data = """<?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE %s SYSTEM "%s.dtd">
 
@@ -69,7 +77,7 @@
 
     # Generate indentation
     def _indentNode(node, level=0):
-        
+
         if node.text is not None and node.text.strip():
             return
         elif len(node):
@@ -87,27 +95,35 @@
     with open(xmlfile, "w") as f:
         f.write(data)
 
+
+
 def newElementTreeWithRoot(roottag):
 
     root = createElement(roottag)
     etree = XML.ElementTree(root)
-    
+
     return etree, root
 
+
+
 def createElement(tag, text=None, **attrs):
 
     child = XML.Element(tag, attrs)
     child.text = text
     return child
 
+
+
 def addSubElement(parent, tag, text=None):
 
     child = XML.SubElement(parent, tag)
     child.text = text
     return child
 
+
+
 def changeSubElementText(parent, tag, text):
-    
+
     child = parent.find(tag)
     if child is not None:
         child.text = text

Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py
===================================================================
--- 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)
@@ -41,8 +41,8 @@
 from twext.web2.dav.resource import TwistedGETContentMD5
 from twext.web2.http_headers import generateContentType, MimeType
 
-from twistedcaldav import caldavxml, customxml
-from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque
+from twistedcaldav import caldavxml, customxml, ical
+from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque, Transparent
 from twistedcaldav.config import config
 from twistedcaldav.ical import InvalidICalendarDataError
 
@@ -84,6 +84,14 @@
     _topPath = "calendars"
     _notifierPrefix = "CalDAV"
 
+    _componentCalendarName = {
+        "VEVENT": "calendar",
+        "VTODO": "tasks",
+        "VJOURNAL": "journals",
+        "VAVAILABILITY": "available",
+        "VPOLL": "polls",
+    }
+
     def __init__(self, uid, path, calendarStore, transaction):
         super(CalendarHome, self).__init__(uid, path, calendarStore, transaction)
 
@@ -177,20 +185,19 @@
 
     def createdHome(self):
 
-        # Default calendar
-        defaultCal = self.createCalendarWithName("calendar")
-        props = defaultCal.properties()
-        props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Opaque())
-
         # Check whether components type must be separate
         if config.RestrictCalendarsToOneComponentType:
-            defaultCal.setSupportedComponents("VEVENT")
+            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")
 
-            # Default tasks
-            defaultTasks = self.createCalendarWithName("tasks")
-            props = defaultTasks.properties()
-            defaultTasks.setSupportedComponents("VTODO")
-
         self.createCalendarWithName("inbox")
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/index_file.py
===================================================================
--- 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)
@@ -55,9 +55,9 @@
 from twistedcaldav.config import config
 from twistedcaldav.memcachepool import CachePoolUserMixIn
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
 
 log = Logger()
 
@@ -341,7 +341,7 @@
                     maxDate = maxDate.duplicate()
                     maxDate.setDateOnly(True)
                     if isStartDate:
-                        maxDate += PyCalendarDuration(days=365)
+                        maxDate += Duration(days=365)
                     self.testAndUpdateIndex(maxDate)
             else:
                 # We cannot handle this filter in an indexed search
@@ -671,7 +671,7 @@
         if master is None or not calendar.isRecurring():
             # When there is no master we have a set of overridden components - index them all.
             # When there is one instance - index it.
-            expand = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            expand = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
             doInstanceIndexing = True
         else:
             # If migrating or re-creating or config option for delayed indexing is off, always index
@@ -682,8 +682,8 @@
             # by default.  This is a caching parameter which affects the size of the index;
             # it does not affect search results beyond this period, but it may affect
             # performance of such a search.
-            expand = (PyCalendarDateTime.getToday() +
-                      PyCalendarDuration(days=config.FreeBusyIndexExpandAheadDays))
+            expand = (DateTime.getToday() +
+                      Duration(days=config.FreeBusyIndexExpandAheadDays))
 
             if expand_until and expand_until > expand:
                 expand = expand_until
@@ -700,8 +700,8 @@
             # occurrences into some obscenely far-in-the-future date, so we cap the caching
             # period.  Searches beyond this period will always be relatively expensive for
             # resources with occurrences beyond this period.
-            if expand > (PyCalendarDateTime.getToday() +
-                         PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
+            if expand > (DateTime.getToday() +
+                         Duration(days=config.FreeBusyIndexExpandMaxDays)):
                 raise IndexedSearchException()
 
         # Always do recurrence expansion even if we do not intend to index - we need this to double-check the
@@ -716,7 +716,7 @@
         # Now coerce indexing to off if needed
         if not doInstanceIndexing:
             instances = None
-            recurrenceLimit = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            recurrenceLimit = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
 
         self._delete_from_db(name, uid, False)
 
@@ -782,8 +782,8 @@
             # Special - for unbounded recurrence we insert a value for "infinity"
             # that will allow an open-ended time-range to always match it.
             if calendar.isRecurringUnbounded():
-                start = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-                end = PyCalendarDateTime(2100, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
+                start = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+                end = DateTime(2100, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
                 float = 'N'
                 self._db_execute(
                     """

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py
===================================================================
--- 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)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twext.python.clsprop import classproperty
 
@@ -45,7 +45,7 @@
         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
         yield self.populate()
 
-        self.now = PyCalendarDateTime.getNowUTC()
+        self.now = DateTime.getNowUTC()
         self.now.setHHMMSS(0, 0, 0)
 
         self.now_12H = self.now.duplicate()
@@ -170,9 +170,9 @@
         scheduler = CalDAVScheduler(self.transactionUnderTest(), "user01")
         result = (yield scheduler.doSchedulingViaPOST("mailto:user01 at example.com", ["mailto:user01 at example.com", ], Component.fromString(data_request)))
         self.assertEqual(len(result.responses), 1)
-        self.assertEqual(str(result.responses[0].children[0].children[0]), "mailto:user01 at 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"))
+        self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01 at 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"))
 
 
     @inlineCallbacks
@@ -227,9 +227,9 @@
         scheduler = CalDAVScheduler(self.transactionUnderTest(), "user01")
         result = (yield scheduler.doSchedulingViaPOST("mailto:user01 at example.com", ["mailto:user01 at example.com", ], Component.fromString(data_request)))
         self.assertEqual(len(result.responses), 1)
-        self.assertEqual(str(result.responses[0].children[0].children[0]), "mailto:user01 at 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"))
+        self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01 at 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"))
 
 
     @inlineCallbacks
@@ -294,6 +294,6 @@
         scheduler = CalDAVScheduler(self.transactionUnderTest(), "user01")
         result = (yield scheduler.doSchedulingViaPOST("mailto:user01 at example.com", ["mailto:user01 at example.com", ], Component.fromString(data_request)))
         self.assertEqual(len(result.responses), 1)
-        self.assertEqual(str(result.responses[0].children[0].children[0]), "mailto:user01 at 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"))
+        self.assertEqual(str(result.responses[0].recipient.children[0]), "mailto:user01 at 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"))

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/freebusy.py
===================================================================
--- 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)
@@ -14,10 +14,10 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.period import Period
+from pycalendar.timezone import Timezone
 
 from twext.python.log import Logger
 
@@ -68,8 +68,8 @@
         if entry:
 
             # Offset one day at either end to account for floating
-            cached_start = entry.timerange.start + PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
-            cached_end = entry.timerange.end - PyCalendarDuration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_start = entry.timerange.start + Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
+            cached_end = entry.timerange.end - Duration(days=FBCacheEntry.CACHE_DAYS_FLOATING_ADJUST)
 
             # Verify that the requested time range lies within the cache time range
             if compareDateTime(timerange.end, cached_end) <= 0 and compareDateTime(timerange.start, cached_start) >= 0:
@@ -187,8 +187,8 @@
                 logItems["fb-uncached"] = logItems.get("fb-uncached", 0) + 1
 
             # We want to cache a large range of time based on the current date
-            cache_start = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=0 - config.FreeBusyCacheDaysBack))
-            cache_end = normalizeToUTC(PyCalendarDateTime.getToday() + PyCalendarDuration(days=config.FreeBusyCacheDaysForward))
+            cache_start = normalizeToUTC(DateTime.getToday() + Duration(days=0 - config.FreeBusyCacheDaysBack))
+            cache_end = normalizeToUTC(DateTime.getToday() + Duration(days=config.FreeBusyCacheDaysForward))
 
             # If the requested time range would fit in our allowed cache range, trigger the cache creation
             if compareDateTime(timerange.start, cache_start) >= 0 and compareDateTime(timerange.end, cache_end) <= 0:
@@ -227,7 +227,7 @@
             logItems["fb-cached"] = logItems.get("fb-cached", 0) + 1
 
         # Determine appropriate timezone (UTC is the default)
-        tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
+        tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
 
     # We care about separate instances for VEVENTs only
     aggregated_resources = {}
@@ -270,15 +270,15 @@
                 if float == 'Y':
                     fbstart.setTimezone(tzinfo)
                 else:
-                    fbstart.setTimezone(PyCalendarTimezone(utc=True))
+                    fbstart.setTimezone(Timezone(utc=True))
                 fbend = parseSQLTimestampToPyCalendar(end)
                 if float == 'Y':
                     fbend.setTimezone(tzinfo)
                 else:
-                    fbend.setTimezone(PyCalendarTimezone(utc=True))
+                    fbend.setTimezone(Timezone(utc=True))
 
                 # Clip instance to time range
-                clipped = clipPeriod(PyCalendarPeriod(fbstart, duration=fbend - fbstart), PyCalendarPeriod(timerange.start, timerange.end))
+                clipped = clipPeriod(Period(fbstart, duration=fbend - fbstart), Period(timerange.start, timerange.end))
 
                 # Double check for overlap
                 if clipped:
@@ -364,7 +364,7 @@
     @param timerange: the time-range in which to expand
     @type timerange: L{TimeRange}
     @param tzinfo: timezone for floating time calculations
-    @type tzinfo: L{PyCalendarTimezone}
+    @type tzinfo: L{Timezone}
     """
 
     # First expand the component
@@ -404,7 +404,7 @@
     @param calendar: the L{Component} that is the VCALENDAR containing the VEVENT's.
     @param fbinfo: the tuple used to store the three types of fb data.
     @param timerange: the time range to restrict free busy data to.
-    @param tzinfo: the L{PyCalendarTimezone} for the timezone to use for floating/all-day events.
+    @param tzinfo: the L{Timezone} for the timezone to use for floating/all-day events.
     """
 
     # Expand out the set of instances for the event with in the required range
@@ -449,10 +449,10 @@
         # Clip period for this instance - use duration for period end if that
         # is what original component used
         if instance.component.hasProperty("DURATION"):
-            period = PyCalendarPeriod(fbstart, duration=fbend - fbstart)
+            period = Period(fbstart, duration=fbend - fbstart)
         else:
-            period = PyCalendarPeriod(fbstart, fbend)
-        clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+            period = Period(fbstart, fbend)
+        clipped = clipPeriod(period, Period(timerange.start, timerange.end))
 
         # Double check for overlap
         if clipped:
@@ -490,7 +490,7 @@
             assert isinstance(fb.value(), list), "FREEBUSY property does not contain a list of values: %r" % (fb,)
             for period in fb.value():
                 # Clip period for this instance
-                clipped = clipPeriod(period.getValue(), PyCalendarPeriod(timerange.start, timerange.end))
+                clipped = clipPeriod(period.getValue(), Period(timerange.start, timerange.end))
                 if clipped:
                     fbinfo[fbtype_mapper.get(fbtype, 0)].append(clipped)
 
@@ -509,12 +509,12 @@
         # Get overall start/end
         start = vav.getStartDateUTC()
         if start is None:
-            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            start = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         end = vav.getEndDateUTC()
         if end is None:
-            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-        period = PyCalendarPeriod(start, end)
-        overall = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+            end = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+        period = Period(start, end)
+        overall = clipPeriod(period, Period(timerange.start, timerange.end))
         if overall is None:
             continue
 
@@ -526,10 +526,10 @@
         last_end = timerange.start
         for period in periods:
             if last_end < period.getStart():
-                busyperiods.append(PyCalendarPeriod(last_end, period.getStart()))
+                busyperiods.append(Period(last_end, period.getStart()))
             last_end = period.getEnd()
         if last_end < timerange.end:
-            busyperiods.append(PyCalendarPeriod(last_end, timerange.end))
+            busyperiods.append(Period(last_end, timerange.end))
 
         # Add to actual results mapped by busy type
         fbtype = vav.propertyValue("BUSYTYPE")
@@ -576,10 +576,10 @@
             # Clip period for this instance - use duration for period end if that
             # is what original component used
             if instance.component.hasProperty("DURATION"):
-                period = PyCalendarPeriod(start, duration=end - start)
+                period = Period(start, duration=end - start)
             else:
-                period = PyCalendarPeriod(start, end)
-            clipped = clipPeriod(period, PyCalendarPeriod(timerange.start, timerange.end))
+                period = Period(start, end)
+            clipped = clipPeriod(period, Period(timerange.start, timerange.end))
             if clipped:
                 periods.append(clipped)
 
@@ -622,7 +622,7 @@
         fb.addProperty(attendee)
     fb.addProperty(Property("DTSTART", timerange.start))
     fb.addProperty(Property("DTEND", timerange.end))
-    fb.addProperty(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+    fb.addProperty(Property("DTSTAMP", DateTime.getNowUTC()))
     if len(fbinfo[0]) != 0:
         fb.addProperty(Property("FREEBUSY", fbinfo[0], {"FBTYPE": "BUSY"}))
     if len(fbinfo[1]) != 0:

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py
===================================================================
--- 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)
@@ -16,8 +16,8 @@
 
 from difflib import unified_diff
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.period import PyCalendarPeriod
+from pycalendar.datetime import DateTime
+from pycalendar.period import Period
 
 from twext.python.log import Logger
 
@@ -484,7 +484,7 @@
 
             # If PARTSTAT was changed by the attendee, add a timestamp if needed
             if config.Scheduling.Options.TimestampAttendeePartStatChanges:
-                serverAttendee.setParameter("X-CALENDARSERVER-DTSTAMP", PyCalendarDateTime.getNowUTC().getText())
+                serverAttendee.setParameter("X-CALENDARSERVER-DTSTAMP", DateTime.getNowUTC().getText())
 
             replyNeeded = True
 
@@ -516,6 +516,10 @@
             if comp.name() == "VALARM":
                 serverComponent.addComponent(comp)
 
+        # VPOLL
+        if serverComponent.name() == "VPOLL":
+            replyNeeded = self._transferVPOLLData(serverComponent, clientComponent)
+
         return True, replyNeeded
 
 
@@ -556,6 +560,44 @@
             return True
 
 
+    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
+
+
     def _checkInvalidChanges(self, serverComponent, clientComponent, declines):
 
         # Properties we care about: DTSTART, DTEND, DURATION, RRULE, RDATE, EXDATE
@@ -585,12 +627,12 @@
     def _getNormalizedDateTimeProperties(self, component):
 
         # Basic time properties
-        if component.name() in ("VEVENT", "VJOURNAL",):
+        if component.name() in ("VEVENT", "VJOURNAL", "VPOLL"):
             dtstart = component.getProperty("DTSTART")
             dtend = component.getProperty("DTEND")
             duration = component.getProperty("DURATION")
 
-            timeRange = PyCalendarPeriod(
+            timeRange = Period(
                 start=dtstart.value()  if dtstart  is not None else None,
                 end=dtend.value()    if dtend    is not None else None,
                 duration=duration.value() if duration is not None else None,
@@ -602,16 +644,19 @@
             duration = component.getProperty("DURATION")
 
             if dtstart or duration:
-                timeRange = PyCalendarPeriod(
+                timeRange = Period(
                     start=dtstart.value()  if dtstart  is not None else None,
                     duration=duration.value() if duration is not None else None,
                 )
             else:
-                timeRange = PyCalendarPeriod()
+                timeRange = Period()
 
             newdue = component.getProperty("DUE")
             if newdue is not None:
                 newdue = newdue.value().duplicate().adjustToUTC()
+        else:
+            timeRange = Period()
+            newdue = None
 
         # Recurrence rules - we need to normalize the order of the value parts
         newrrules = set()
@@ -627,7 +672,7 @@
         rdates = component.properties("RDATE")
         for rdate in rdates:
             for value in rdate.value():
-                if isinstance(value, PyCalendarDateTime):
+                if isinstance(value, DateTime):
                     value = value.duplicate().adjustToUTC()
                 newrdates.add(value)
 
@@ -734,6 +779,7 @@
         comp.normalizePropertyValueLists("EXDATE")
         comp.removePropertyParameters("ORGANIZER", ("SCHEDULE-STATUS",))
         comp.removePropertyParameters("ATTENDEE", ("SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
+        comp.removePropertyParameters("VOTER", ("SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
         comp.removeAlarms()
         comp.normalizeAll()
         comp.normalizeAttachments()

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/icalsplitter.py
===================================================================
--- 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)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twistedcaldav.ical import Property
 
@@ -34,10 +34,10 @@
 
         """
         self.threshold = threshold
-        self.past = PyCalendarDateTime.getNowUTC()
+        self.past = DateTime.getNowUTC()
         self.past.setHHMMSS(0, 0, 0)
         self.past.offsetDay(-past)
-        self.now = PyCalendarDateTime.getNowUTC()
+        self.now = DateTime.getNowUTC()
         self.now.setHHMMSS(0, 0, 0)
         self.now.offsetDay(-1)
 
@@ -91,7 +91,7 @@
         @type ical: L{Component}
 
         @return: recurrence-id of the split
-        @rtype: L{PyCalendarDateTime}
+        @rtype: L{DateTime}
         """
 
         # Find the instance RECURRENCE-ID where a split is going to happen
@@ -124,7 +124,7 @@
         @type ical: L{Component}
 
         @param rid: recurrence-id where the split should occur, or C{None} to determine it here
-        @type rid: L{PyCalendarDateTime} or C{None}
+        @type rid: L{DateTime} or C{None}
 
         @param olderUID: UID to use for the split off component, or C{None} to generate one here
         @type olderUID: C{str} or C{None}

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/outbound.py
===================================================================
--- 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)
@@ -26,8 +26,8 @@
 from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
 import email.utils
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
 from twext.enterprise.dal.record import fromTable
 from twext.enterprise.queue import WorkItem
 from twext.python.log import Logger
@@ -320,8 +320,8 @@
         """
 
         if onlyAfter is None:
-            duration = PyCalendarDuration(days=self.suppressionDays)
-            onlyAfter = PyCalendarDateTime.getNowUTC() - duration
+            duration = Duration(days=self.suppressionDays)
+            onlyAfter = DateTime.getNowUTC() - duration
 
         icaluid = calendar.resourceUID()
         method = calendar.propertyValue("METHOD")

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
===================================================================
--- 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)
@@ -64,7 +64,7 @@
         yield delivery.generateSchedulingResponses()
 
         self.assertEqual(len(responses.responses), 1)
-        self.assertEqual(str(responses.responses[0].children[1]), iTIPRequestStatus.SERVICE_UNAVAILABLE)
+        self.assertEqual(str(responses.responses[0].reqstatus), iTIPRequestStatus.SERVICE_UNAVAILABLE)
 
 
     @inlineCallbacks

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py
===================================================================
--- 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)
@@ -300,7 +300,7 @@
         yield txn.commit()
         self.assertEquals(
             "1.2;Scheduling message has been delivered",
-            result.responses[0].children[1].toString()
+            result.responses[0].reqstatus.toString()
         )
 
 
@@ -333,7 +333,7 @@
         yield txn.commit()
         self.assertEquals(
             "3.7;Invalid Calendar User",
-            result.responses[0].children[1].toString()
+            result.responses[0].reqstatus.toString()
         )
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
===================================================================
--- 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)
@@ -17,7 +17,7 @@
 
 from cStringIO import StringIO
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twisted.internet.defer import inlineCallbacks, succeed
 from twisted.trial import unittest
@@ -275,7 +275,7 @@
                 inputOriginator,
                 inputRecipient,
                 Component.fromString(inputCalendar.replace("\n", "\r\n")),
-                onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0)
+                onlyAfter=DateTime(2010, 1, 1, 0, 0, 0)
             )
             yield txn.commit()
 
@@ -319,7 +319,7 @@
                 inputOriginator,
                 inputRecipient,
                 Component.fromString(inputCalendar.replace("\n", "\r\n")),
-                onlyAfter=PyCalendarDateTime(2021, 1, 1, 0, 0, 0)
+                onlyAfter=DateTime(2021, 1, 1, 0, 0, 0)
             )
             yield txn.commit()
             self.assertFalse(self.sender.smtpSender.sendMessageCalled)
@@ -381,7 +381,7 @@
         txn = self.store.newTransaction()
         yield self.sender.outbound(txn, inputOriginator, inputRecipient,
             Component.fromString(inputCalendar.replace("\n", "\r\n")),
-            onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0))
+            onlyAfter=DateTime(2010, 1, 1, 0, 0, 0))
 
         # Verify we didn't create a new token...
         txn = self.store.newTransaction()

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/implicit.py
===================================================================
--- 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)
@@ -21,7 +21,6 @@
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError
 
-from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config
 from twistedcaldav.ical import Property
@@ -1047,17 +1046,17 @@
 
         # Map each recipient in the response to a status code
         responses = {}
+        propname = self.calendar.mainComponent().recipientPropertyName() if is_organizer else "ORGANIZER"
         for item in response.responses:
-            assert isinstance(item, caldavxml.Response), "Wrong element in response"
-            recipient = str(item.children[0].children[0])
-            status = str(item.children[1])
+            recipient = str(item.recipient.children[0])
+            status = str(item.reqstatus)
             responses[recipient] = status
 
             # Now apply to each ATTENDEE/ORGANIZER in the original data
             self.calendar.setParameterToValueForPropertyWithValue(
                 "SCHEDULE-STATUS",
                 status.split(";")[0],
-                "ATTENDEE" if is_organizer else "ORGANIZER",
+                propname,
                 recipient)
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/resource.py
===================================================================
--- 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)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twext.web2 import responsecode
 from twext.web2.dav.http import ErrorResponse
@@ -158,12 +158,26 @@
         """
 
         # Determine min/max date-time for iSchedule
-        now = PyCalendarDateTime.getNowUTC()
-        minDateTime = PyCalendarDateTime(now.getYear(), 1, 1, 0, 0, 0, PyCalendarTimezone(utc=True))
+        now = DateTime.getNowUTC()
+        minDateTime = DateTime(now.getYear(), 1, 1, 0, 0, 0, Timezone(utc=True))
         minDateTime.offsetYear(-1)
-        maxDateTime = PyCalendarDateTime(now.getYear(), 1, 1, 0, 0, 0, PyCalendarTimezone(utc=True))
+        maxDateTime = DateTime(now.getYear(), 1, 1, 0, 0, 0, Timezone(utc=True))
         maxDateTime.offsetYear(10)
 
+        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",
+                })
+            )
         result = ischedulexml.QueryResult(
 
             ischedulexml.Capabilities(
@@ -189,12 +203,7 @@
                         name="VFREEBUSY"
                     ),
                 ),
-                ischedulexml.CalendarDataTypes(
-                    ischedulexml.CalendarDataType(**{
-                            "content-type": "text/calendar",
-                            "version": "2.0",
-                    }),
-                ),
+                ischedulexml.CalendarDataTypes(*dataTypes),
                 ischedulexml.Attachments(
                     ischedulexml.External(),
                 ),
@@ -223,25 +232,49 @@
         # This is a server-to-server scheduling operation.
         scheduler = IScheduleScheduler(txn, None, podding=self._podding)
 
+        # 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,
+            ))
+
         originator = self.loadOriginatorFromRequestHeaders(request)
         recipients = self.loadRecipientsFromRequestHeaders(request)
         body = (yield allDataFromStream(request.stream))
+        calendar = Component.fromString(body, format=format)
 
         # Do the POST processing treating this as a non-local schedule
         try:
-            result = (yield scheduler.doSchedulingViaPOST(request.remoteAddr, request.headers, body, originator, recipients))
+            result = (yield scheduler.doSchedulingViaPOST(request.remoteAddr, request.headers, body, calendar, originator, recipients))
         except Exception:
             ex = Failure()
             yield txn.abort()
             ex.raiseException()
         else:
             yield txn.commit()
-        response = result.response()
+        response = result.response(format=format)
         if not self._podding:
             response.headers.addRawHeader(ISCHEDULE_CAPABILITIES, str(config.Scheduling.iSchedule.SerialNumber))
         returnValue(response)
 
 
+    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
+
+
     def loadOriginatorFromRequestHeaders(self, request):
         # Must have Originator header
         originator = request.headers.getRawHeaders("originator")

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
===================================================================
--- 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)
@@ -23,7 +23,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twistedcaldav.config import config
-from twistedcaldav.ical import normalizeCUAddress, Component
+from twistedcaldav.ical import normalizeCUAddress
 
 from txdav.caldav.datastore.scheduling import addressmapping
 from txdav.caldav.datastore.scheduling.cuaddress import RemoteCalendarUser
@@ -147,7 +147,7 @@
 
 
     @inlineCallbacks
-    def doSchedulingViaPOST(self, remoteAddr, headers, body, originator, recipients):
+    def doSchedulingViaPOST(self, remoteAddr, headers, body, calendar, originator, recipients):
         """
         Carry out iSchedule specific processing.
         """
@@ -180,8 +180,6 @@
                     msg,
                 ))
 
-        calendar = Component.fromString(body)
-
         if self._podding and self.headers.getRawHeaders('x-calendarserver-itip-refreshonly', ("F"))[0] == "T":
             self.txn.doing_attendee_refresh = 1
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
===================================================================
--- 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)
@@ -94,6 +94,7 @@
             headers=http_headers.Headers(rawHeaders={
                 "Originator": ("mailto:wsanchez at example.com",),
                 "Recipient": ("mailto:cdaboo at example.com",),
+                "Content-Type": "text/calendar",
             }),
             content="""BEGIN:VCALENDAR
 CALSCALE:GREGORIAN
@@ -144,6 +145,7 @@
             headers=http_headers.Headers(rawHeaders={
                 "Originator": ("mailto:user01 at example.org",),
                 "Recipient": ("mailto:user02 at example.com",),
+                "Content-Type": ("text/calendar",)
             }),
             content="""BEGIN:VCALENDAR
 CALSCALE:GREGORIAN

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/itip.py
===================================================================
--- 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)
@@ -33,7 +33,7 @@
 from twistedcaldav.ical import Property, iCalendarProductID, Component, \
     ignoredComponents
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 log = Logger()
 
@@ -402,9 +402,14 @@
     @staticmethod
     def updateAttendeeData(from_component, to_component):
         """
+        Called when processing a REPLY only.
+
         Copy the PARTSTAT of the Attendee in the from_component to the matching ATTENDEE
         in the to_component. Ignore if no match found. Also update the private comments.
 
+        For VPOLL we need to copy POLL-ITEM-ID response values into the actual matching
+        polled sub-components as VOTER properties.
+
         @param from_component: component to copy from
         @type from_component: L{Component}
         @param to_component: component to copy to
@@ -423,7 +428,7 @@
             reqstatus = "2.0"
 
         # Get attendee in from_component - there MUST be only one
-        attendees = tuple(from_component.properties("ATTENDEE"))
+        attendees = tuple(from_component.properties(from_component.recipientPropertyName()))
         if len(attendees) != 1:
             log.error("There must be one and only one ATTENDEE property in a REPLY\n%s" % (str(from_component),))
             return None, False, False
@@ -484,7 +489,7 @@
                     attendee_comment.value(),
                     params={
                         "X-CALENDARSERVER-ATTENDEE-REF": attendee.value(),
-                        "X-CALENDARSERVER-DTSTAMP": PyCalendarDateTime.getNowUTC().getText(),
+                        "X-CALENDARSERVER-DTSTAMP": DateTime.getNowUTC().getText(),
                     }
                 )
                 to_component.addProperty(private_comment)
@@ -499,17 +504,60 @@
 
                     # Add default parameters
                     private_comment.setParameter("X-CALENDARSERVER-ATTENDEE-REF", attendee.value())
-                    private_comment.setParameter("X-CALENDARSERVER-DTSTAMP", PyCalendarDateTime.getNowUTC().getText())
+                    private_comment.setParameter("X-CALENDARSERVER-DTSTAMP", DateTime.getNowUTC().getText())
 
                     # Set new value
                     private_comment.setValue(attendee_comment.value())
 
                     private_comment_changed = True
 
+            # Do VPOLL transfer
+            if from_component.name() == "VPOLL":
+                # TODO: figure out how to report changes back
+                iTipProcessing.updateVPOLLData(from_component, to_component, attendee)
+
         return attendee.value(), partstat_changed, private_comment_changed
 
 
     @staticmethod
+    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
     def transferItems(from_calendar, to_component, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, other_props, recipient, remove_matched=False):
         """
         Transfer properties from a calendar to a component by first trying to match the component in the original calendar and
@@ -847,7 +895,7 @@
         itip.filterComponents(changedRids)
 
         # Force update to DTSTAMP everywhere so reply sequencing will work
-        itip.replacePropertyInAllComponents(Property("DTSTAMP", PyCalendarDateTime.getNowUTC()))
+        itip.replacePropertyInAllComponents(Property("DTSTAMP", DateTime.getNowUTC()))
 
         # Remove all attendees except the one we want
         itip.removeAllButOneAttendee(attendee)
@@ -877,6 +925,7 @@
             "EXDATE",
             "ORGANIZER",
             "ATTENDEE",
+            "VOTER",
             "X-CALENDARSERVER-PRIVATE-COMMENT",
             "SUMMARY",
             "LOCATION",
@@ -896,10 +945,38 @@
         # Strip out unwanted bits
         iTipGenerator.prepareSchedulingMessage(itip, reply=True)
 
+        # Handle VPOLL behavior
+        for component in itip.subcomponents():
+            if component.name() == "VPOLL":
+                iTipGenerator.generateVPOLLReply(component, attendee)
+
         return itip
 
 
     @staticmethod
+    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
     def prepareSchedulingMessage(itip, reply=False):
         """
         Remove properties and parameters that should not be sent in an iTIP message
@@ -925,6 +1002,7 @@
 
         # Property Parameters
         itip.removePropertyParameters("ATTENDEE", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND", "X-CALENDARSERVER-DTSTAMP",))
+        itip.removePropertyParameters("VOTER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND", "X-CALENDARSERVER-DTSTAMP",))
         itip.removePropertyParameters("ORGANIZER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- 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)
@@ -14,9 +14,9 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
 
 from twext.python.log import Logger
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
@@ -785,13 +785,13 @@
         cuas = self.recipient.principal.calendarUserAddresses
 
         # First expand current one to get instances (only go 1 year into the future)
-        default_future_expansion_duration = PyCalendarDuration(days=config.Scheduling.Options.AutoSchedule.FutureFreeBusyDays)
-        expand_max = PyCalendarDateTime.getToday() + default_future_expansion_duration
+        default_future_expansion_duration = Duration(days=config.Scheduling.Options.AutoSchedule.FutureFreeBusyDays)
+        expand_max = DateTime.getToday() + default_future_expansion_duration
         instances = calendar.expandTimeRanges(expand_max, ignoreInvalidInstances=True)
 
         # We are going to ignore auto-accept processing for anything more than a day old (actually use -2 days
         # to add some slop to account for possible timezone offsets)
-        min_date = PyCalendarDateTime.getToday()
+        min_date = DateTime.getToday()
         min_date.offsetDay(-2)
         allOld = True
 
@@ -824,7 +824,7 @@
             # Get the timezone property from the collection, and store in the query filter
             # for use during the query itself.
             tz = testcal.getTimezone()
-            tzinfo = tz.gettimezone() if tz is not None else PyCalendarTimezone(utc=True)
+            tzinfo = tz.gettimezone() if tz is not None else Timezone(utc=True)
 
             # Now do search for overlapping time-range and set instance.free based
             # on whether there is an overlap or not

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/scheduler.py
===================================================================
--- 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)
@@ -41,7 +41,9 @@
 from txdav.caldav.datastore.scheduling.imip.delivery import ScheduleViaIMip
 from txdav.caldav.datastore.scheduling.ischedule.delivery import ScheduleViaISchedule
 from txdav.caldav.datastore.scheduling.itip import iTIPRequestStatus
+
 import hashlib
+from collections import namedtuple
 
 """
 CalDAV/Server-to-Server scheduling behavior.
@@ -654,6 +656,11 @@
     response_description_element = davxml.ResponseDescription
     calendar_data_element = caldavxml.CalendarData
 
+    ScheduleResonseDetails = namedtuple(
+        "ScheduleResonseDetails",
+        ["recipient", "reqstatus", "calendar", "error", "message", ]
+    )
+
     def __init__(self, method, success_response, recipient_mapper=None):
         """
         @param method: the name of the method generating the queue.
@@ -703,16 +710,14 @@
         if not suppressErrorLog and code > 400: # Error codes only
             self.log.error("Error during %s for %s: %s" % (self.method, recipient, message))
 
-        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))
+        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)
 
 
     def errorForFailure(self, failure):
@@ -728,19 +733,17 @@
         @param clone: the response to clone.
         """
 
-        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))
+        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)
 
 
-    def response(self):
+    def response(self, format=None):
         """
         Generate a L{ScheduleResponseResponse} with the responses contained in the
         queue or, if no such responses, return the C{success_response} provided
@@ -748,6 +751,20 @@
         @return: the response.
         """
         if self.responses:
-            return ScheduleResponseResponse(self.schedule_response_element, self.responses, self.location)
+            # 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)
         else:
             return self.success_response

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_freebusy.py
===================================================================
--- 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)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.period import PyCalendarPeriod
+from pycalendar.datetime import DateTime
+from pycalendar.period import Period
 
 from twext.python.clsprop import classproperty
 
@@ -94,7 +94,7 @@
             (
                 "#1.3 With single busy time",
                 [
-                    [PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"), ],
+                    [Period.parseText("20080601T120000Z/20080601T130000Z"), ],
                     [],
                     [],
                 ],
@@ -120,8 +120,8 @@
                 "#1.4 With multiple busy time",
                 [
                     [
-                        PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
-                        PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
+                        Period.parseText("20080601T120000Z/20080601T130000Z"),
+                        Period.parseText("20080601T140000Z/20080601T150000Z"),
                     ],
                     [],
                     [],
@@ -148,10 +148,10 @@
                 "#1.5 With multiple busy time, some overlap",
                 [
                     [
-                        PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
-                        PyCalendarPeriod.parseText("20080601T123000Z/20080601T133000Z"),
-                        PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
-                        PyCalendarPeriod.parseText("20080601T150000Z/20080601T160000Z"),
+                        Period.parseText("20080601T120000Z/20080601T130000Z"),
+                        Period.parseText("20080601T123000Z/20080601T133000Z"),
+                        Period.parseText("20080601T140000Z/20080601T150000Z"),
+                        Period.parseText("20080601T150000Z/20080601T160000Z"),
                     ],
                     [],
                     [],
@@ -178,14 +178,14 @@
                 "#1.6 With all busy time types",
                 [
                     [
-                        PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"),
-                        PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
+                        Period.parseText("20080601T120000Z/20080601T130000Z"),
+                        Period.parseText("20080601T140000Z/20080601T150000Z"),
                     ],
                     [
-                        PyCalendarPeriod.parseText("20080601T140000Z/20080601T150000Z"),
+                        Period.parseText("20080601T140000Z/20080601T150000Z"),
                     ],
                     [
-                        PyCalendarPeriod.parseText("20080601T160000Z/20080601T170000Z"),
+                        Period.parseText("20080601T160000Z/20080601T170000Z"),
                     ],
                 ],
                 "20080601T000000Z",
@@ -211,7 +211,7 @@
             (
                 "#1.7 With single busy time and event details",
                 [
-                    [PyCalendarPeriod.parseText("20080601T120000Z/20080601T130000Z"), ],
+                    [Period.parseText("20080601T120000Z/20080601T130000Z"), ],
                     [],
                     [],
                 ],
@@ -269,7 +269,7 @@
         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
         yield self.populate()
 
-        self.now = PyCalendarDateTime.getNowUTC()
+        self.now = DateTime.getNowUTC()
         self.now.setHHMMSS(0, 0, 0)
 
         self.now_12H = self.now.duplicate()
@@ -368,7 +368,7 @@
         timerange = caldavxml.TimeRange(start=self.now.getText(), end=self.now_1D.getText())
         result = (yield generateFreeBusyInfo(calendar, fbinfo, timerange, matchtotal))
         self.assertEqual(result, 1)
-        self.assertEqual(fbinfo[0], [PyCalendarPeriod.parseText("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
+        self.assertEqual(fbinfo[0], [Period.parseText("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
         self.assertEqual(len(fbinfo[1]), 0)
         self.assertEqual(len(fbinfo[2]), 0)
 
@@ -406,7 +406,7 @@
             event_details=event_details
         ))
         self.assertEqual(result, 1)
-        self.assertEqual(fbinfo[0], [PyCalendarPeriod.parseText("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
+        self.assertEqual(fbinfo[0], [Period.parseText("%s/%s" % (self.now_12H.getText(), self.now_13H.getText(),)), ])
         self.assertEqual(len(fbinfo[1]), 0)
         self.assertEqual(len(fbinfo[2]), 0)
         self.assertEqual(len(event_details), 1)

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py
===================================================================
--- 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)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 from twisted.trial import unittest
 from twistedcaldav.stdconfig import config
 from twistedcaldav.ical import Component
@@ -31,7 +31,7 @@
 
         self.subs = {}
 
-        self.now = PyCalendarDateTime.getNowUTC()
+        self.now = DateTime.getNowUTC()
         self.now.setHHMMSS(0, 0, 0)
 
         self.subs["now"] = self.now

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_implicit.py
===================================================================
--- 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)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twext.python.clsprop import classproperty
 from twext.web2 import responsecode
@@ -248,9 +248,9 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -287,12 +287,12 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -330,15 +330,15 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 9, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 12, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 9, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 12, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -447,7 +447,7 @@
 """,
                 (
                     ("mailto:user3 at example.com", None),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -502,7 +502,7 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -648,9 +648,9 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user3 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -705,7 +705,7 @@
 """,
                 (
                     ("mailto:user3 at example.com", None),
-                    ("mailto:user4 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user4 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -751,7 +751,7 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user4 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user4 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
             (
@@ -798,9 +798,9 @@
 END:VCALENDAR
 """,
                 (
-                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
-                    ("mailto:user4 at example.com", PyCalendarDateTime(2008, 8, 1, 12, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user1 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user2 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
+                    ("mailto:user4 at example.com", DateTime(2008, 8, 1, 12, 0, 0, tzid=Timezone(utc=True))),
                 ),
             ),
         )

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_itip.py
===================================================================
--- 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)
@@ -15,8 +15,8 @@
 ##
 from __future__ import print_function
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twisted.trial import unittest
 
@@ -2025,7 +2025,7 @@
 END:VCALENDAR
 """,
                 ("mailto:user2 at example.com",),
-                (PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
+                (DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
             ),
 
             # Recurring component with one instance, each with one attendee - cancel instance
@@ -2066,7 +2066,7 @@
 END:VCALENDAR
 """,
                 ("mailto:user2 at example.com",),
-                (PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
+                (DateTime(2008, 11, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
             ),
 
             # Recurring component with one instance, each with one attendee - cancel master
@@ -2127,7 +2127,7 @@
 """,
                 "",
                 ("mailto:user2 at example.com",),
-                (PyCalendarDateTime(2008, 12, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),),
+                (DateTime(2008, 12, 14, 0, 0, 0, tzid=Timezone(utc=True)),),
             ),
 
         )
@@ -2229,7 +2229,8 @@
 DTSTART;TZID=America/Los_Angeles:20101007T113000
 DTEND;TZID=America/Los_Angeles:20101007T120000
 ATTENDEE;CN=Missing Attendee;CUTYPE=INDIVIDUAL;EMAIL=missing at example.com;P
- ARTSTAT=DECLINED;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:missing at example.com
+ ARTSTAT=DECLINED;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:missing at example.co
+ m
 ORGANIZER;CN=The Organizer:mailto:organizer at example.com
 REQUEST-STATUS:2.0;Success
 SEQUENCE:24

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_utils.py
===================================================================
--- 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)
@@ -18,7 +18,7 @@
 Tests for calendarserver.tools.purge
 """
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twisted.internet.defer import inlineCallbacks
 from twisted.trial import unittest
@@ -30,7 +30,7 @@
 from txdav.common.datastore.test.util import populateCalendarsFrom, CommonCommonTests
 
 
-now = PyCalendarDateTime.getToday().getYear()
+now = DateTime.getToday().getYear()
 
 ORGANIZER_ICS = """BEGIN:VCALENDAR
 VERSION:2.0

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- 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)
@@ -47,7 +47,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python import hashlib
 
-from twistedcaldav import caldavxml, customxml
+from twistedcaldav import caldavxml, customxml, ical
 from twistedcaldav.config import config
 from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
 from twistedcaldav.dateops import normalizeForIndex, datetimeMktime, \
@@ -89,10 +89,10 @@
     InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
     InvalidResourceMove, InvalidComponentForStoreError
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
-from pycalendar.timezone import PyCalendarTimezone
-from pycalendar.value import PyCalendarValue
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
+from pycalendar.value import Value
 
 from zope.interface.declarations import implements
 
@@ -406,6 +406,26 @@
 
     _cacher = Memcacher("SQL.calhome", pickle=True, key_normalization=False)
 
+    _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",
+    }
+
     def __init__(self, transaction, ownerUID):
 
         self._childClass = Calendar
@@ -422,9 +442,8 @@
 
         # Common behavior is to have created and modified
 
-        return (
-            cls._homeMetaDataSchema.DEFAULT_EVENTS,
-            cls._homeMetaDataSchema.DEFAULT_TASKS,
+        default_collections = tuple([cls._componentDefaultColumn[name] for name in sorted(cls._componentDefaultColumn.keys())])
+        return default_collections + (
             cls._homeMetaDataSchema.ALARM_VEVENT_TIMED,
             cls._homeMetaDataSchema.ALARM_VEVENT_ALLDAY,
             cls._homeMetaDataSchema.ALARM_VTODO_TIMED,
@@ -445,9 +464,8 @@
 
         # Common behavior is to have created and modified
 
-        return (
-            "_default_events",
-            "_default_tasks",
+        default_attributes = tuple([cls._componentDefaultAttribute[name] for name in sorted(cls._componentDefaultAttribute.keys())])
+        return default_attributes + (
             "_alarm_vevent_timed",
             "_alarm_vevent_allday",
             "_alarm_vtodo_timed",
@@ -624,22 +642,18 @@
     @inlineCallbacks
     def createdHome(self):
 
-        # Default calendar
-        defaultCal = yield self.createCalendarWithName("calendar")
-
         # Check whether components type must be separate
         if config.RestrictCalendarsToOneComponentType:
-            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)
+            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)
         else:
-            yield self.setDefaultCalendar(defaultCal, False)
-            yield self.setDefaultCalendar(defaultCal, True)
+            cal = yield self.createCalendarWithName("calendar")
+            for name in ical.allowedStoreComponents:
+                yield self.setDefaultCalendar(cal, name)
 
         inbox = yield self.createCalendarWithName("inbox")
         yield inbox.setUsedForFreeBusy(False)
@@ -693,55 +707,13 @@
                     newcal = yield self.createCalendarWithName(newname)
                     yield newcal.setSupportedComponents(support_component)
 
-            yield _requireCalendarWithType("VEVENT", "calendar")
-            yield _requireCalendarWithType("VTODO", "tasks")
+            for name in ical.allowedStoreComponents:
+                yield _requireCalendarWithType(name, self._componentCalendarName[name])
 
 
     @inlineCallbacks
-    def pickNewDefaultCalendar(self, tasks=False):
+    def setDefaultCalendar(self, calendar, componentType):
         """
-        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):
-        """
         Set the default calendar for a particular type of component.
 
         @param calendar: the calendar being set as the default
@@ -749,10 +721,15 @@
         @param tasks: C{True} for VTODO, C{False} for VEVENT
         @type componentType: C{bool}
         """
+
+        # We only support VEVENT and VTOTO right now
+        componentType = componentType.upper()
+        if componentType not in self._componentDefaultAttribute:
+            returnValue(None)
+
         chm = self._homeMetaDataSchema
-        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
+        attribute_to_test = self._componentDefaultAttribute[componentType]
+        column_to_set = self._componentDefaultColumn[componentType]
 
         # Check validity of the default
         if calendar.isInbox():
@@ -794,8 +771,13 @@
         @rtype: L{Calendar} or C{None}
         """
 
+        # We only support VEVENT and VTOTO right now
+        componentType = componentType.upper()
+        if componentType not in self._componentDefaultAttribute:
+            returnValue(None)
+
         # Check any default calendar property first - this will create if none exists
-        attribute_to_test = "_default_tasks" if componentType == "VTODO" else "_default_events"
+        attribute_to_test = self._componentDefaultAttribute[componentType]
         defaultID = getattr(self, attribute_to_test)
         if defaultID:
             default = (yield self.childWithID(defaultID))
@@ -816,7 +798,8 @@
 
             # Try to find a calendar supporting the required component type. If there are multiple, pick
             # the one with the oldest created timestamp as that will likely be the initial provision.
-            for calendarName in (yield self.listCalendars()):
+            existing_names = (yield self.listCalendars())
+            for calendarName in existing_names:
                 calendar = (yield self.calendarWithName(calendarName))
                 if calendar.isInbox():
                     continue
@@ -832,12 +815,15 @@
                 if not create:
                     returnValue(None)
                 else:
-                    new_name = "%ss" % (componentType.lower()[1:],)
+                    # 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())
                     default = yield self.createCalendarWithName(new_name)
-                    yield default.setSupportedComponents(componentType.upper())
+                    yield default.setSupportedComponents(componentType)
 
             # Update the metadata
-            yield self.setDefaultCalendar(default, componentType == "VTODO")
+            yield self.setDefaultCalendar(default, componentType)
 
         returnValue(default)
 
@@ -847,7 +833,10 @@
         Is the supplied calendar one of the possible default calendars.
         """
         # Not allowed to delete the default calendar
-        return calendar._resourceID in (self._default_events, self._default_tasks)
+        for attr in self._componentDefaultAttribute.values():
+            if calendar._resourceID == getattr(self, attr):
+                return True
+        return False
 
     ALARM_DETAILS = {
         (True, True): (_homeMetaDataSchema.ALARM_VEVENT_TIMED, "_alarm_vevent_timed"),
@@ -2251,7 +2240,7 @@
                 # When there is no master we have a set of overridden components -
                 #   index them all.
                 # When there is one instance - index it.
-                expand = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+                expand = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
                 doInstanceIndexing = True
             else:
 
@@ -2263,8 +2252,8 @@
                 # by default.  This is a caching parameter which affects the size of the index;
                 # it does not affect search results beyond this period, but it may affect
                 # performance of such a search.
-                expand = (PyCalendarDateTime.getToday() +
-                          PyCalendarDuration(days=config.FreeBusyIndexExpandAheadDays))
+                expand = (DateTime.getToday() +
+                          Duration(days=config.FreeBusyIndexExpandAheadDays))
 
                 if expand_until and expand_until > expand:
                     expand = expand_until
@@ -2281,12 +2270,12 @@
                 # occurrences into some obscenely far-in-the-future date, so we cap the caching
                 # period.  Searches beyond this period will always be relatively expensive for
                 # resources with occurrences beyond this period.
-                if expand > (PyCalendarDateTime.getToday() +
-                             PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)):
+                if expand > (DateTime.getToday() +
+                             Duration(days=config.FreeBusyIndexExpandMaxDays)):
                     raise IndexedSearchException
 
             if config.FreeBusyIndexLowerLimitDays:
-                truncateLowerLimit = PyCalendarDateTime.getToday()
+                truncateLowerLimit = DateTime.getToday()
                 truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
             else:
                 truncateLowerLimit = None
@@ -2313,7 +2302,7 @@
             if not doInstanceIndexing:
                 instances = None
                 recurrenceLowerLimit = None
-                recurrenceLimit = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+                recurrenceLimit = DateTime(1900, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
 
         co = schema.CALENDAR_OBJECT
         tr = schema.TIME_RANGE
@@ -2432,7 +2421,7 @@
         @param instances: the set of instances to add
         @type instances: L{InstanceList}
         @param truncateLowerLimit: the lower limit for instances
-        @type truncateLowerLimit: L{PyCalendarDateTime}
+        @type truncateLowerLimit: L{DateTime}
         @param isInboxItem: indicates if an inbox item
         @type isInboxItem: C{bool}
         @param txn: transaction to use
@@ -2461,8 +2450,8 @@
         # For truncated items we insert a tomb stone lower bound so that a time-range
         # query with just an end bound will match
         if lowerLimitApplied or instances.lowerLimit and len(instances.instances) == 0:
-            start = PyCalendarDateTime(1901, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-            end = PyCalendarDateTime(1901, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            start = DateTime(1901, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+            end = DateTime(1901, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
             yield self._addInstanceDetails(component, None, start, end, False, True, "UNKNOWN", isInboxItem, txn)
 
         # Special - for unbounded recurrence we insert a value for "infinity"
@@ -2470,8 +2459,8 @@
         # We also need to add the "infinity" value if the event was bounded but
         # starts after the future expansion cut-off limit.
         if component.isRecurringUnbounded() or instances.limit and len(instances.instances) == 0:
-            start = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
-            end = PyCalendarDateTime(2100, 1, 1, 1, 0, 0, tzid=PyCalendarTimezone(utc=True))
+            start = DateTime(2100, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
+            end = DateTime(2100, 1, 1, 1, 0, 0, tzid=Timezone(utc=True))
             yield self._addInstanceDetails(component, None, start, end, False, True, "UNKNOWN", isInboxItem, txn)
 
 
@@ -2658,7 +2647,7 @@
         Get the RECURRANCE_MIN, RECURRANCE_MAX value from the database. Occasionally we might need to do an
         update to time-range data via a separate transaction, so we allow that to be passed in.
 
-        @return: L{PyCalendarDateTime} result
+        @return: L{DateTime} result
         """
         # Setup appropriate txn
         txn = txn if txn is not None else self._txn
@@ -4280,7 +4269,7 @@
         """
         Return an iCalendar ATTACH property for this attachment.
         """
-        attach = Property("ATTACH", "", valuetype=PyCalendarValue.VALUETYPE_URI)
+        attach = Property("ATTACH", "", valuetype=Value.VALUETYPE_URI)
         location = (yield self.updateProperty(attach))
         returnValue((attach, location,))
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- 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)
@@ -1337,7 +1337,7 @@
     @inlineCallbacks
     def test_iCalendarText(self):
         """
-        L{ICalendarObject.iCalendarText} returns a C{str} describing the same
+        L{ICalendarObject._text} returns a C{str} describing the same
         data provided by L{ICalendarObject.component}.
         """
         text = yield (yield self.calendarObjectUnderTest())._text()

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_attachments.py
===================================================================
--- 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)
@@ -16,8 +16,8 @@
 
 from calendarserver.tap.util import directoryFromConfig
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.value import PyCalendarValue
+from pycalendar.datetime import DateTime
+from pycalendar.value import Value
 
 from twext.enterprise.dal.syntax import Delete
 from twext.python.clsprop import classproperty
@@ -1249,7 +1249,7 @@
 
 
 
-now = PyCalendarDateTime.getToday().getYear()
+now = DateTime.getToday().getYear()
 
 PLAIN_ICS = """BEGIN:VCALENDAR
 VERSION:2.0
@@ -1454,7 +1454,7 @@
         cal.mainComponent().addProperty(Property(
             "ATTACH",
             "http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s" % (home.name(), dropboxid, name,),
-            valuetype=PyCalendarValue.VALUETYPE_URI
+            valuetype=Value.VALUETYPE_URI
         ))
         yield event.setComponent(cal)
         yield txn.commit()
@@ -1477,7 +1477,7 @@
         cal.mainComponent().addProperty(Property(
             "ATTACH",
             "http://localhost/calendars/users/%s/dropbox/%s.dropbox/%s" % (owner_home, dropboxid, name,),
-            valuetype=PyCalendarValue.VALUETYPE_URI
+            valuetype=Value.VALUETYPE_URI
         ))
         yield event.setComponent(cal)
         yield txn.commit()

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
===================================================================
--- 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)
@@ -42,7 +42,7 @@
 from txdav.caldav.datastore.test.common import (
     CommonTests, test_event_text, event1modified_text)
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 storePath = FilePath(__file__).parent().child("calendar_store")
 
@@ -68,7 +68,7 @@
     storePath.copyTo(calendarPath)
 
     # Set year values to current year
-    nowYear = PyCalendarDateTime.getToday().getYear()
+    nowYear = DateTime.getToday().getYear()
     for home in calendarPath.child("ho").child("me").children():
         if not home.basename().startswith("."):
             for calendar in home.children():

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_index_file.py
===================================================================
--- 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)
@@ -30,7 +30,7 @@
 from twistedcaldav.test.util import InMemoryMemcacheProtocol
 import twistedcaldav.test.util
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 import os
 
@@ -311,7 +311,7 @@
             else:
                 self.assertFalse(self.db.resourceExists(name), msg=description)
 
-        self.db.testAndUpdateIndex(PyCalendarDateTime(2020, 1, 1))
+        self.db.testAndUpdateIndex(DateTime(2020, 1, 1))
         for description, name, calendar_txt, reCreate, ok in data:
             if ok:
                 self.assertTrue(self.db.resourceExists(name), msg=description)

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- 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)
@@ -27,8 +27,8 @@
 L{txdav.caldav.datastore.test.common}.
 """
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.datetime import DateTime
+from pycalendar.timezone import Timezone
 
 from twext.enterprise.dal.syntax import Select, Parameter, Insert, Delete, \
     Update
@@ -42,7 +42,7 @@
 from twisted.internet.task import deferLater
 from twisted.trial import unittest
 
-from twistedcaldav import caldavxml
+from twistedcaldav import caldavxml, ical
 from twistedcaldav.caldavxml import CalendarDescription
 from twistedcaldav.config import config
 from twistedcaldav.dateops import datetimeMktime
@@ -78,7 +78,7 @@
         self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory)
         yield self.populate()
 
-        self.nowYear = {"now": PyCalendarDateTime.getToday().getYear()}
+        self.nowYear = {"now": DateTime.getToday().getYear()}
 
 
     @inlineCallbacks
@@ -474,14 +474,14 @@
             )
 
         supported_components = set()
-        self.assertEqual(len(toCalendars), 4)
+        self.assertEqual(len(toCalendars), 2 + len(ical.allowedStoreComponents))
         for calendar in toCalendars:
             if calendar.name() == "inbox":
                 continue
             result = yield calendar.getSupportedComponents()
             supported_components.add(result)
 
-        self.assertEqual(supported_components, set(("VEVENT", "VTODO",)))
+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
 
 
     @inlineCallbacks
@@ -509,7 +509,7 @@
             result = yield calendar.getSupportedComponents()
             supported_components.add(result)
 
-        self.assertEqual(supported_components, set(("VEVENT", "VTODO",)))
+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
 
 
     def test_calendarHomeVersion(self):
@@ -1124,7 +1124,7 @@
             result = yield calendar.getSupportedComponents()
             supported_components.add(result)
 
-        self.assertEqual(supported_components, set(("VEVENT", "VTODO",)))
+        self.assertEqual(supported_components, set(ical.allowedStoreComponents))
 
 
     @inlineCallbacks
@@ -1190,7 +1190,7 @@
         self.assertEqual(home._default_events, None)
         self.assertEqual(home._default_tasks, None)
         calendar1 = yield home.calendarWithName("calendar_1")
-        yield home.setDefaultCalendar(calendar1, False)
+        yield home.setDefaultCalendar(calendar1, "VEVENT")
         self.assertEqual(home._default_events, calendar1._resourceID)
         self.assertEqual(home._default_tasks, None)
         yield self.commit()
@@ -1198,7 +1198,7 @@
         home = yield self.homeUnderTest(name="home_defaults")
         calendar1 = yield home.calendarWithName("calendar_1")
         calendar2 = yield home.calendarWithName("calendar_1-vtodo")
-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, False), InvalidDefaultCalendar)
+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar2, "VEVENT"), InvalidDefaultCalendar)
         self.assertEqual(home._default_events, calendar1._resourceID)
         self.assertEqual(home._default_tasks, None)
         yield self.commit()
@@ -1206,20 +1206,20 @@
         home = yield self.homeUnderTest(name="home_defaults")
         calendar1 = yield home.calendarWithName("calendar_1")
         calendar2 = yield home.calendarWithName("calendar_1-vtodo")
-        yield home.setDefaultCalendar(calendar2, True)
+        yield home.setDefaultCalendar(calendar2, "VTODO")
         self.assertEqual(home._default_events, calendar1._resourceID)
         self.assertEqual(home._default_tasks, calendar2._resourceID)
         yield self.commit()
 
         home = yield self.homeUnderTest(name="home_defaults")
         calendar1 = yield home.calendarWithName("inbox")
-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, "VEVENT"), InvalidDefaultCalendar)
         yield self.commit()
 
         home = yield self.homeUnderTest(name="home_defaults")
         home_other = yield self.homeUnderTest(name="home_splits")
         calendar1 = yield home_other.calendarWithName("calendar_1")
-        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, False), InvalidDefaultCalendar)
+        yield self.failUnlessFailure(home.setDefaultCalendar(calendar1, "VEVENT"), InvalidDefaultCalendar)
         yield self.commit()
 
 
@@ -1377,38 +1377,38 @@
         self.assertEqual(rmax.getYear(), nowYear + 1)
 
         # Fully within range
-        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))
+        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))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, [])
 
         # Upper bound exceeded
-        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))
+        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))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower bound exceeded
-        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))
+        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))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower and upper bounds exceeded
-        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))
+        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))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower none within range
         testMin = None
-        testMax = PyCalendarDateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+        testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, [])
 
         # Lower none and upper bounds exceeded
         testMin = None
-        testMax = PyCalendarDateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+        testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         result = yield index.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
@@ -2154,7 +2154,7 @@
 
         self.subs = {}
 
-        self.now = PyCalendarDateTime.getNowUTC()
+        self.now = DateTime.getNowUTC()
         self.now.setHHMMSS(0, 0, 0)
 
         self.subs["now"] = self.now

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_util.py
===================================================================
--- 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)
@@ -349,7 +349,8 @@
                 "inbox": {},
                 # XXX: implementation is configuration-sensitive regarding the
                 # 'tasks' calendar and it shouldn't be.
-                "tasks": {}
+                "tasks": {},
+                "polls": {},
             }
         }, self.storeUnderTest())
         txn = self.transactionUnderTest()
@@ -412,7 +413,7 @@
             c1 = {"1.ics": self.sampleEvent("uid1")}
         if c2 is None:
             c2 = {"2.ics": self.sampleEvent("uid2")}
-        defaults = {"calendar": {}, "inbox": {}, "tasks": {}}
+        defaults = {"calendar": {}, "inbox": {}, "tasks": {}, "polls": {}}
         def conflicted(caldata):
             d = defaults.copy()
             d.update(conflicted=caldata)

Modified: CalendarServer/trunk/txdav/caldav/datastore/util.py
===================================================================
--- 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)
@@ -37,6 +37,7 @@
 from twext.python.vcomponent import InvalidICalendarDataError
 from twext.python.vcomponent import VComponent
 
+from twistedcaldav import ical
 from twistedcaldav.datafilters.hiddeninstance import HiddenInstanceFilter
 from twistedcaldav.datafilters.privateevents import PrivateEventFilter
 from twistedcaldav.ical import PERUSER_UID
@@ -380,9 +381,11 @@
     """
     from twistedcaldav.config import config
     if not merge:
-        yield outHome.removeCalendarWithName("calendar")
         if config.RestrictCalendarsToOneComponentType:
-            yield outHome.removeCalendarWithName("tasks")
+            for name in ical.allowedStoreComponents:
+                yield outHome.removeCalendarWithName(outHome._componentCalendarName[name])
+        else:
+            yield outHome.removeCalendarWithName("calendar")
         yield outHome.removeCalendarWithName("inbox")
 
     outHome.properties().update(inHome.properties())

Modified: CalendarServer/trunk/txdav/caldav/icalendarstore.py
===================================================================
--- 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)
@@ -363,9 +363,9 @@
         instances that occur within the time range that begins at
         C{start} and ends at C{end}.
 
-        @param start: a L{PyCalendarDateTime}.
-        @param end: a L{PyCalendarDateTime}.
-        @param timeZone: a L{PyCalendarTimezone}.
+        @param start: a L{DateTime}.
+        @param end: a L{DateTime}.
+        @param timeZone: a L{Timezone}.
         @return: an iterable of L{ICalendarObject}s.
         """
 

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- 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)
@@ -27,7 +27,7 @@
 
 from cStringIO import StringIO
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from twext.enterprise.dal.syntax import (
     Delete, utcNowSQL, Union, Insert, Len, Max, Parameter, SavepointAction,
@@ -1106,7 +1106,7 @@
     def eventsOlderThan(self, cutoff, batchSize=None):
         """
         Return up to the oldest batchSize events which exist completely earlier
-        than "cutoff" (PyCalendarDateTime)
+        than "cutoff" (DateTime)
 
         Returns a deferred to a list of (uid, calendarName, eventName, maxDate)
         tuples.
@@ -1114,7 +1114,7 @@
 
         # Make sure cut off is after any lower limit truncation in the DB
         if config.FreeBusyIndexLowerLimitDays:
-            truncateLowerLimit = PyCalendarDateTime.getToday()
+            truncateLowerLimit = DateTime.getToday()
             truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
             if cutoff < truncateLowerLimit:
                 raise ValueError("Cannot query events older than %s" % (truncateLowerLimit.getText(),))
@@ -1132,7 +1132,7 @@
 
         # Make sure cut off is after any lower limit truncation in the DB
         if config.FreeBusyIndexLowerLimitDays:
-            truncateLowerLimit = PyCalendarDateTime.getToday()
+            truncateLowerLimit = DateTime.getToday()
             truncateLowerLimit.offsetDay(-config.FreeBusyIndexLowerLimitDays)
             if cutoff < truncateLowerLimit:
                 raise ValueError("Cannot query events older than %s" % (truncateLowerLimit.getText(),))

Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- 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)
@@ -43,8 +43,8 @@
 from twext.python.clsprop import classproperty
 from twext.python.log import Logger
 
-from pycalendar.datetime import PyCalendarDateTime
-from pycalendar.duration import PyCalendarDuration
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
 
 log = Logger()
 
@@ -566,7 +566,7 @@
             )
             if qualifiers is not None:
 
-                today = PyCalendarDateTime.getToday()
+                today = DateTime.getToday()
 
                 # Determine how far we need to extend the current expansion of
                 # events. If we have an open-ended time-range we will expand
@@ -578,11 +578,11 @@
                     maxDate = maxDate.duplicate()
                     maxDate.offsetDay(1)
                     maxDate.setDateOnly(True)
-                    upperLimit = today + PyCalendarDuration(days=config.FreeBusyIndexExpandMaxDays)
+                    upperLimit = today + Duration(days=config.FreeBusyIndexExpandMaxDays)
                     if maxDate > upperLimit:
                         raise TimeRangeUpperLimit(upperLimit)
                     if isStartDate:
-                        maxDate += PyCalendarDuration(days=365)
+                        maxDate += Duration(days=365)
 
                 # Determine if the start date is too early for the restricted range we
                 # are applying. If it is today or later we don't need to worry about truncation
@@ -591,7 +591,7 @@
                 if minDate >= today:
                     minDate = None
                 if minDate is not None and config.FreeBusyIndexLowerLimitDays:
-                    truncateLowerLimit = today - PyCalendarDuration(days=config.FreeBusyIndexLowerLimitDays)
+                    truncateLowerLimit = today - Duration(days=config.FreeBusyIndexLowerLimitDays)
                     if minDate < truncateLowerLimit:
                         raise TimeRangeLowerLimit(truncateLowerLimit)
 

Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- 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)
@@ -30,6 +30,7 @@
     "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,
+    "DEFAULT_POLLS" 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,
@@ -365,7 +366,7 @@
     "VALUE" nvarchar2(255)
 );
 
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '26');
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '27');
 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 (
@@ -376,6 +377,10 @@
     DEFAULT_TASKS
 );
 
+create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
+    DEFAULT_POLLS
+);
+
 create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
     NOTIFICATION_HOME_RESOURCE_ID
 );

Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- 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)
@@ -74,6 +74,7 @@
   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,
+  DEFAULT_POLLS            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,
@@ -87,6 +88,8 @@
 	CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
 create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
 	CALENDAR_HOME_METADATA(DEFAULT_TASKS);
+create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
+	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
 -----------------------
 -- Calendar Metadata --
@@ -695,6 +698,6 @@
   VALUE                         varchar(255)
 );
 
-insert into CALENDARSERVER values ('VERSION', '26');
+insert into CALENDARSERVER values ('VERSION', '27');
 insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
 insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v24.sql
===================================================================
--- 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)
@@ -1,491 +0,0 @@
-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
-);
-

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)
===================================================================
--- 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)
@@ -0,0 +1,491 @@
+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
+);
+

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v25.sql
===================================================================
--- 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)
@@ -1,491 +0,0 @@
-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
-);
-

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)
===================================================================
--- 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)
@@ -0,0 +1,491 @@
+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
+);
+

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)
===================================================================
--- 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)
@@ -0,0 +1,495 @@
+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
+);
+

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql
===================================================================
--- 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)
@@ -1,700 +0,0 @@
--- -*- 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');

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)
===================================================================
--- 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)
@@ -0,0 +1,700 @@
+-- -*- 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');

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql
===================================================================
--- 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)
@@ -1,700 +0,0 @@
--- -*- 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');

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)
===================================================================
--- 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)
@@ -0,0 +1,700 @@
+-- -*- 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');

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)
===================================================================
--- 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)
@@ -0,0 +1,700 @@
+-- -*- 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');

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
===================================================================
--- 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)
@@ -1,26 +0,0 @@
-----
--- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,26 @@
+----
+-- 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';

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql
===================================================================
--- 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)
@@ -1,43 +0,0 @@
-----
--- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,43 @@
+----
+-- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,33 @@
+----
+-- 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';

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
===================================================================
--- 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)
@@ -1,35 +0,0 @@
-----
--- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,35 @@
+----
+-- 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';

Deleted: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql
===================================================================
--- 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)
@@ -1,32 +0,0 @@
-----
--- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,32 @@
+----
+-- 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';

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)
===================================================================
--- 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)
@@ -0,0 +1,31 @@
+----
+-- 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';

Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- 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)
@@ -32,7 +32,7 @@
 
 from hashlib import md5
 
-from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.datetime import DateTime
 
 from random import Random
 
@@ -50,6 +50,7 @@
 from twisted.internet.task import deferLater
 from twisted.trial.unittest import TestCase
 
+from twistedcaldav import ical
 from twistedcaldav.config import config
 from twistedcaldav.stdconfig import DEFAULT_CONFIG
 from twistedcaldav.vcard import Component as ABComponent
@@ -447,12 +448,11 @@
             # We don't want the default calendar or inbox to appear unless it's
             # explicitly listed.
             try:
-                yield home.removeCalendarWithName("calendar")
-                # FIXME: this should be an argument to the function, not a
-                # global configuration variable.  Related: this needs
-                # independent tests.
                 if config.RestrictCalendarsToOneComponentType:
-                    yield home.removeCalendarWithName("tasks")
+                    for name in ical.allowedStoreComponents:
+                        yield home.removeCalendarWithName(home._componentCalendarName[name])
+                else:
+                    yield home.removeCalendarWithName("calendar")
                 yield home.removeCalendarWithName("inbox")
             except NoSuchHomeChildError:
                 pass
@@ -480,7 +480,7 @@
     Update the supplied iCalendar data so that all dates are updated to the current year.
     """
 
-    nowYear = PyCalendarDateTime.getToday().getYear()
+    nowYear = DateTime.getToday().getYear()
     return data % {"now": nowYear}
 
 

Modified: CalendarServer/trunk/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
===================================================================
--- 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)
@@ -108,8 +108,12 @@
                     calendar = (yield home.calendarWithName(calendarName))
                     if calendar is not None:
                         try:
+                            if propname == caldavxml.ScheduleDefaultCalendarURL:
+                                ctype = "VEVENT"
+                            elif propname == customxml.ScheduleDefaultTasksURL:
+                                ctype = "VTODO"
                             yield home.setDefaultCalendar(
-                                calendar, tasks=(propname == customxml.ScheduleDefaultTasksURL)
+                                calendar, ctype
                             )
                         except InvalidDefaultCalendar:
                             # Ignore these - the server will recover
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/4a010cb5/attachment.html>


More information about the calendarserver-changes mailing list