<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12994] CalendarServer/branches/users/sagen/move2who-4</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12994">12994</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-03-25 14:34:44 -0700 (Tue, 25 Mar 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>test_upgrade.py passes</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertapcaldavpy">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/caldav.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavicalpy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/ical.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavtesttest_upgradepy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_upgrade.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavtestutilpy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/util.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavupgradepy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/upgrade.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavutilpy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/util.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertapcaldavpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/caldav.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/caldav.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tap/caldav.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -98,7 +98,9 @@
</span><span class="cx"> from twistedcaldav.config import config, ConfigurationError
</span><span class="cx"> from twistedcaldav.localization import processLocalizationFiles
</span><span class="cx"> from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
</span><del>-from twistedcaldav.upgrade import UpgradeFileSystemFormatStep, PostDBImportStep
</del><ins>+from twistedcaldav.upgrade import (
+ UpgradeFileSystemFormatStep, PostDBImportStep,
+)
</ins><span class="cx">
</span><span class="cx"> try:
</span><span class="cx"> from twistedcaldav.authkerb import NegotiateCredentialFactory
</span><span class="lines">@@ -1235,13 +1237,6 @@
</span><span class="cx"> if store is None:
</span><span class="cx"> raise StoreNotAvailable()
</span><span class="cx">
</span><del>- # Create a Directory Proxy "Server" service and hand it to the
- # store.
- # FIXME: right now the store passed *to* the directory is the
- # calendar/contacts data store, but for a multi-server deployment
- # it will need its own separate store.
- store.setDirectoryService(directoryFromConfig(config, store=store))
-
</del><span class="cx"> result = self.requestProcessingService(options, store, logObserver)
</span><span class="cx">
</span><span class="cx"> # Optionally set up push notifications
</span><span class="lines">@@ -1371,12 +1366,6 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def toolServiceCreator(pool, store, ignored, storageService):
</span><del>- # Create a Directory Proxy "Server" service and hand it to the
- # store
- # FIXME: right now the store passed *to* the directory is the
- # calendar/contacts data store, but for a multi-server deployment
- # it will need its own separate store.
- store.setDirectoryService(directoryFromConfig(config, store=store))
</del><span class="cx"> return config.UtilityServiceClass(store)
</span><span class="cx">
</span><span class="cx"> uid, gid = getSystemIDs(config.UserName, config.GroupName)
</span><span class="lines">@@ -1461,6 +1450,7 @@
</span><span class="cx"> @return: the appropriate a service to start.
</span><span class="cx"> @rtype: L{IService}
</span><span class="cx"> """
</span><ins>+
</ins><span class="cx"> def createSubServiceFactory(
</span><span class="cx"> dialect=POSTGRES_DIALECT, paramstyle='pyformat'
</span><span class="cx"> ):
</span><span class="lines">@@ -1473,6 +1463,13 @@
</span><span class="cx"> )
</span><span class="cx"> cp.setServiceParent(ms)
</span><span class="cx"> store = storeFromConfig(config, cp.connection, directory)
</span><ins>+ if directory is None:
+ # Create a Directory Proxy "Server" service and hand it to
+ # the store.
+ # FIXME: right now the store passed *to* the directory is the
+ # calendar/contacts data store, but for a multi-server deployment
+ # it will need its own separate store.
+ store.setDirectoryService(directoryFromConfig(config, store=store))
</ins><span class="cx">
</span><span class="cx"> pps = PreProcessingService(
</span><span class="cx"> createMainService, cp, store, logObserver, storageService
</span><span class="lines">@@ -1489,7 +1486,7 @@
</span><span class="cx">
</span><span class="cx"> # Still need this for Snow Leopard support
</span><span class="cx"> pps.addStep(
</span><del>- UpgradeFileSystemFormatStep(config)
</del><ins>+ UpgradeFileSystemFormatStep(config, store)
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> pps.addStep(
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavicalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/ical.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/ical.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/ical.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -3241,7 +3241,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def normalizeCalendarUserAddresses(self, lookupFunction, principalFunction,
</del><ins>+ def normalizeCalendarUserAddresses(self, lookupFunction, recordFunction,
</ins><span class="cx"> toUUID=True):
</span><span class="cx"> """
</span><span class="cx"> Do the ORGANIZER/ATTENDEE property normalization.
</span><span class="lines">@@ -3249,6 +3249,7 @@
</span><span class="cx"> @param lookupFunction: function returning full name, guid, CUAs for a given CUA
</span><span class="cx"> @type lookupFunction: L{Function}
</span><span class="cx"> """
</span><ins>+
</ins><span class="cx"> for component in self.subcomponents():
</span><span class="cx"> if component.name() in ignoredComponents:
</span><span class="cx"> continue
</span><span class="lines">@@ -3261,7 +3262,7 @@
</span><span class="cx"> # Check that we can lookup this calendar user address - if not
</span><span class="cx"> # we cannot do anything with it
</span><span class="cx"> cuaddr = normalizeCUAddr(prop.value())
</span><del>- name, guid, cuaddrs = yield lookupFunction(cuaddr, principalFunction, config)
</del><ins>+ name, guid, cuaddrs = yield lookupFunction(cuaddr, recordFunction, config)
</ins><span class="cx"> if guid is None:
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="lines">@@ -3357,7 +3358,7 @@
</span><span class="cx">
</span><span class="cx"> # For VPOLL also do immediate children
</span><span class="cx"> if component.name() == "VPOLL":
</span><del>- yield component.normalizeCalendarUserAddresses(lookupFunction, principalFunction, toUUID)
</del><ins>+ yield component.normalizeCalendarUserAddresses(lookupFunction, recordFunction, toUUID)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def allPerUserUIDs(self):
</span><span class="lines">@@ -3568,10 +3569,10 @@
</span><span class="cx"> # #
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>-def normalizeCUAddress(cuaddr, lookupFunction, principalFunction, toUUID=True):
</del><ins>+def normalizeCUAddress(cuaddr, lookupFunction, recordFunction, toUUID=True):
</ins><span class="cx"> # Check that we can lookup this calendar user address - if not
</span><span class="cx"> # we cannot do anything with it
</span><del>- _ignore_name, guid, cuaddrs = (yield lookupFunction(normalizeCUAddr(cuaddr), principalFunction, config))
</del><ins>+ _ignore_name, guid, cuaddrs = (yield lookupFunction(normalizeCUAddr(cuaddr), recordFunction, config))
</ins><span class="cx">
</span><span class="cx"> if toUUID:
</span><span class="cx"> # Always re-write value to urn:uuid
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavtesttest_upgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_upgrade.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_upgrade.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/test_upgrade.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -20,21 +20,20 @@
</span><span class="cx"> import cPickle
</span><span class="cx">
</span><span class="cx"> from twisted.python.reflect import namedClass
</span><del>-from twisted.internet.defer import inlineCallbacks
</del><ins>+from twisted.internet.defer import inlineCallbacks, succeed
</ins><span class="cx">
</span><span class="cx"> from txdav.xml.parser import WebDAVDocument
</span><span class="cx"> from txdav.caldav.datastore.index_file import db_basename
</span><span class="cx">
</span><span class="cx"> from twistedcaldav.config import config
</span><del>-from twistedcaldav.directory.xmlfile import XMLDirectoryService
</del><ins>+# from twistedcaldav.directory.xmlfile import XMLDirectoryService
</ins><span class="cx"> from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
</span><span class="cx"> from txdav.caldav.datastore.scheduling.imip.mailgateway import MailGatewayTokensDatabase
</span><span class="cx"> from twistedcaldav.upgrade import (
</span><span class="cx"> xattrname, upgradeData, updateFreeBusySet,
</span><span class="cx"> removeIllegalCharacters, normalizeCUAddrs
</span><span class="cx"> )
</span><del>-from twistedcaldav.test.util import TestCase
-from calendarserver.tools.util import getDirectory
</del><ins>+from twistedcaldav.test.util import StoreTestCase
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -51,33 +50,33 @@
</span><span class="cx"> OLDPROXYFILE = ".db.calendaruserproxy"
</span><span class="cx"> NEWPROXYFILE = "proxies.sqlite"
</span><span class="cx">
</span><del>-class UpgradeTests(TestCase):
</del><span class="cx">
</span><ins>+class UpgradeTests(StoreTestCase):
</ins><span class="cx">
</span><del>- def setUpXMLDirectory(self):
- xmlFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
- "directory", "test", "accounts.xml")
- config.DirectoryService.params.xmlFile = xmlFile
</del><span class="cx">
</span><del>- xmlAugmentsFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
- "directory", "test", "augments.xml")
- config.AugmentService.type = "twistedcaldav.directory.augment.AugmentXMLDB"
- config.AugmentService.params.xmlFiles = (xmlAugmentsFile,)
</del><ins>+ # def setUpXMLDirectory(self):
+ # xmlFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
+ # "directory", "test", "accounts.xml")
+ # config.DirectoryService.params.xmlFile = xmlFile
</ins><span class="cx">
</span><del>- resourceFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
- "directory", "test", "resources.xml")
- config.ResourceService.params.xmlFile = resourceFile
</del><ins>+ # xmlAugmentsFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
+ # "directory", "test", "augments.xml")
+ # config.AugmentService.type = "twistedcaldav.directory.augment.AugmentXMLDB"
+ # config.AugmentService.params.xmlFiles = (xmlAugmentsFile,)
</ins><span class="cx">
</span><ins>+ # resourceFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
+ # "directory", "test", "resources.xml")
+ # config.ResourceService.params.xmlFile = resourceFile
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def doUpgrade(self, config):
</span><span class="cx"> """
</span><span class="cx"> Perform the actual upgrade. (Hook for parallel tests.)
</span><span class="cx"> """
</span><del>- return upgradeData(config)
</del><ins>+ return upgradeData(config, self.directory)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def setUpInitialStates(self):
</span><del>- self.setUpXMLDirectory()
</del><span class="cx">
</span><span class="cx"> self.setUpOldDocRoot()
</span><span class="cx"> self.setUpOldDocRootWithoutDB()
</span><span class="lines">@@ -202,7 +201,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> self.setUpInitialStates()
</span><del>- directory = getDirectory()
</del><ins>+ directory = self.directory
</ins><span class="cx">
</span><span class="cx"> #
</span><span class="cx"> # Verify these values require no updating:
</span><span class="lines">@@ -210,18 +209,18 @@
</span><span class="cx">
</span><span class="cx"> # Uncompressed XML
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/__uids__/BB05932F-DCE7-4195-9ED4-0896EAFF3B0B/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><del>- self.assertEquals(updateFreeBusySet(value, directory), None)
</del><ins>+ self.assertEquals((yield updateFreeBusySet(value, directory)), None)
</ins><span class="cx">
</span><span class="cx"> # Zlib compressed XML
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/__uids__/BB05932F-DCE7-4195-9ED4-0896EAFF3B0B/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><span class="cx"> value = zlib.compress(value)
</span><del>- self.assertEquals(updateFreeBusySet(value, directory), None)
</del><ins>+ self.assertEquals((yield updateFreeBusySet(value, directory)), None)
</ins><span class="cx">
</span><span class="cx"> # Pickled XML
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/__uids__/BB05932F-DCE7-4195-9ED4-0896EAFF3B0B/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><span class="cx"> doc = WebDAVDocument.fromString(value)
</span><span class="cx"> value = cPickle.dumps(doc.root_element)
</span><del>- self.assertEquals(updateFreeBusySet(value, directory), None)
</del><ins>+ self.assertEquals((yield updateFreeBusySet(value, directory)), None)
</ins><span class="cx">
</span><span class="cx"> #
</span><span class="cx"> # Verify these values do require updating:
</span><span class="lines">@@ -230,14 +229,14 @@
</span><span class="cx">
</span><span class="cx"> # Uncompressed XML
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><del>- newValue = updateFreeBusySet(value, directory)
</del><ins>+ newValue = yield updateFreeBusySet(value, directory)
</ins><span class="cx"> newValue = zlib.decompress(newValue)
</span><span class="cx"> self.assertEquals(newValue, expected)
</span><span class="cx">
</span><span class="cx"> # Zlib compressed XML
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><span class="cx"> value = zlib.compress(value)
</span><del>- newValue = updateFreeBusySet(value, directory)
</del><ins>+ newValue = yield updateFreeBusySet(value, directory)
</ins><span class="cx"> newValue = zlib.decompress(newValue)
</span><span class="cx"> self.assertEquals(newValue, expected)
</span><span class="cx">
</span><span class="lines">@@ -245,7 +244,7 @@
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><span class="cx"> doc = WebDAVDocument.fromString(value)
</span><span class="cx"> value = cPickle.dumps(doc.root_element)
</span><del>- newValue = updateFreeBusySet(value, directory)
</del><ins>+ newValue = yield updateFreeBusySet(value, directory)
</ins><span class="cx"> newValue = zlib.decompress(newValue)
</span><span class="cx"> self.assertEquals(newValue, expected)
</span><span class="cx">
</span><span class="lines">@@ -254,7 +253,7 @@
</span><span class="cx"> #
</span><span class="cx"> expected = "<?xml version='1.0' encoding='UTF-8'?>\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'/>"
</span><span class="cx"> value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/nonexistent/calendar</href>\r\n</calendar-free-busy-set>\r\n"
</span><del>- newValue = updateFreeBusySet(value, directory)
</del><ins>+ newValue = yield updateFreeBusySet(value, directory)
</ins><span class="cx"> newValue = zlib.decompress(newValue)
</span><span class="cx"> self.assertEquals(newValue, expected)
</span><span class="cx">
</span><span class="lines">@@ -296,7 +295,6 @@
</span><span class="cx"> The upgrade process should remove unused notification directories in
</span><span class="cx"> users' calendar homes, as well as the XML files found therein.
</span><span class="cx"> """
</span><del>- self.setUpXMLDirectory()
</del><span class="cx">
</span><span class="cx"> before = {
</span><span class="cx"> "calendars": {
</span><span class="lines">@@ -306,7 +304,7 @@
</span><span class="cx"> db_basename : {
</span><span class="cx"> "@contents": "",
</span><span class="cx"> },
</span><del>- },
</del><ins>+ },
</ins><span class="cx"> "notifications": {
</span><span class="cx"> "sample-notification.xml": {
</span><span class="cx"> "@contents": "<?xml version='1.0'>\n<should-be-ignored />"
</span><span class="lines">@@ -353,8 +351,6 @@
</span><span class="cx"> are upgraded to /calendars/__uids__/XX/YY/<guid> form
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -503,8 +499,6 @@
</span><span class="cx"> whose records don't exist are moved into dataroot/archived/
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -575,8 +569,6 @@
</span><span class="cx"> whose records don't exist are moved into dataroot/archived/
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "archived" :
</span><span class="cx"> {
</span><span class="lines">@@ -663,8 +655,6 @@
</span><span class="cx"> interrupt an upgrade.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> ignoredUIDContents = {
</span><span class="cx"> "64" : {
</span><span class="cx"> "23" : {
</span><span class="lines">@@ -757,8 +747,6 @@
</span><span class="cx"> interrupt an upgrade.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> beforeUIDContents = {
</span><span class="cx"> "64" : {
</span><span class="cx"> "23" : {
</span><span class="lines">@@ -867,8 +855,6 @@
</span><span class="cx"> are upgraded to /calendars/__uids__/XX/YY/<guid>/ form
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -978,8 +964,6 @@
</span><span class="cx"> form are upgraded correctly in place
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -1106,8 +1090,6 @@
</span><span class="cx"> form which require no changes are untouched
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -1233,8 +1215,6 @@
</span><span class="cx"> Verify that inbox items older than 60 days are deleted
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -1337,8 +1317,6 @@
</span><span class="cx"> also doesn't write the new version file
</span><span class="cx"> """
</span><span class="cx">
</span><del>- self.setUpXMLDirectory()
-
</del><span class="cx"> before = {
</span><span class="cx"> "calendars" :
</span><span class="cx"> {
</span><span class="lines">@@ -1454,7 +1432,7 @@
</span><span class="cx"> self.setUpInitialStates()
</span><span class="cx"> # Override the normal getResourceInfo method with our own:
</span><span class="cx"> # XMLDirectoryService.getResourceInfo = _getResourceInfo
</span><del>- self.patch(XMLDirectoryService, "getResourceInfo", _getResourceInfo)
</del><ins>+ # self.patch(XMLDirectoryService, "getResourceInfo", _getResourceInfo)
</ins><span class="cx">
</span><span class="cx"> before = {
</span><span class="cx"> "trigger_resource_migration" : {
</span><span class="lines">@@ -1520,7 +1498,9 @@
</span><span class="cx"> autoSchedule = autoSchedule == 1
</span><span class="cx"> self.assertEquals(info[0], autoSchedule)
</span><span class="cx">
</span><ins>+ test_migrateResourceInfo.todo = "Need to port to twext.who"
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def test_removeIllegalCharacters(self):
</span><span class="cx"> """
</span><span class="cx"> Control characters aside from NL and CR are removed.
</span><span class="lines">@@ -1543,37 +1523,37 @@
</span><span class="cx"> reduce the number of principal lookup calls during upgrade.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- class StubPrincipal(object):
- def __init__(self, record):
- self.record = record
-
</del><span class="cx"> class StubRecord(object):
</span><del>- def __init__(self, fullName, guid, cuas):
- self.fullName = fullName
- self.guid = guid
</del><ins>+ def __init__(self, fullNames, uid, cuas):
+ self.fullNames = fullNames
+ self.uid = uid
</ins><span class="cx"> self.calendarUserAddresses = cuas
</span><span class="cx">
</span><ins>+ @property
+ def displayName(self):
+ return self.fullNames[0]
+
</ins><span class="cx"> class StubDirectory(object):
</span><span class="cx"> def __init__(self):
</span><span class="cx"> self.count = 0
</span><span class="cx">
</span><del>- def principalForCalendarUserAddress(self, cuaddr):
</del><ins>+ def recordWithCalendarUserAddress(self, cuaddr):
</ins><span class="cx"> self.count += 1
</span><span class="cx"> record = records.get(cuaddr, None)
</span><span class="cx"> if record is not None:
</span><del>- return StubPrincipal(record)
</del><ins>+ return succeed(record)
</ins><span class="cx"> else:
</span><span class="cx"> raise Exception
</span><span class="cx">
</span><span class="cx"> records = {
</span><del>- "mailto:a@example.com" :
- StubRecord("User A", 123, ("mailto:a@example.com", "urn:uuid:123")),
- "mailto:b@example.com" :
- StubRecord("User B", 234, ("mailto:b@example.com", "urn:uuid:234")),
- "/principals/users/a" :
- StubRecord("User A", 123, ("mailto:a@example.com", "urn:uuid:123")),
- "/principals/users/b" :
- StubRecord("User B", 234, ("mailto:b@example.com", "urn:uuid:234")),
</del><ins>+ "mailto:a@example.com":
+ StubRecord(("User A",), u"123", ("mailto:a@example.com", "urn:uuid:123")),
+ "mailto:b@example.com":
+ StubRecord(("User B",), u"234", ("mailto:b@example.com", "urn:uuid:234")),
+ "/principals/users/a":
+ StubRecord(("User A",), u"123", ("mailto:a@example.com", "urn:uuid:123")),
+ "/principals/users/b":
+ StubRecord(("User B",), u"234", ("mailto:b@example.com", "urn:uuid:234")),
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> directory = StubDirectory()
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavtestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/util.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/util.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/test/util.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -187,91 +187,6 @@
</span><span class="cx"> augments.setContent(augmentsFile.getContent())
</span><span class="cx">
</span><span class="cx">
</span><del>-class TestCase(txweb2.dav.test.util.TestCase):
- resource_class = RootResource
-
- def createDataStore(self):
- """
- Create an L{IDataStore} that can store calendars (but not
- addressbooks.) By default returns a L{CommonDataStore}, but this is a
- hook for subclasses to override to provide different data stores.
- """
- return CommonDataStore(FilePath(config.DocumentRoot), None, None, True, False,
- quota=deriveQuota(self))
-
-
- def setupCalendars(self):
- """
- When a directory service exists, set up the resources at C{/calendars}
- and C{/addressbooks} (a L{DirectoryCalendarHomeProvisioningResource}
- and L{DirectoryAddressBookHomeProvisioningResource} respectively), and
- assign them to the C{self.calendarCollection} and
- C{self.addressbookCollection} attributes.
-
- A directory service may be associated with this L{TestCase} with
- L{TestCase.createStockDirectoryService} or
- L{TestCase.directoryFixture.addDirectoryService}.
- """
- newStore = self.createDataStore()
-
-
- @self.directoryFixture.whenDirectoryServiceChanges
- def putAllChildren(ds):
- self.calendarCollection = (
- DirectoryCalendarHomeProvisioningResource(
- ds, "/calendars/", newStore
- ))
- self.site.resource.putChild("calendars", self.calendarCollection)
- self.addressbookCollection = (
- DirectoryAddressBookHomeProvisioningResource(
- ds, "/addressbooks/", newStore
- ))
- self.site.resource.putChild("addressbooks",
- self.addressbookCollection)
-
-
- def configure(self):
- """
- Adjust the global configuration for this test.
- """
- config.reset()
-
- config.ServerRoot = os.path.abspath(self.serverRoot)
- config.ConfigRoot = "config"
- config.LogRoot = "logs"
- config.RunRoot = "logs"
-
- config.Memcached.Pools.Default.ClientEnabled = False
- config.Memcached.Pools.Default.ServerEnabled = False
- ClientFactory.allowTestCache = True
- memcacher.Memcacher.allowTestCache = True
- memcacher.Memcacher.memoryCacheInstance = None
- config.DirectoryAddressBook.Enabled = False
- config.UsePackageTimezones = True
-
-
-
- def setUp(self):
- super(TestCase, self).setUp()
-
- # FIXME: this is only here to workaround circular imports
- doBind()
-
- self.serverRoot = self.mktemp()
- os.mkdir(self.serverRoot)
-
- self.configure()
-
- if not os.path.exists(config.DataRoot):
- os.makedirs(config.DataRoot)
- if not os.path.exists(config.DocumentRoot):
- os.makedirs(config.DocumentRoot)
- if not os.path.exists(config.ConfigRoot):
- os.makedirs(config.ConfigRoot)
- if not os.path.exists(config.LogRoot):
- os.makedirs(config.LogRoot)
-
-
</del><span class="cx"> def createHierarchy(self, structure, root=None):
</span><span class="cx"> if root is None:
</span><span class="cx"> root = os.path.abspath(self.mktemp())
</span><span class="lines">@@ -425,6 +340,93 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><ins>+class TestCase(txweb2.dav.test.util.TestCase):
+ resource_class = RootResource
+
+ def createDataStore(self):
+ """
+ Create an L{IDataStore} that can store calendars (but not
+ addressbooks.) By default returns a L{CommonDataStore}, but this is a
+ hook for subclasses to override to provide different data stores.
+ """
+ return CommonDataStore(FilePath(config.DocumentRoot), None, None, True, False,
+ quota=deriveQuota(self))
+
+
+ def setupCalendars(self):
+ """
+ When a directory service exists, set up the resources at C{/calendars}
+ and C{/addressbooks} (a L{DirectoryCalendarHomeProvisioningResource}
+ and L{DirectoryAddressBookHomeProvisioningResource} respectively), and
+ assign them to the C{self.calendarCollection} and
+ C{self.addressbookCollection} attributes.
+
+ A directory service may be associated with this L{TestCase} with
+ L{TestCase.createStockDirectoryService} or
+ L{TestCase.directoryFixture.addDirectoryService}.
+ """
+ newStore = self.createDataStore()
+
+
+ @self.directoryFixture.whenDirectoryServiceChanges
+ def putAllChildren(ds):
+ self.calendarCollection = (
+ DirectoryCalendarHomeProvisioningResource(
+ ds, "/calendars/", newStore
+ ))
+ self.site.resource.putChild("calendars", self.calendarCollection)
+ self.addressbookCollection = (
+ DirectoryAddressBookHomeProvisioningResource(
+ ds, "/addressbooks/", newStore
+ ))
+ self.site.resource.putChild("addressbooks",
+ self.addressbookCollection)
+
+
+ def configure(self):
+ """
+ Adjust the global configuration for this test.
+ """
+ config.reset()
+
+ config.ServerRoot = os.path.abspath(self.serverRoot)
+ config.ConfigRoot = "config"
+ config.LogRoot = "logs"
+ config.RunRoot = "logs"
+
+ config.Memcached.Pools.Default.ClientEnabled = False
+ config.Memcached.Pools.Default.ServerEnabled = False
+ ClientFactory.allowTestCache = True
+ memcacher.Memcacher.allowTestCache = True
+ memcacher.Memcacher.memoryCacheInstance = None
+ config.DirectoryAddressBook.Enabled = False
+ config.UsePackageTimezones = True
+
+
+
+ def setUp(self):
+ super(TestCase, self).setUp()
+
+ # FIXME: this is only here to workaround circular imports
+ doBind()
+
+ self.serverRoot = self.mktemp()
+ os.mkdir(self.serverRoot)
+
+ self.configure()
+
+ if not os.path.exists(config.DataRoot):
+ os.makedirs(config.DataRoot)
+ if not os.path.exists(config.DocumentRoot):
+ os.makedirs(config.DocumentRoot)
+ if not os.path.exists(config.ConfigRoot):
+ os.makedirs(config.ConfigRoot)
+ if not os.path.exists(config.LogRoot):
+ os.makedirs(config.LogRoot)
+
+
+
+
</ins><span class="cx"> class norequest(object):
</span><span class="cx"> def addResponseFilter(self, filter):
</span><span class="cx"> "stub; ignore me"
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavupgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/upgrade.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/upgrade.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/upgrade.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> import grp
</span><span class="cx"> import shutil
</span><span class="cx"> import errno
</span><del>-import operator
</del><span class="cx"> import time
</span><span class="cx"> from zlib import compress
</span><span class="cx"> from cPickle import loads as unpickle, UnpicklingError
</span><span class="lines">@@ -55,12 +54,18 @@
</span><span class="cx">
</span><span class="cx"> from txdav.caldav.datastore.index_file import db_basename
</span><span class="cx">
</span><del>-from twisted.protocols.amp import AMP, Command, String, Boolean
</del><ins>+# from twisted.protocols.amp import AMP, Command, String, Boolean
</ins><span class="cx">
</span><span class="cx"> from calendarserver.tap.util import getRootResource, FakeRequest
</span><span class="cx">
</span><span class="cx"> from txdav.caldav.datastore.scheduling.imip.mailgateway import migrateTokensToStore
</span><span class="cx">
</span><ins>+from twext.who.idirectory import RecordType
+from txdav.who.idirectory import RecordType as CalRecordType
+from txdav.who.delegates import addDelegate
+
+
+
</ins><span class="cx"> deadPropertyXattrPrefix = namedAny(
</span><span class="cx"> "txdav.base.propertystore.xattr.PropertyStore.deadPropertyXattrPrefix"
</span><span class="cx"> )
</span><span class="lines">@@ -70,6 +75,7 @@
</span><span class="cx">
</span><span class="cx"> log = Logger()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def xattrname(n):
</span><span class="cx"> return deadPropertyXattrPrefix + n
</span><span class="cx">
</span><span class="lines">@@ -144,8 +150,10 @@
</span><span class="cx"> log.warn("Fixing bad quotes in %s" % (resPath,))
</span><span class="cx"> needsRewrite = True
</span><span class="cx"> except Exception, e:
</span><del>- log.error("Error while fixing bad quotes in %s: %s" %
- (resPath, e))
</del><ins>+ log.error(
+ "Error while fixing bad quotes in %s: %s" %
+ (resPath, e)
+ )
</ins><span class="cx"> errorOccurred = True
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="lines">@@ -155,8 +163,10 @@
</span><span class="cx"> log.warn("Removing illegal characters in %s" % (resPath,))
</span><span class="cx"> needsRewrite = True
</span><span class="cx"> except Exception, e:
</span><del>- log.error("Error while removing illegal characters in %s: %s" %
- (resPath, e))
</del><ins>+ log.error(
+ "Error while removing illegal characters in %s: %s" %
+ (resPath, e)
+ )
</ins><span class="cx"> errorOccurred = True
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="lines">@@ -166,8 +176,10 @@
</span><span class="cx"> log.debug("Normalized CUAddrs in %s" % (resPath,))
</span><span class="cx"> needsRewrite = True
</span><span class="cx"> except Exception, e:
</span><del>- log.error("Error while normalizing %s: %s" %
- (resPath, e))
</del><ins>+ log.error(
+ "Error while normalizing %s: %s" %
+ (resPath, e)
+ )
</ins><span class="cx"> errorOccurred = True
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="lines">@@ -236,7 +248,7 @@
</span><span class="cx"> try:
</span><span class="cx"> for attr, value in xattr.xattr(calPath).iteritems():
</span><span class="cx"> if attr == xattrname("{urn:ietf:params:xml:ns:caldav}calendar-free-busy-set"):
</span><del>- value = updateFreeBusySet(value, directory)
</del><ins>+ value = yield updateFreeBusySet(value, directory)
</ins><span class="cx"> if value is not None:
</span><span class="cx"> # Need to write the xattr back to disk
</span><span class="cx"> xattr.setxattr(calPath, attr, value)
</span><span class="lines">@@ -256,40 +268,40 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-class UpgradeOneHome(Command):
- arguments = [('path', String())]
- response = [('succeeded', Boolean())]
</del><ins>+# class UpgradeOneHome(Command):
+# arguments = [('path', String())]
+# response = [('succeeded', Boolean())]
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-class To1Driver(AMP):
- """
- Upgrade driver which runs in the parent process.
- """
</del><ins>+# class To1Driver(AMP):
+# """
+# Upgrade driver which runs in the parent process.
+# """
</ins><span class="cx">
</span><del>- def upgradeHomeInHelper(self, path):
- return self.callRemote(UpgradeOneHome, path=path).addCallback(
- operator.itemgetter("succeeded")
- )
</del><ins>+# def upgradeHomeInHelper(self, path):
+# return self.callRemote(UpgradeOneHome, path=path).addCallback(
+# operator.itemgetter("succeeded")
+# )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-class To1Home(AMP):
- """
- Upgrade worker which runs in dedicated subprocesses.
- """
</del><ins>+# class To1Home(AMP):
+# """
+# Upgrade worker which runs in dedicated subprocesses.
+# """
</ins><span class="cx">
</span><del>- def __init__(self, config):
- super(To1Home, self).__init__()
- self.directory = getDirectory(config)
- self.cuaCache = {}
</del><ins>+# def __init__(self, config):
+# super(To1Home, self).__init__()
+# self.directory = getDirectory(config)
+# self.cuaCache = {}
</ins><span class="cx">
</span><span class="cx">
</span><del>- @UpgradeOneHome.responder
- @inlineCallbacks
- def upgradeOne(self, path):
- result = yield upgradeCalendarHome(path, self.directory, self.cuaCache)
- returnValue(dict(succeeded=result))
</del><ins>+# @UpgradeOneHome.responder
+# @inlineCallbacks
+# def upgradeOne(self, path):
+# result = yield upgradeCalendarHome(path, self.directory, self.cuaCache)
+# returnValue(dict(succeeded=result))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -299,13 +311,14 @@
</span><span class="cx"> Upconvert data from any calendar server version prior to data format 1.
</span><span class="cx"> """
</span><span class="cx"> errorOccurred = []
</span><ins>+
</ins><span class="cx"> def setError(f=None):
</span><span class="cx"> if f is not None:
</span><span class="cx"> log.error(f)
</span><span class="cx"> errorOccurred.append(True)
</span><span class="cx">
</span><span class="cx">
</span><del>- def doProxyDatabaseMoveUpgrade(config, uid= -1, gid= -1):
</del><ins>+ def doProxyDatabaseMoveUpgrade(config, uid=-1, gid=-1):
</ins><span class="cx"> # See if the new one is already present
</span><span class="cx"> oldFilename = ".db.calendaruserproxy"
</span><span class="cx"> newFilename = "proxies.sqlite"
</span><span class="lines">@@ -344,7 +357,7 @@
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def moveCalendarHome(oldHome, newHome, uid= -1, gid= -1):
</del><ins>+ def moveCalendarHome(oldHome, newHome, uid=-1, gid=-1):
</ins><span class="cx"> if os.path.exists(newHome):
</span><span class="cx"> # Both old and new homes exist; stop immediately to let the
</span><span class="cx"> # administrator fix it
</span><span class="lines">@@ -353,8 +366,9 @@
</span><span class="cx"> % (oldHome, newHome)
</span><span class="cx"> )
</span><span class="cx">
</span><del>- makeDirsUserGroup(os.path.dirname(newHome.rstrip("/")), uid=uid,
- gid=gid)
</del><ins>+ makeDirsUserGroup(
+ os.path.dirname(newHome.rstrip("/")), uid=uid, gid=gid
+ )
</ins><span class="cx"> os.rename(oldHome, newHome)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -365,12 +379,15 @@
</span><span class="cx"> service, because in "v1" that's where this info lived.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+ print("FIXME, need to port migrateResourceInfo to twext.who")
+ returnValue(None)
+
</ins><span class="cx"> log.warn("Fetching delegate assignments and auto-schedule settings from directory")
</span><span class="cx"> resourceInfo = directory.getResourceInfo()
</span><span class="cx"> if len(resourceInfo) == 0:
</span><span class="cx"> # Nothing to migrate, or else not appleopendirectory
</span><span class="cx"> log.warn("No resource info found in directory")
</span><del>- return
</del><ins>+ returnValue(None)
</ins><span class="cx">
</span><span class="cx"> log.warn("Found info for %d resources and locations in directory; applying settings" % (len(resourceInfo),))
</span><span class="cx">
</span><span class="lines">@@ -466,20 +483,23 @@
</span><span class="cx"> os.chown(uidHomes, uid, gid)
</span><span class="cx">
</span><span class="cx"> for recordType, dirName in (
</span><del>- (DirectoryService.recordType_users, "users"),
- (DirectoryService.recordType_groups, "groups"),
- (DirectoryService.recordType_locations, "locations"),
- (DirectoryService.recordType_resources, "resources"),
</del><ins>+ (RecordType.user, u"users"),
+ (RecordType.group, u"groups"),
+ (CalRecordType.location, u"locations"),
+ (CalRecordType.resource, u"resources"),
</ins><span class="cx"> ):
</span><span class="cx"> dirPath = os.path.join(calRoot, dirName)
</span><span class="cx"> if os.path.exists(dirPath):
</span><span class="cx"> for shortName in os.listdir(dirPath):
</span><del>- record = directory.recordWithShortName(recordType,
- shortName)
</del><ins>+ record = yield directory.recordWithShortName(
+ recordType, shortName
+ )
</ins><span class="cx"> oldHome = os.path.join(dirPath, shortName)
</span><span class="cx"> if record is not None:
</span><del>- newHome = os.path.join(uidHomes, record.uid[0:2],
- record.uid[2:4], record.uid)
</del><ins>+ newHome = os.path.join(
+ uidHomes, record.uid[0:2],
+ record.uid[2:4], record.uid
+ )
</ins><span class="cx"> moveCalendarHome(oldHome, newHome, uid=uid, gid=gid)
</span><span class="cx"> else:
</span><span class="cx"> # an orphaned calendar home (principal no longer
</span><span class="lines">@@ -549,8 +569,10 @@
</span><span class="cx">
</span><span class="cx"> count += 1
</span><span class="cx"> if count % 10 == 0:
</span><del>- log.warn("Processed calendar home %d of %d"
- % (count, total))
</del><ins>+ log.warn(
+ "Processed calendar home %d of %d"
+ % (count, total)
+ )
</ins><span class="cx"> log.warn("Done processing calendar homes")
</span><span class="cx">
</span><span class="cx"> triggerPath = os.path.join(config.ServerRoot, TRIGGER_FILE)
</span><span class="lines">@@ -584,23 +606,25 @@
</span><span class="cx"> cal = Component.fromString(data)
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def lookupFunction(cuaddr, principalFunction, config):
</del><ins>+ def lookupFunction(cuaddr, recordFunction, config):
</ins><span class="cx">
</span><span class="cx"> # Return cached results, if any.
</span><span class="cx"> if cuaddr in cuaCache:
</span><span class="cx"> returnValue(cuaCache[cuaddr])
</span><span class="cx">
</span><del>- result = yield normalizationLookup(cuaddr, principalFunction, config)
</del><ins>+ result = yield normalizationLookup(cuaddr, recordFunction, config)
</ins><span class="cx">
</span><span class="cx"> # Cache the result
</span><span class="cx"> cuaCache[cuaddr] = result
</span><span class="cx"> returnValue(result)
</span><span class="cx">
</span><del>- yield cal.normalizeCalendarUserAddresses(lookupFunction,
- directory.principalForCalendarUserAddress)
</del><ins>+ yield cal.normalizeCalendarUserAddresses(
+ lookupFunction,
+ directory.recordWithCalendarUserAddress
+ )
</ins><span class="cx">
</span><span class="cx"> newData = str(cal)
</span><del>- returnValue(newData, not newData == data)
</del><ins>+ returnValue((newData, not newData == data))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -709,6 +733,7 @@
</span><span class="cx"> raise UpgradeError("Data upgrade failed, see error.log for details")
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> # The on-disk version number (which defaults to zero if .calendarserver_version
</span><span class="cx"> # doesn't exist), is compared with each of the numbers in the upgradeMethods
</span><span class="cx"> # array. If it is less than the number, the associated method is called.
</span><span class="lines">@@ -718,17 +743,17 @@
</span><span class="cx"> (2, upgrade_to_2),
</span><span class="cx"> ]
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><del>-def upgradeData(config):
</del><ins>+def upgradeData(config, directory):
</ins><span class="cx">
</span><del>- directory = getDirectory()
</del><span class="cx">
</span><span class="cx"> triggerPath = os.path.join(config.ServerRoot, TRIGGER_FILE)
</span><span class="cx"> if os.path.exists(triggerPath):
</span><span class="cx"> try:
</span><span class="cx"> # Migrate locations/resources now because upgrade_to_1 depends
</span><span class="cx"> # on them being in resources.xml
</span><del>- (yield migrateFromOD(config, directory))
</del><ins>+ yield migrateFromOD(config, directory)
</ins><span class="cx"> except Exception, e:
</span><span class="cx"> raise UpgradeError("Unable to migrate locations and resources from OD: %s" % (e,))
</span><span class="cx">
</span><span class="lines">@@ -746,11 +771,15 @@
</span><span class="cx"> with open(versionFilePath) as versionFile:
</span><span class="cx"> onDiskVersion = int(versionFile.read().strip())
</span><span class="cx"> except IOError:
</span><del>- log.error("Cannot open %s; skipping migration" %
- (versionFilePath,))
</del><ins>+ log.error(
+ "Cannot open %s; skipping migration" %
+ (versionFilePath,)
+ )
</ins><span class="cx"> except ValueError:
</span><del>- log.error("Invalid version number in %s; skipping migration" %
- (versionFilePath,))
</del><ins>+ log.error(
+ "Invalid version number in %s; skipping migration" %
+ (versionFilePath,)
+ )
</ins><span class="cx">
</span><span class="cx"> uid, gid = getCalendarServerIDs(config)
</span><span class="cx">
</span><span class="lines">@@ -780,26 +809,28 @@
</span><span class="cx"> #
</span><span class="cx"> # Utility functions
</span><span class="cx"> #
</span><ins>+@inlineCallbacks
</ins><span class="cx"> def updateFreeBusyHref(href, directory):
</span><span class="cx"> pieces = href.split("/")
</span><span class="cx"> if pieces[2] == "__uids__":
</span><span class="cx"> # Already updated
</span><del>- return None
</del><ins>+ returnValue(None)
</ins><span class="cx">
</span><span class="cx"> recordType = pieces[2]
</span><span class="cx"> shortName = pieces[3]
</span><del>- record = directory.recordWithShortName(recordType, shortName)
</del><ins>+ record = yield directory.recordWithShortName(recordType, shortName)
</ins><span class="cx"> if record is None:
</span><span class="cx"> # We will simply ignore this and not write out an fb-set entry
</span><span class="cx"> log.error("Can't update free-busy href; %s is not in the directory" % shortName)
</span><del>- return ""
</del><ins>+ returnValue("")
</ins><span class="cx">
</span><span class="cx"> uid = record.uid
</span><span class="cx"> newHref = "/calendars/__uids__/%s/%s/" % (uid, pieces[4])
</span><del>- return newHref
</del><ins>+ returnValue(newHref)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><ins>+@inlineCallbacks
</ins><span class="cx"> def updateFreeBusySet(value, directory):
</span><span class="cx">
</span><span class="cx"> try:
</span><span class="lines">@@ -816,14 +847,13 @@
</span><span class="cx"> freeBusySet = unpickle(value)
</span><span class="cx"> except UnpicklingError:
</span><span class="cx"> log.error("Invalid free/busy property value")
</span><del>- # MOR: continue on?
- return None
</del><ins>+ returnValue(None)
</ins><span class="cx">
</span><span class="cx"> fbset = set()
</span><span class="cx"> didUpdate = False
</span><span class="cx"> for href in freeBusySet.children:
</span><span class="cx"> href = str(href)
</span><del>- newHref = updateFreeBusyHref(href, directory)
</del><ins>+ newHref = yield updateFreeBusyHref(href, directory)
</ins><span class="cx"> if newHref is None:
</span><span class="cx"> fbset.add(href)
</span><span class="cx"> else:
</span><span class="lines">@@ -832,18 +862,19 @@
</span><span class="cx"> fbset.add(newHref)
</span><span class="cx">
</span><span class="cx"> if didUpdate:
</span><del>- property = caldavxml.CalendarFreeBusySet(*[element.HRef(href)
- for href in fbset])
</del><ins>+ property = caldavxml.CalendarFreeBusySet(
+ *[element.HRef(href) for href in fbset]
+ )
</ins><span class="cx"> value = compress(property.toxml())
</span><del>- return value
</del><ins>+ returnValue(value)
</ins><span class="cx">
</span><del>- return None # no update required
</del><ins>+ returnValue(None) # no update required
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-def makeDirsUserGroup(path, uid= -1, gid= -1):
</del><ins>+def makeDirsUserGroup(path, uid=-1, gid=-1):
</ins><span class="cx"> parts = path.split("/")
</span><del>- if parts[0] == "": # absolute path
</del><ins>+ if parts[0] == "": # absolute path
</ins><span class="cx"> parts[0] = "/"
</span><span class="cx">
</span><span class="cx"> path = ""
</span><span class="lines">@@ -888,6 +919,8 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> DELETECHARS = ''.join(chr(i) for i in xrange(32) if i not in (9, 10, 13))
</span><ins>+
+
</ins><span class="cx"> def removeIllegalCharacters(data):
</span><span class="cx"> """
</span><span class="cx"> Remove all characters below ASCII 32 except HTAB, LF and CR
</span><span class="lines">@@ -906,7 +939,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> # # Deferred
</span><del>-# def migrateFromOD(config, directory):
</del><ins>+def migrateFromOD(config, directory):
+ # FIXME:
+ print("STILL NEED TO IMPLEMENT migrateFromOD")
+ return succeed(None)
</ins><span class="cx"> # #
</span><span class="cx"> # # Migrates locations and resources from OD
</span><span class="cx"> # #
</span><span class="lines">@@ -937,7 +973,14 @@
</span><span class="cx"> def migrateAutoSchedule(config, directory):
</span><span class="cx"> # Fetch the autoSchedule assignments from resourceinfo.sqlite and store
</span><span class="cx"> # the values in augments
</span><del>- augmentService = directory.augmentService
</del><ins>+ augmentService = None
+ if config.AugmentService.type:
+ augmentClass = namedClass(config.AugmentService.type)
+ try:
+ augmentService = augmentClass(**config.AugmentService.params)
+ except:
+ log.error("Could not start augment service")
+
</ins><span class="cx"> if augmentService:
</span><span class="cx"> augmentRecords = []
</span><span class="cx"> dbPath = os.path.join(config.DataRoot, ResourceInfoDatabase.dbFilename)
</span><span class="lines">@@ -947,11 +990,18 @@
</span><span class="cx"> results = resourceInfoDatabase._db_execute(
</span><span class="cx"> "select GUID, AUTOSCHEDULE from RESOURCEINFO"
</span><span class="cx"> )
</span><del>- for guid, autoSchedule in results:
- record = directory.recordWithGUID(guid)
</del><ins>+ for uid, autoSchedule in results:
+ record = yield directory.recordWithUID(uid)
</ins><span class="cx"> if record is not None:
</span><del>- augmentRecord = (yield augmentService.getAugmentRecord(guid, record.recordType))
- augmentRecord.autoSchedule = autoSchedule
</del><ins>+ augmentRecord = (
+ yield augmentService.getAugmentRecord(
+ uid,
+ directory.recordTypeToOldName(record.recordType)
+ )
+ )
+ augmentRecord.autoScheduleMode = (
+ "automatic" if autoSchedule else "default"
+ )
</ins><span class="cx"> augmentRecords.append(augmentRecord)
</span><span class="cx">
</span><span class="cx"> if augmentRecords:
</span><span class="lines">@@ -959,17 +1009,68 @@
</span><span class="cx"> log.warn("Migrated %d auto-schedule settings" % (len(augmentRecords),))
</span><span class="cx">
</span><span class="cx">
</span><ins>+@inlineCallbacks
+def migrateDelegatesToStore(config, store):
+ """
+ If there is an sqlite file of delegates, migrate them into the store.
+ """
+ if config.ProxyDBService.type != "twistedcaldav.directory.calendaruserproxy.ProxySqliteDB":
+ returnValue(None)
</ins><span class="cx">
</span><ins>+ dbPath = os.path.join(config.DataRoot, config.ProxyDBService.params.dbpath)
+ if not os.path.exists(dbPath):
+ returnValue(None)
+
+ proxyClass = namedClass(config.ProxyDBService.type)
+ try:
+ proxyService = proxyClass(**config.ProxyDBService.params)
+ except:
+ log.error("Could not migrate delegates to store")
+ returnValue(None)
+
+ yield _migrateDelegatesToStore(proxyService, store)
+ os.remove(dbPath)
+
+
+@inlineCallbacks
+def _migrateDelegatesToStore(oldProxyService, store):
+ directory = store.directoryService()
+ txn = store.newTransaction()
+ for groupName, memberUID in (
+ yield oldProxyService.query(
+ "select GROUPNAME, MEMBER from GROUPS"
+ )
+ ):
+ if "#" not in groupName:
+ continue
+
+ delegatorUID, groupType = groupName.split("#")
+ delegatorRecord = yield directory.recordWithUID(delegatorUID)
+ if delegatorRecord is None:
+ continue
+
+ delegateRecord = yield directory.recordWithUID(memberUID)
+ if delegateRecord is None:
+ continue
+
+ readWrite = (groupType == "calendar-proxy-write")
+ yield addDelegate(txn, delegatorRecord, delegateRecord, readWrite)
+
+ yield txn.commit()
+
+
+
</ins><span class="cx"> class UpgradeFileSystemFormatStep(object):
</span><span class="cx"> """
</span><span class="cx"> Upgrade filesystem from previous versions.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def __init__(self, config):
</del><ins>+ def __init__(self, config, store):
</ins><span class="cx"> """
</span><span class="cx"> Initialize the service.
</span><span class="cx"> """
</span><span class="cx"> self.config = config
</span><ins>+ self.store = store
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="lines">@@ -986,7 +1087,7 @@
</span><span class="cx"> memcacheEnabled = self.config.Memcached.Pools.Default.ClientEnabled
</span><span class="cx"> self.config.Memcached.Pools.Default.ClientEnabled = False
</span><span class="cx">
</span><del>- yield upgradeData(self.config)
</del><ins>+ yield upgradeData(self.config, self.store.directoryService())
</ins><span class="cx">
</span><span class="cx"> # Restore memcached client setting
</span><span class="cx"> self.config.Memcached.Pools.Default.ClientEnabled = memcacheEnabled
</span><span class="lines">@@ -998,9 +1099,7 @@
</span><span class="cx"> """
</span><span class="cx"> Execute the step.
</span><span class="cx"> """
</span><del>- return succeed(None)
- # MOVE2WHO
- # return self.doUpgrade()
</del><ins>+ return self.doUpgrade()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1013,6 +1112,8 @@
</span><span class="cx">
</span><span class="cx"> 1. Populating the group-membership cache
</span><span class="cx"> 2. Processing non-implicit inbox items
</span><ins>+ 3. Migrate IMIP tokens into the store
+ 4. Migrating delegate assignments into the store
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, store, config, doPostImport):
</span><span class="lines">@@ -1028,7 +1129,7 @@
</span><span class="cx"> def stepWithResult(self, result):
</span><span class="cx"> if self.doPostImport:
</span><span class="cx">
</span><del>- directory = self.store.directoryService()
</del><ins>+ # directory = self.store.directoryService()
</ins><span class="cx">
</span><span class="cx"> # Load proxy assignments from XML if specified
</span><span class="cx"> if self.config.ProxyLoadFromFile:
</span><span class="lines">@@ -1069,7 +1170,10 @@
</span><span class="cx"> # Migrate mail tokens from sqlite to store
</span><span class="cx"> yield migrateTokensToStore(self.config.DataRoot, self.store)
</span><span class="cx">
</span><ins>+ # Migrate delegate assignments from sqlite to store
+ yield migrateDelegatesToStore(self.config, self.store)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def processInboxItems(self):
</span><span class="cx"> """
</span><span class="lines">@@ -1106,14 +1210,14 @@
</span><span class="cx"> inboxItems.remove(inboxItem)
</span><span class="cx"> continue
</span><span class="cx">
</span><del>- record = directory.recordWithUID(uuid)
</del><ins>+ record = yield directory.recordWithUID(uuid)
</ins><span class="cx"> if record is None:
</span><span class="cx"> log.debug("Ignored inbox item - no record: %s" % (inboxItem,))
</span><span class="cx"> inboxItems.remove(inboxItem)
</span><span class="cx"> ignoreUUIDs.add(uuid)
</span><span class="cx"> continue
</span><span class="cx">
</span><del>- principal = principalCollection.principalForRecord(record)
</del><ins>+ principal = yield principalCollection.principalForRecord(record)
</ins><span class="cx"> if principal is None or not isinstance(principal, DirectoryCalendarPrincipalResource):
</span><span class="cx"> log.debug("Ignored inbox item - no principal: %s" % (inboxItem,))
</span><span class="cx"> inboxItems.remove(inboxItem)
</span><span class="lines">@@ -1121,7 +1225,7 @@
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="cx"> request = FakeRequest(root, "PUT", None)
</span><del>- request.noAttendeeRefresh = True # tell scheduling to skip refresh
</del><ins>+ request.noAttendeeRefresh = True # tell scheduling to skip refresh
</ins><span class="cx"> request.checkedSACL = True
</span><span class="cx"> request.authnUser = request.authzUser = element.Principal(
</span><span class="cx"> element.HRef.fromString("/principals/__uids__/%s/" % (uuid,))
</span><span class="lines">@@ -1160,8 +1264,10 @@
</span><span class="cx"> uri
</span><span class="cx"> )
</span><span class="cx"> except Exception, e:
</span><del>- log.error("Error processing inbox item: %s (%s)"
- % (inboxItem, e))
</del><ins>+ log.error(
+ "Error processing inbox item: %s (%s)"
+ % (inboxItem, e)
+ )
</ins><span class="cx"> else:
</span><span class="cx"> log.debug("Ignored inbox item - no resource: %s" % (inboxItem,))
</span><span class="cx"> else:
</span><span class="lines">@@ -1198,8 +1304,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def processInboxItem(self, root, directory, principal, request, inbox,
- inboxItem, uuid, uri):
</del><ins>+ def processInboxItem(
+ self, root, directory, principal, request, inbox,
+ inboxItem, uuid, uri
+ ):
</ins><span class="cx"> """
</span><span class="cx"> Run an individual inbox item through implicit scheduling and remove
</span><span class="cx"> the inbox item.
</span><span class="lines">@@ -1211,8 +1319,10 @@
</span><span class="cx">
</span><span class="cx"> ownerPrincipal = principal
</span><span class="cx"> cua = "urn:uuid:%s" % (uuid,)
</span><del>- owner = LocalCalendarUser(cua, ownerPrincipal,
- inbox, ownerPrincipal.scheduleInboxURL())
</del><ins>+ owner = LocalCalendarUser(
+ cua, ownerPrincipal,
+ inbox, ownerPrincipal.scheduleInboxURL()
+ )
</ins><span class="cx">
</span><span class="cx"> calendar = yield inboxItem.iCalendar()
</span><span class="cx"> if calendar.mainType() is not None:
</span><span class="lines">@@ -1230,14 +1340,16 @@
</span><span class="cx"> originator = calendar.getOrganizer()
</span><span class="cx">
</span><span class="cx"> principalCollection = directory.principalCollection
</span><del>- originatorPrincipal = principalCollection.principalForCalendarUserAddress(originator)
</del><ins>+ originatorPrincipal = yield principalCollection.principalForCalendarUserAddress(originator)
</ins><span class="cx"> originator = LocalCalendarUser(originator, originatorPrincipal)
</span><span class="cx"> recipients = (owner,)
</span><span class="cx">
</span><span class="cx"> scheduler = DirectScheduler(request, inboxItem)
</span><span class="cx"> # Process inbox item
</span><del>- yield scheduler.doSchedulingViaPUT(originator, recipients, calendar,
- internal_request=False, noAttendeeRefresh=True)
</del><ins>+ yield scheduler.doSchedulingViaPUT(
+ originator, recipients, calendar,
+ internal_request=False, noAttendeeRefresh=True
+ )
</ins><span class="cx"> else:
</span><span class="cx"> log.warn("Removing invalid inbox item: %s" % (uri,))
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/util.py (12993 => 12994)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/util.py        2014-03-25 16:55:29 UTC (rev 12993)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/util.py        2014-03-25 21:34:44 UTC (rev 12994)
</span><span class="lines">@@ -505,26 +505,25 @@
</span><span class="cx"> principal for the cuaddr.
</span><span class="cx"> """
</span><span class="cx"> try:
</span><del>- principal = yield principalFunction(cuaddr)
</del><ins>+ record = yield principalFunction(cuaddr)
</ins><span class="cx"> except Exception, e:
</span><span class="cx"> log.debug("Lookup of %s failed: %s" % (cuaddr, e))
</span><del>- principal = None
</del><ins>+ record = None
</ins><span class="cx">
</span><del>- if principal is None:
</del><ins>+ if record is None:
</ins><span class="cx"> returnValue((None, None, None))
</span><span class="cx"> else:
</span><del>- rec = principal.record
</del><span class="cx">
</span><span class="cx"> # RFC5545 syntax does not allow backslash escaping in
</span><span class="cx"> # parameter values. A double-quote is thus not allowed
</span><span class="cx"> # in a parameter value except as the start/end delimiters.
</span><span class="cx"> # Single quotes are allowed, so we convert any double-quotes
</span><span class="cx"> # to single-quotes.
</span><del>- fullName = rec.fullName.replace('"', "'")
</del><ins>+ fullName = record.displayName.replace('"', "'")
</ins><span class="cx">
</span><del>- cuas = principal.record.calendarUserAddresses()
</del><ins>+ cuas = record.calendarUserAddresses
</ins><span class="cx">
</span><del>- returnValue((fullName, rec.guid, cuas))
</del><ins>+ returnValue((fullName, record.uid, cuas))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>