<!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>[4508] CalendarServer/branches/more-deferreds-3</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.macosforge.org/projects/calendarserver/changeset/4508">4508</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2009-08-26 10:42:05 -0700 (Wed, 26 Aug 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>Checkpoint -- deadProperty access is deferred; all but 3 twisted unit tests pass</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedapplicationapppatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.application.app.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedmailimap4patch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.mail.imap4.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedpythonutilpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.python.util.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2authdigestpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.auth.digest.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davmethodreportpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.report.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davresourcepatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.resource.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davstaticpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.static.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_resourcepatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_resource.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davxattrpropspatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2errorpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.error.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2serverpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.server.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2staticpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.static.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavdirectorycalendarpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/directory/calendar.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmailpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/mail.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmemcachepropspy">CalendarServer/branches/more-deferreds-3/twistedcaldav/memcacheprops.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethoddelete_commonpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/delete_common.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethodgetpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/get.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethodmkcalendarpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/mkcalendar.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethodput_commonpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/put_common.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethodreport_calquerypy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_calquery.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavmethodreport_commonpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_common.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavresourcepy">CalendarServer/branches/more-deferreds-3/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavstaticpy">CalendarServer/branches/more-deferreds-3/twistedcaldav/static.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavtesttest_memcachepropspy">CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_memcacheprops.py</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3twistedcaldavtesttest_resourcepy">CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_resource.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davauthpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.auth.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davmethodput_commonpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.put_common.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davnonepropspatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.noneprops.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_aclpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_acl.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_copypatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_copy.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_deletepatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_delete.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_mkcolpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_mkcol.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_movepatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_move.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_optionspatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_options.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_proppatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_prop.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_putpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_put.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_quotapatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_quota.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_reportpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_report.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_staticpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_static.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_xattrpropspatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_xattrprops.patch</a></li>
<li><a href="#CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtestutilpatch">CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.util.patch</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedapplicationapppatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.application.app.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.application.app.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.application.app.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/application/app.py'
---- twisted/application/app.py        2008-12-14 22:09:07 +0000
-+++ twisted/application/app.py        2009-07-15 23:30:17 +0000
</del><ins>+Index: twisted/application/app.py
+===================================================================
+--- twisted/application/app.py        (revision 26969)
++++ twisted/application/app.py        (working copy)
</ins><span class="cx"> @@ -241,7 +241,11 @@
</span><span class="cx">          @param application: The application on which to check for an
</span><span class="cx">              L{ILogObserver}.
</span><span class="lines">@@ -14,24 +15,25 @@
</span><span class="cx">  
</span><span class="cx">          if observer is None:
</span><span class="cx">              observer = self._getLogObserver()
</span><del>-@@ -408,8 +412,6 @@
</del><ins>+@@ -408,9 +412,7 @@
</ins><span class="cx">          Run the application.
</span><span class="cx">          &quot;&quot;&quot;
</span><span class="cx">          self.preApplication()
</span><span class="cx"> -        self.application = self.createOrGetApplication()
</span><ins>+ 
</ins><span class="cx"> -
</span><del>- 
</del><span class="cx">          getLogObserverLegacy = getattr(self, 'getLogObserver', None)
</span><span class="cx">          if getLogObserverLegacy is not None:
</span><del>-@@ -418,7 +420,9 @@
</del><ins>+             warnings.warn(&quot;Specifying a log observer with getLogObserver is &quot;
+@@ -418,8 +420,10 @@
</ins><span class="cx">                            category=DeprecationWarning)
</span><span class="cx">              self.startLogging(self.getLogObserver())
</span><span class="cx">          else:
</span><span class="cx"> -            self.logger.start(self.application)
</span><span class="cx"> +            self.logger.start(None)
</span><ins>+ 
++        self.application = self.createOrGetApplication()
</ins><span class="cx"> +
</span><del>-+        self.application = self.createOrGetApplication()

</del><span class="cx">          self.postApplication()
</span><span class="cx">          self.logger.stop()
</span><del>-
</del><ins>+ 
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedmailimap4patch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.mail.imap4.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.mail.imap4.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.mail.imap4.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/mail/imap4.py'
---- twisted/mail/imap4.py        2009-03-23 11:02:59 +0000
-+++ twisted/mail/imap4.py        2009-07-15 23:30:17 +0000
</del><ins>+Index: twisted/mail/imap4.py
+===================================================================
+--- twisted/mail/imap4.py        (revision 26969)
++++ twisted/mail/imap4.py        (working copy)
</ins><span class="cx"> @@ -333,7 +333,7 @@
</span><span class="cx">  
</span><span class="cx">  
</span><span class="lines">@@ -19,4 +20,3 @@
</span><span class="cx">  
</span><span class="cx">  
</span><span class="cx">  class MailboxException(IMAP4Exception): pass
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedpythonutilpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.python.util.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.python.util.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.python.util.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,7 +1,8 @@
</span><del>-=== modified file 'twisted/python/util.py'
---- twisted/python/util.py        2009-03-30 13:33:33 +0000
-+++ twisted/python/util.py        2009-07-15 23:30:18 +0000
-@@ -569,7 +569,27 @@
</del><ins>+Index: twisted/python/util.py
+===================================================================
+--- twisted/python/util.py        (revision 26969)
++++ twisted/python/util.py        (working copy)
+@@ -569,9 +569,29 @@
</ins><span class="cx">      L2.sort()
</span><span class="cx">      return [e[2] for e in L2]
</span><span class="cx">  
</span><span class="lines">@@ -17,8 +18,8 @@
</span><span class="cx"> +if sys.platform == &quot;darwin&quot; and hasCtypes:
</span><span class="cx"> +    import pwd
</span><span class="cx"> +    libc = cdll.LoadLibrary(find_library(&quot;libc&quot;))
</span><del>-+    def initgroups(uid, primaryGid):
-+        &quot;&quot;&quot;
</del><ins>+     def initgroups(uid, primaryGid):
+         &quot;&quot;&quot;
</ins><span class="cx"> +        Call initgroups with ctypes.
</span><span class="cx"> +        &quot;&quot;&quot;
</span><span class="cx"> +        c_gid = c_int(primaryGid)
</span><span class="lines">@@ -27,7 +28,8 @@
</span><span class="cx"> +        return libc.initgroups(c_username, c_gid)
</span><span class="cx"> +
</span><span class="cx"> +elif pwd is None or grp is None or setgroups is None or getgroups is None:
</span><del>-     def initgroups(uid, primaryGid):
-         &quot;&quot;&quot;
</del><ins>++    def initgroups(uid, primaryGid):
++        &quot;&quot;&quot;
</ins><span class="cx">          Do nothing.
</span><del>-
</del><ins>+ 
+         Underlying platform support require to manipulate groups is missing.
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2authdigestpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.auth.digest.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.auth.digest.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.auth.digest.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/web2/auth/digest.py'
---- twisted/web2/auth/digest.py        2009-04-20 17:38:06 +0000
-+++ twisted/web2/auth/digest.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/auth/digest.py
+===================================================================
+--- twisted/web2/auth/digest.py        (revision 26969)
++++ twisted/web2/auth/digest.py        (working copy)
</ins><span class="cx"> @@ -138,11 +138,15 @@
</span><span class="cx">      implements(credentials.IUsernameHashedPassword,
</span><span class="cx">                 IUsernameDigestHash)
</span><span class="lines">@@ -18,7 +19,7 @@
</span><span class="cx">  
</span><span class="cx">      def checkPassword(self, password):
</span><span class="cx">          response = self.fields.get('response')
</span><del>-@@ -155,10 +159,22 @@
</del><ins>+@@ -155,11 +159,23 @@
</ins><span class="cx">  
</span><span class="cx">          expected = calcResponse(
</span><span class="cx">              calcHA1(algo, self.username, self.realm, password, nonce, cnonce),
</span><span class="lines">@@ -29,7 +30,7 @@
</span><span class="cx"> -        return expected == response
</span><span class="cx"> +        if expected == response:
</span><span class="cx"> +            return True
</span><del>-+
</del><ins>+ 
</ins><span class="cx"> +        # IE7 sends cnonce and nc values, but auth fails if they are used.
</span><span class="cx"> +        # So try again without them...
</span><span class="cx"> +        # They can be omitted for backwards compatibility [RFC 2069].
</span><span class="lines">@@ -40,9 +41,10 @@
</span><span class="cx"> +            )
</span><span class="cx"> +            if expected == response:
</span><span class="cx"> +                return True
</span><del>- 
</del><ins>++
</ins><span class="cx">      def checkHash(self, digestHash):
</span><span class="cx">          response = self.fields.get('response')
</span><ins>+         uri = self.fields.get('uri')
</ins><span class="cx"> @@ -171,7 +187,7 @@
</span><span class="cx">  
</span><span class="cx">          expected = calcResponse(
</span><span class="lines">@@ -78,4 +80,3 @@
</span><span class="cx"> +                                               self.realm,
</span><span class="cx"> +                                               auth,
</span><span class="cx"> +                                               originalMethod))
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davauthpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.auth.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.auth.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.auth.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+Index: twisted/web2/dav/auth.py
+===================================================================
+--- twisted/web2/dav/auth.py        (revision 26969)
++++ twisted/web2/dav/auth.py        (working copy)
+@@ -90,14 +90,18 @@
+         else:
+             raise error.UnauthorizedLogin(&quot;Bad credentials for: %s&quot; % (principalURIs[0],))

+-    def requestAvatarId(self, credentials):
+-        pcreds = IPrincipalCredentials(credentials)
+-        pswd = str(pcreds.authnPrincipal.readDeadProperty(TwistedPasswordProperty))
+-
++    def _cbReadDeadProperty(self, result, credentials, pcreds):
++        pswd = str(result)
+         d = defer.maybeDeferred(credentials.checkPassword, pswd)
+         d.addCallback(self._cbPasswordMatch, (pcreds.authnPrincipal.principalURL(), pcreds.authzPrincipal.principalURL()))
+         return d

++    def requestAvatarId(self, credentials):
++        pcreds = IPrincipalCredentials(credentials)
++        d = pcreds.authnPrincipal.readDeadProperty(TwistedPasswordProperty)
++        d.addCallback(self._cbReadDeadProperty, credentials, pcreds)
++        return d
++
+ ##
+ # Utilities
+ ##
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davmethodput_commonpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.put_common.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.put_common.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.put_common.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+Index: twisted/web2/dav/method/put_common.py
+===================================================================
+--- twisted/web2/dav/method/put_common.py        (revision 26969)
++++ twisted/web2/dav/method/put_common.py        (working copy)
+@@ -208,20 +208,31 @@
+         # Update the MD5 value on the resource
+         if source is not None:
+             # Copy MD5 value from source to destination
+-            if source.hasDeadProperty(TwistedGETContentMD5):
+-                md5 = source.readDeadProperty(TwistedGETContentMD5)
+-                destination.writeDeadProperty(md5)
++            hasDeadProperty = waitForDeferred(source.hasDeadProperty(TwistedGETContentMD5))
++            yield hasDeadProperty
++            hasDeadProperty = hasDeadProperty.getResult()
++            if hasDeadProperty:
++                md5 = waitForDeferred(source.readDeadProperty(TwistedGETContentMD5))
++                yield md5
++                md5 = md5.getResult()
++                ignore = waitForDeferred(destination.writeDeadProperty(md5))
++                yield ignore
++                ignore = ignore.getResult( )
+         else:
+             # Finish MD5 calc and write dead property
+             md5.close()
+             md5 = md5.getMD5()
+-            destination.writeDeadProperty(TwistedGETContentMD5.fromString(md5))
++            ignore = waitForDeferred(destination.writeDeadProperty(TwistedGETContentMD5.fromString(md5)))
++            yield ignore
++            ignore = ignore.getResult( )

+         # Update the content-type value on the resource if it is not been copied or moved
+         if source is None:
+             content_type = request.headers.getHeader(&quot;content-type&quot;)
+             if content_type is not None:
+-                destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(content_type)))
++                ignore = destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(content_type)))
++                yield ignore
++                ignore = ignore.getResult( )

+         response = IResponse(response)
+         
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davmethodreportpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.report.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.report.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.method.report.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/web2/dav/method/report.py'
---- twisted/web2/dav/method/report.py        2009-04-20 17:38:06 +0000
-+++ twisted/web2/dav/method/report.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/dav/method/report.py
+===================================================================
+--- twisted/web2/dav/method/report.py        (revision 26969)
++++ twisted/web2/dav/method/report.py        (working copy)
</ins><span class="cx"> @@ -94,8 +94,9 @@
</span><span class="cx">      namespace = doc.root_element.namespace
</span><span class="cx">      name = doc.root_element.name
</span><span class="lines">@@ -31,4 +32,3 @@
</span><span class="cx">      try:
</span><span class="cx">          method = getattr(self, method_name)
</span><span class="cx">          
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davnonepropspatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.noneprops.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.noneprops.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.noneprops.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+Index: twisted/web2/dav/noneprops.py
+===================================================================
+--- twisted/web2/dav/noneprops.py        (revision 26969)
++++ twisted/web2/dav/noneprops.py        (working copy)
+@@ -33,6 +33,8 @@

+ from twisted.web2 import responsecode
+ from twisted.web2.http import HTTPError, StatusResponse
++from twisted.python.failure import Failure
++from twisted.internet.defer import succeed

+ class NonePropertyStore (object):
+     &quot;&quot;&quot;
+@@ -50,18 +52,18 @@
+         pass

+     def get(self, qname):
+-        raise HTTPError(StatusResponse(responsecode.NOT_FOUND, &quot;No such property: {%s}%s&quot; % qname))
++        return Failure(HTTPError(StatusResponse(responsecode.NOT_FOUND, &quot;No such property: {%s}%s&quot; % qname)))

+     def set(self, property):
+-        raise HTTPError(StatusResponse(responsecode.FORBIDDEN, &quot;Permission denied for setting property: %s&quot; % (property,)))
++        return Failure(HTTPError(StatusResponse(responsecode.FORBIDDEN, &quot;Permission denied for setting property: %s&quot; % (property,))))

+     def delete(self, qname):
+         # RFC 2518 Section 12.13.1 says that removal of
+         # non-existing property is not an error.
+-        pass
++        return succeed(None)

+     def contains(self, qname):
+-        return False
++        return succeed(False)

+     def list(self):
+-        return ()
++        return succeed( () )
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davresourcepatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.resource.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.resource.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.resource.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/web2/dav/resource.py'
---- twisted/web2/dav/resource.py        2009-05-07 20:35:07 +0000
-+++ twisted/web2/dav/resource.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/dav/resource.py
+===================================================================
+--- twisted/web2/dav/resource.py        (revision 26969)
++++ twisted/web2/dav/resource.py        (working copy)
</ins><span class="cx"> @@ -49,12 +49,14 @@
</span><span class="cx">  if not hasattr(__builtin__, &quot;frozenset&quot;):
</span><span class="cx">      import sets.ImmutableSet as frozenset
</span><span class="lines">@@ -18,15 +19,197 @@
</span><span class="cx">  from twisted.internet import reactor
</span><span class="cx">  from twisted.web2 import responsecode
</span><span class="cx">  from twisted.web2.http import HTTPError, RedirectResponse, StatusResponse
</span><del>-@@ -578,7 +580,6 @@
</del><ins>+@@ -186,9 +188,15 @@
+                 d = self.hasQuota(request)
+                 d.addCallback(lambda result: result)
+                 return d
+-        
+-        return succeed(qname in self.liveProperties or self.deadProperties().contains(qname))
</ins><span class="cx">  
</span><ins>++        if qname in self.liveProperties:
++            return succeed(True)
++
++        d = self.deadProperties().contains(qname)
++        d.addCallback(lambda result: result)
++        return d
++        # return succeed(qname in self.liveProperties or self.deadProperties().contains(qname))
++
+     def readProperty(self, property, request):
+         &quot;&quot;&quot;
+         See L{IDAVResource.readProperty}.
+@@ -206,24 +214,43 @@
+             if namespace == dav_namespace:
+                 if name == &quot;resourcetype&quot;:
+                     # Allow live property to be overriden by dead property
+-                    if self.deadProperties().contains(qname):
+-                        return self.deadProperties().get(qname)
+-                    if self.isCollection():
+-                        return davxml.ResourceType.collection
+-                    return davxml.ResourceType.empty
++                    def callback(result):
++                        if result:
++                            return self.deadProperties().get(qname)
++                        else:
++                            if self.isCollection():
++                                return davxml.ResourceType.collection
++                            return davxml.ResourceType.empty

++                    d = self.deadProperties().contains(qname)
++                    d.addCallback(callback)
++                    return d
++
+                 if name == &quot;getetag&quot;:
+-                    etag = self.etag()
+-                    if etag is None:
+-                        return None
+-                    return davxml.GETETag(etag.generate())
++                    def etagCallback(result):
++                        if result is None:
++                            return None
++                        return davxml.GETETag(result.generate())

++                    d = self.etag()
++                    d.addCallback(etagCallback)
++                    return d
++
++                    # etag = self.etag()
++                    # if etag is None:
++                    #     return None
++                    # return davxml.GETETag(etag.generate())
++
+                 if name == &quot;getcontenttype&quot;:
+-                    mimeType = self.contentType()
+-                    if mimeType is None:
+-                        return None
+-                    return davxml.GETContentType(generateContentType(mimeType))
++                    def contentTypeCallback(result):
++                        if result is None:
++                            return None
++                        return davxml.GETContentType(generateContentType(result))
++                    d = self.contentType()
++                    d.addCallback(contentTypeCallback)
++                    return d

++
+                 if name == &quot;getcontentlength&quot;:
+                     length = self.contentLength()
+                     if length is None:
+@@ -247,11 +274,15 @@
+                     return davxml.CreationDate.fromDate(creationDate)

+                 if name == &quot;displayname&quot;:
+-                    displayName = self.displayName()
+-                    if displayName is None:
+-                        return None
+-                    return davxml.DisplayName(displayName)
++                    def displaynameCallback(result):
++                        if result is None:
++                            return None
++                        return davxml.DisplayName(result)

++                    d = self.displayName()
++                    d.addCallback(displaynameCallback)
++                    return d
++
+                 if name == &quot;supportedlock&quot;:
+                     return davxml.SupportedLock(
+                         davxml.LockEntry(davxml.LockScope.exclusive, davxml.LockType.write),
+@@ -426,7 +457,10 @@
+             if not has:
+                 qnames.remove(dqname)

+-        for qname in self.deadProperties().list():
++        qnamesList = waitForDeferred(self.deadProperties().list())
++        yield qnamesList
++        qnamesList = qnamesList.getResult()
++        for qname in qnamesList:
+             if (qname not in qnames) and (qname[0] != twisted_private_namespace):
+                 qnames.add(qname)

+@@ -495,37 +529,54 @@
+         in the dead property store may or may not be ignored when reading the
+         property with L{readProperty}.
+         &quot;&quot;&quot;
+-        self.deadProperties().set(property)
++        return self.deadProperties().set(property)

+     def removeDeadProperty(self, property):
+         &quot;&quot;&quot;
+         Same as L{removeProperty}, but bypasses the live property store and acts
+         directly on the dead property store.
+         &quot;&quot;&quot;
+-        if self.hasDeadProperty(property):
+-            if type(property) is tuple:
+-                qname = property
++        def callback(result):
++            if result:
++                if type(property) is tuple:
++                    qname = property
++                else:
++                    qname = property.qname()
++                # MOR: Double check I can return a deferred here
++                return self.deadProperties().delete(qname)
+             else:
+-                qname = property.qname()
++                return succeed(None) # Is this necessary?

+-            self.deadProperties().delete(qname)
++        d = self.hasDeadProperty(property)
++        d.addCallback(callback)
++        return d

++
+     #
+     # Overrides some methods in MetaDataMixin in order to allow DAV properties
+     # to override the values of some HTTP metadata.
+     #
+     def contentType(self):
+-        if self.hasDeadProperty((davxml.dav_namespace, &quot;getcontenttype&quot;)):
+-            return self.readDeadProperty((davxml.dav_namespace, &quot;getcontenttype&quot;)).mimeType()
+-        else:
+-            return super(DAVPropertyMixIn, self).contentType()
++        def callback(result):
++            if result:
++                return self.readDeadProperty((davxml.dav_namespace, &quot;getcontenttype&quot;)).mimeType()
++            else:
++                return super(DAVPropertyMixIn, self).contentType()
++        d = self.hasDeadProperty((davxml.dav_namespace, &quot;getcontenttype&quot;))
++        d.addCallback(callback)
++        return d

+     def displayName(self):
+-        if self.hasDeadProperty((davxml.dav_namespace, &quot;displayname&quot;)):
+-            return str(self.readDeadProperty((davxml.dav_namespace, &quot;displayname&quot;)))
+-        else:
+-            return super(DAVPropertyMixIn, self).displayName()
++        def callback(result):
++            if result:
++                return str(self.readDeadProperty((davxml.dav_namespace, &quot;displayname&quot;)))
++            else:
++                return super(DAVPropertyMixIn, self).displayName()

++        d = self.hasDeadProperty((davxml.dav_namespace, &quot;displayname&quot;))
++        d.addCallback(callback)
++        return d
++
+ class DAVResource (DAVPropertyMixIn, StaticRenderMixin):
+     &quot;&quot;&quot;
+     WebDAV resource.
+@@ -578,11 +629,10 @@

</ins><span class="cx">          completionDeferred = Deferred()
</span><span class="cx">          basepath = request.urlForResource(self)
</span><span class="cx"> -        children = list(self.listChildren())
</span><span class="cx">  
</span><del>-         def checkPrivilegesError(failure):
</del><ins>+-        def checkPrivilegesError(failure):
++        def checkPrivilegesError(failure, children):
</ins><span class="cx">              failure.trap(AccessDeniedError)
</span><del>-@@ -595,7 +596,7 @@
</del><ins>+-            reactor.callLater(0, getChild)
++            reactor.callLater(0, getChild, children)

+         def checkPrivileges(child):
+             if child is None:
+@@ -595,7 +645,7 @@
</ins><span class="cx">              d.addCallback(lambda _: child)
</span><span class="cx">              return d
</span><span class="cx">  
</span><span class="lines">@@ -35,7 +218,7 @@
</span><span class="cx">              if child is None:
</span><span class="cx">                  callback(None, childpath + &quot;/&quot;)
</span><span class="cx">              else:
</span><del>-@@ -603,14 +604,15 @@
</del><ins>+@@ -603,14 +653,15 @@
</ins><span class="cx">                      callback(child, childpath + &quot;/&quot;)
</span><span class="cx">                      if depth == &quot;infinity&quot;:
</span><span class="cx">                          d = child.findChildren(depth, request, callback, privileges)
</span><span class="lines">@@ -54,12 +237,12 @@
</span><span class="cx">              try:
</span><span class="cx">                  childname = children.pop()
</span><span class="cx">              except IndexError:
</span><del>-@@ -619,10 +621,10 @@
</del><ins>+@@ -619,10 +670,10 @@
</ins><span class="cx">                  childpath = joinURL(basepath, childname)
</span><span class="cx">                  d = request.locateChildResource(self, childname)
</span><span class="cx">                  d.addCallback(checkPrivileges)
</span><span class="cx"> -                d.addCallbacks(gotChild, checkPrivilegesError, (childpath,))
</span><del>-+                d.addCallbacks(gotChild, checkPrivilegesError, (childpath, children))
</del><ins>++                d.addCallbacks(gotChild, checkPrivilegesError, callbackArgs=(childpath, children), errbackArgs=(children,))
</ins><span class="cx">                  d.addErrback(completionDeferred.errback)
</span><span class="cx">  
</span><span class="cx"> -        getChild()
</span><span class="lines">@@ -67,7 +250,7 @@
</span><span class="cx">  
</span><span class="cx">          return completionDeferred
</span><span class="cx">  
</span><del>-@@ -642,39 +644,41 @@
</del><ins>+@@ -642,41 +693,43 @@
</ins><span class="cx">      # Authentication
</span><span class="cx">      ##
</span><span class="cx">  
</span><span class="lines">@@ -97,15 +280,10 @@
</span><span class="cx"> -                # &quot;Authorization will not help&quot; according to RFC2616
</span><span class="cx"> -                #
</span><span class="cx"> -                raise HTTPError(response)
</span><del>--
</del><ins>+ 
</ins><span class="cx"> -            d = self.checkPrivileges(request, privileges, recurse)
</span><span class="cx"> -            d.addErrback(onErrors)
</span><span class="cx"> -            return d
</span><del>--
--        d = maybeDeferred(self.authenticate, request)
--        d.addCallback(onAuth)
--        return d
-+
</del><span class="cx"> +        try:
</span><span class="cx"> +            yield self.authenticate(request)
</span><span class="cx"> +        except (UnauthorizedLogin, LoginFailed), e:
</span><span class="lines">@@ -115,7 +293,10 @@
</span><span class="cx"> +                request.remoteAddr
</span><span class="cx"> +            ))
</span><span class="cx"> +            raise HTTPError(response)
</span><del>-+
</del><ins>+ 
+-        d = maybeDeferred(self.authenticate, request)
+-        d.addCallback(onAuth)
+-        return d
</ins><span class="cx"> +        try:
</span><span class="cx"> +            yield self.checkPrivileges(request, privileges, recurse)
</span><span class="cx"> +        except AccessDeniedError, e:
</span><span class="lines">@@ -134,11 +315,220 @@
</span><span class="cx"> +            # &quot;Authorization will not help&quot; according to RFC2616
</span><span class="cx"> +            #
</span><span class="cx"> +            raise HTTPError(response)
</span><ins>+ 

</ins><span class="cx"> +
</span><ins>+     def authenticate(self, request):
+         if not (
+             hasattr(request, 'portal') and 
+@@ -781,7 +834,7 @@
+         This implementation stores the ACL in the private property
+         C{(L{twisted_private_namespace}, &quot;acl&quot;)}.
+         &quot;&quot;&quot;
+-        self.writeDeadProperty(acl)
++        return self.writeDeadProperty(acl)
</ins><span class="cx">  
</span><ins>+     def mergeAccessControlList(self, new_acl, request):
+         &quot;&quot;&quot;
+@@ -1089,7 +1142,9 @@
+             return url
</ins><span class="cx">  
</span><del>-     def authenticate(self, request):
-@@ -1880,7 +1884,7 @@
</del><ins>+         try:
+-            acl = self.readDeadProperty(davxml.ACL)
++            acl = waitForDeferred(self.readDeadProperty(davxml.ACL))
++            yield acl
++            acl = acl.getResult()
+         except HTTPError, e:
+             assert e.response.code == responsecode.NOT_FOUND, (
+                 &quot;Expected %s response from readDeadProperty() exception, not %s&quot;
+@@ -1635,7 +1690,9 @@

+         # Check this resource first
+         if self.isCollection():
+-            qroot = self.quotaRoot(request)
++            qroot = waitForDeferred(self.quotaRoot(request))
++            yield qroot
++            qroot = qroot.getResult()
+             if qroot is not None:
+                 used = waitForDeferred(self.currentQuotaUse(request))
+                 yield used
+@@ -1673,7 +1730,10 @@
+         &quot;&quot;&quot;
+         
+         # Check this one first
+-        if self.hasQuotaRoot(request):
++        hasQuotaRoot = waitForDeferred(self.hasQuotaRoot(request))
++        yield hasQuotaRoot
++        hasQuotaRoot = hasQuotaRoot.getResult()
++        if hasQuotaRoot:
+             yield True
+             return
+         
+@@ -1705,10 +1765,19 @@
+         @return: a C{int} containing the maximum allowed bytes if this collection
+             is quota-controlled, or C{None} if not quota controlled.
+         &quot;&quot;&quot;
+-        if self.hasDeadProperty(TwistedQuotaRootProperty):
+-            return int(str(self.readDeadProperty(TwistedQuotaRootProperty)))
++        hasDeadProperty = waitForDeferred(self.hasDeadProperty(TwistedQuotaRootProperty))
++        yield hasDeadProperty
++        hasDeadProperty = hasDeadProperty.getResult()
++
++        if hasDeadProperty:
++            propValue = waitForDeferred(self.readDeadProperty(TwistedQuotaRootProperty))
++            yield propValue
++            propValue = propValue.getResult()
++            yield int(str(propValue))
+         else:
+-            return None
++            yield None
++
++    quotaRoot = deferredGenerator(quotaRoot)
+     
+     def quotaRootParent(self, request):
+         &quot;&quot;&quot;
+@@ -1724,7 +1793,10 @@
+             parent = waitForDeferred(request.locateResource(url))
+             yield parent
+             parent = parent.getResult()
+-            if parent.hasQuotaRoot(request):
++            hasQuotaRoot = waitForDeferred(parent.hasQuotaRoot(request))
++            yield hasQuotaRoot
++            hasQuotaRoot = hasQuotaRoot.getResult()
++            if hasQuotaRoot:
+                 yield parent
+                 return

+@@ -1741,11 +1813,19 @@
+         assert maxsize is None or isinstance(maxsize, int), &quot;maxsize must be an int or None&quot;
+         
+         if maxsize is not None:
+-            self.writeDeadProperty(TwistedQuotaRootProperty(str(maxsize)))
++            d = waitForDeferred(self.writeDeadProperty(TwistedQuotaRootProperty(str(maxsize))))
++            yield d
++            d.getResult()
+         else:
+             # Remove both the root and the cached used value
+-            self.removeDeadProperty(TwistedQuotaRootProperty)
+-            self.removeDeadProperty(TwistedQuotaUsedProperty)
++            d = waitForDeferred(self.removeDeadProperty(TwistedQuotaRootProperty))
++            yield d
++            d.getResult()
++            d = waitForDeferred(self.removeDeadProperty(TwistedQuotaUsedProperty))
++            yield d
++            d.getResult()
++
++    setQuotaRoot = deferredGenerator(setQuotaRoot)
+     
+     def quotaSize(self, request):
+         &quot;&quot;&quot;
+@@ -1795,7 +1875,10 @@
+         
+         # Check this resource first
+         if self.isCollection():
+-            if self.hasQuotaRoot(request):
++            hasQuotaRoot = waitForDeferred(self.hasQuotaRoot(request))
++            yield hasQuotaRoot
++            hasQuotaRoot = hasQuotaRoot.getResult()
++            if hasQuotaRoot:
+                 d = waitForDeferred(self.updateQuotaUse(request, adjust))
+                 yield d
+                 d.getResult()
+@@ -1825,20 +1908,34 @@
+             is quota-controlled, or C{None} if not quota controlled.
+         &quot;&quot;&quot;
+         assert self.isCollection(), &quot;Only collections can have a quota root&quot;
+-        assert self.hasQuotaRoot(request), &quot;Quota use only on quota root collection&quot;
++        hasQuotaRoot = waitForDeferred(self.hasQuotaRoot(request))
++        yield hasQuotaRoot
++        hasQuotaRoot = hasQuotaRoot.getResult()
++        assert hasQuotaRoot, &quot;Quota use only on quota root collection&quot;
+         
+         # Try to get the cached value property
+-        if self.hasDeadProperty(TwistedQuotaUsedProperty):
+-            return succeed(int(str(self.readDeadProperty(TwistedQuotaUsedProperty))))
++        hasDeadProperty = waitForDeferred(self.hasDeadProperty(TwistedQuotaUsedProperty))
++        yield hasDeadProperty
++        hasDeadProperty = hasDeadProperty.getResult()
++        if hasDeadProperty:
++            propValue = waitForDeferred(self.readDeadProperty(TwistedQuotaUsedProperty))
++            yield propValue
++            propValue = propValue.getResult()
++            yield int(str(propValue))
++            return
+         else:
+             # Do brute force size determination and cache the result in the private property
+-            def _defer(result):
+-                self.writeDeadProperty(TwistedQuotaUsedProperty(str(result)))
+-                return result
+-            d = self.quotaSize(request)
+-            d.addCallback(_defer)
+-            return d
++            quotaSize = waitForDeferred(self.quotaSize(request))
++            yield quotaSize
++            quotaSize = quotaSize.getResult()
++            d = waitForDeferred(self.writeDeadProperty(TwistedQuotaUsedProperty(str(quotaSize))))
++            yield d
++            d = d.getResult()
++            yield quotaSize
++            return

++    currentQuotaUse = deferredGenerator(currentQuotaUse)
++
+     def updateQuotaUse(self, request, adjust):
+         &quot;&quot;&quot;
+         Update the quota used value on this resource.
+@@ -1848,25 +1945,32 @@
+         @return: an L{Deferred} with a C{int} result containing the current used byte if this collection
+             is quota-controlled, or C{None} if not quota controlled.
+         &quot;&quot;&quot;
++
+         assert self.isCollection(), &quot;Only collections can have a quota root&quot;
+-        
+-        # Get current value
+-        def _defer(size):
+-            size += adjust
+-            
+-            # Sanity check the resulting size
+-            if size &gt;= 0:
+-                self.writeDeadProperty(TwistedQuotaUsedProperty(str(size)))
+-            else:
+-                # Remove the dead property and re-read to do brute force quota calc
+-                log.msg(&quot;Attempt to set quota used to a negative value: %s (adjustment: %s)&quot; % (size, adjust,))
+-                self.removeDeadProperty(TwistedQuotaUsedProperty)
+-                return self.currentQuotaUse(request)
++        size = waitForDeferred(self.currentQuotaUse(request))
++        yield size
++        size = size.getResult()
++        size += adjust

+-        d = self.currentQuotaUse(request)
+-        d.addCallback(_defer)
+-        return d
+-        
++        # Sanity check the resulting size
++        if size &gt;= 0:
++            d = waitForDeferred(self.writeDeadProperty(TwistedQuotaUsedProperty(str(size))))
++            yield d
++            d = d.getResult()
++        else:
++            # Remove the dead property and re-read to do brute force quota calc
++            log.msg(&quot;Attempt to set quota used to a negative value: %s (adjustment: %s)&quot; % (size, adjust,))
++            d = waitForDeferred(self.removeDeadProperty(TwistedQuotaUsedProperty))
++            yield d
++            d.getResult()
++            size = waitForDeferred(self.currentQuotaUse(request))
++            yield size
++            size = size.getResult()
++        yield size
++        return
++
++    updateQuotaUse = deferredGenerator(updateQuotaUse)
++
+     ##
+     # HTTP
+     ##
+@@ -1880,7 +1984,7 @@
</ins><span class="cx">          # If this is a collection and the URI doesn't end in &quot;/&quot;, redirect.
</span><span class="cx">          #
</span><span class="cx">          if self.isCollection() and request.path[-1:] != &quot;/&quot;:
</span><span class="lines">@@ -147,4 +537,3 @@
</span><span class="cx">  
</span><span class="cx">          def setHeaders(response):
</span><span class="cx">              response = IResponse(response)
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davstaticpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.static.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.static.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.static.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/web2/dav/static.py'
---- twisted/web2/dav/static.py        2009-04-20 17:38:06 +0000
-+++ twisted/web2/dav/static.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/dav/static.py
+===================================================================
+--- twisted/web2/dav/static.py        (revision 26969)
++++ twisted/web2/dav/static.py        (working copy)
</ins><span class="cx"> @@ -53,6 +53,14 @@
</span><span class="cx">  
</span><span class="cx">      Extends twisted.web2.static.File to handle WebDAV methods.
</span><span class="lines">@@ -16,7 +17,38 @@
</span><span class="cx">      def __init__(
</span><span class="cx">          self, path,
</span><span class="cx">          defaultType=&quot;text/plain&quot;, indexNames=None,
</span><del>-@@ -192,7 +200,7 @@
</del><ins>+@@ -82,12 +90,26 @@
+     ##

+     def etag(self):
+-        if not self.fp.exists(): return None
+-        if self.hasDeadProperty(TwistedGETContentMD5):
+-            return http_headers.ETag(str(self.readDeadProperty(TwistedGETContentMD5)))
++        if not self.fp.exists():
++            yield None
++            return
++
++        hasProp = waitForDeferred(self.hasDeadProperty(TwistedGETContentMD5))
++        yield hasProp
++        hasProp = hasProp.getResult()
++        if hasProp:
++            propValue = waitForDeferred(self.readDeadProperty(TwistedGETContentMD5))
++            yield propValue
++            propValue = propValue.getResult()
++            yield http_headers.ETag(str(propValue))
+         else:
+-            return super(DAVFile, self).etag()
++            d = waitForDeferred(super(DAVFile, self).etag())
++            yield d
++            d = d.getResult()
++            yield d

++    etag = deferredGenerator(etag)
++
+     def davComplianceClasses(self):
+         return (&quot;1&quot;, &quot;access-control&quot;) # Add &quot;2&quot; when we have locking

+@@ -192,7 +214,7 @@
</ins><span class="cx">          return (self.createSimilarFile(self.fp.child(path).path), segments[1:])
</span><span class="cx">  
</span><span class="cx">      def createSimilarFile(self, path):
</span><span class="lines">@@ -25,4 +57,3 @@
</span><span class="cx">              path, defaultType=self.defaultType, indexNames=self.indexNames[:],
</span><span class="cx">              principalCollections=self.principalCollections())
</span><span class="cx">  
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_aclpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_acl.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_acl.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_acl.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,479 @@
</span><ins>+Index: twisted/web2/dav/test/test_acl.py
+===================================================================
+--- twisted/web2/dav/test/test_acl.py        (revision 26969)
++++ twisted/web2/dav/test/test_acl.py        (working copy)
+@@ -26,6 +26,8 @@

+ from twisted.cred.portal import Portal

++from twisted.internet.defer import waitForDeferred, deferredGenerator
++
+ from twisted.web2 import responsecode
+ from twisted.web2.auth import basic
+ from twisted.web2.stream import MemoryStream
+@@ -68,7 +70,9 @@
+         os.mkdir(docroot)

+         userResource = TestDAVPrincipalResource(&quot;/principals/users/user01&quot;)
+-        userResource.writeDeadProperty(TwistedPasswordProperty(&quot;user01&quot;))
++        d = waitForDeferred(userResource.writeDeadProperty(TwistedPasswordProperty(&quot;user01&quot;)))
++        yield d
++        d = d.getResult()

+         principalCollection = TestPrincipalsCollection(
+             &quot;/principals/&quot;,
+@@ -118,8 +122,9 @@
+                 os.mkdir(dirname)
+             resource = self.resource_class(dirname)
+             resource.setAccessControlList(acl)
+-        return docroot
++        yield docroot

++    createDocumentRoot = deferredGenerator(createDocumentRoot)

+     def restore(self):
+         # Get rid of whatever messed up state the test has now so that we'll
+@@ -134,24 +139,32 @@
+         Verify source access controls during COPY and MOVE.
+         &quot;&quot;&quot;
+         def work():
+-            dst_path = os.path.join(self.docroot, &quot;copy_dst&quot;)
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            dst_path = os.path.join(docroot, &quot;copy_dst&quot;)
+             dst_uri = &quot;/&quot; + os.path.basename(dst_path)

++            results = []
+             for src, status in (
+                 (&quot;nobind&quot;, responsecode.FORBIDDEN),
+                 (&quot;bind&quot;,   responsecode.FORBIDDEN),
+                 (&quot;unbind&quot;, responsecode.CREATED),
+             ):
+-                src_path = os.path.join(self.docroot, &quot;src_&quot; + src)
++                src_path = os.path.join(docroot, &quot;src_&quot; + src)
+                 src_uri = &quot;/&quot; + os.path.basename(src_path)
+                 if not os.path.isdir(src_path):
+                     os.mkdir(src_path)
+                 src_resource = self.resource_class(src_path)
+-                src_resource.setAccessControlList({
++
++                d = waitForDeferred(src_resource.setAccessControlList({
+                     &quot;nobind&quot;: self.grant(),
+                     &quot;bind&quot;  : self.grant(davxml.Bind()),
+                     &quot;unbind&quot;: self.grant(davxml.Bind(), davxml.Unbind())
+-                }[src])
++                }[src]))
++                yield d
++                d.getResult()
++
+                 for name, acl in (
+                     (&quot;none&quot;       , self.grant()),
+                     (&quot;read&quot;       , self.grant(davxml.Read())),
+@@ -162,8 +175,11 @@
+                     filename = os.path.join(src_path, name)
+                     if not os.path.isfile(filename):
+                         file(filename, &quot;w&quot;).close()
+-                    self.resource_class(filename).setAccessControlList(acl)

++                    d = waitForDeferred(self.resource_class(filename).setAccessControlList(acl))
++                    yield d
++                    d.getResult()
++
+                 for method in (&quot;COPY&quot;, &quot;MOVE&quot;):
+                     for name, code in (
+                         (&quot;none&quot;       , {&quot;COPY&quot;: responsecode.FORBIDDEN, &quot;MOVE&quot;: status}[method]),
+@@ -175,7 +191,11 @@
+                         path = os.path.join(src_path, name)
+                         uri = src_uri + &quot;/&quot; + name
+     
+-                        request = SimpleRequest(self.site, method, uri)
++                        site = waitForDeferred(self.site)
++                        yield site
++                        site = site.getResult()
++
++                        request = SimpleRequest(site, method, uri)
+                         request.headers.setHeader(&quot;destination&quot;, dst_uri)
+                         _add_auth_header(request)
+     
+@@ -184,30 +204,56 @@
+                                 os.remove(dst_path)
+     
+                             if response.code != code:
+-                                return self.oops(request, response, code, method, name)
++                                d = waitForDeferred(self.oops(request, response, code, method, name))
++                                yield d
++                                d = d.getResult()
++                                yield d
++                                return
+     
+-                        yield (request, test)
++                        results.append( (request, test) )

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_MOVE_source = deferredGenerator(test_COPY_MOVE_source)
++
++
+     def test_COPY_MOVE_dest(self):
+         &quot;&quot;&quot;
+         Verify destination access controls during COPY and MOVE.
+         &quot;&quot;&quot;
+         def work():
+-            src_path = os.path.join(self.docroot, &quot;read&quot;)
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            src_path = os.path.join(docroot, &quot;read&quot;)
+             uri = &quot;/&quot; + os.path.basename(src_path)

++            results = []
+             for method in (&quot;COPY&quot;, &quot;MOVE&quot;):
+                 for name, code in (
+                     (&quot;nobind&quot; , responsecode.FORBIDDEN),
+                     (&quot;bind&quot;   , responsecode.CREATED),
+                     (&quot;unbind&quot; , responsecode.CREATED),
+                 ):
+-                    dst_parent_path = os.path.join(self.docroot, name)
++                    dst_parent_path = os.path.join(docroot, name)
+                     dst_path = os.path.join(dst_parent_path, &quot;dst&quot;)

+-                    request = SimpleRequest(self.site, method, uri)
++                    site = waitForDeferred(self.site)
++                    yield site
++                    site = site.getResult()
++
++                    request = SimpleRequest(site, method, uri)
+                     request.headers.setHeader(&quot;destination&quot;, &quot;/&quot; + name + &quot;/dst&quot;)
+                     _add_auth_header(request)

+@@ -216,39 +262,80 @@
+                             os.remove(dst_path)

+                         if response.code != code:
+-                            return self.oops(request, response, code, method, name)
++                            d = waitForDeferred(self.oops(request, response, code, method, name))
++                            yield d
++                            d = d.getResult()
++                            yield d
++                            return

+-                    yield (request, test)
++                    results.append((request, test))
+                     self.restore()

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_MOVE_dest = deferredGenerator(test_COPY_MOVE_dest)
++
+     def test_DELETE(self):
+         &quot;&quot;&quot;
+         Verify access controls during DELETE.
+         &quot;&quot;&quot;
+         def work():
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
+             for name, code in (
+                 (&quot;nobind&quot; , responsecode.FORBIDDEN),
+                 (&quot;bind&quot;   , responsecode.FORBIDDEN),
+                 (&quot;unbind&quot; , responsecode.NO_CONTENT),
+             ):
+-                collection_path = os.path.join(self.docroot, name)
++                collection_path = os.path.join(docroot, name)
+                 path = os.path.join(collection_path, &quot;dst&quot;)

+                 file(path, &quot;w&quot;).close()

+-                request = SimpleRequest(self.site, &quot;DELETE&quot;, &quot;/&quot; + name + &quot;/dst&quot;)
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++
++                request = SimpleRequest(site, &quot;DELETE&quot;, &quot;/&quot; + name + &quot;/dst&quot;)
+                 _add_auth_header(request)

+                 def test(response, code=code, path=path):
+                     if response.code != code:
+-                        return self.oops(request, response, code, &quot;DELETE&quot;, name)
++                        d = waitForDeferred(self.oops(request, response, code, &quot;DELETE&quot;, name))
++                        yield d
++                        d = d.getResult()
++                        yield d
++                        return

+-                yield (request, test)
++                results.append((request, test))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++
+     def test_UNLOCK(self):
+         &quot;&quot;&quot;
+         Verify access controls during UNLOCK of unowned lock.
+@@ -261,14 +348,19 @@
+         &quot;&quot;&quot;
+         Verify access controls during MKCOL.
+         &quot;&quot;&quot;
+-        for method in (&quot;MKCOL&quot;, &quot;PUT&quot;):
+-            def work():
++        def work():
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
++
++            for method in (&quot;MKCOL&quot;, &quot;PUT&quot;):
+                 for name, code in (
+                     (&quot;nobind&quot; , responsecode.FORBIDDEN),
+                     (&quot;bind&quot;   , responsecode.CREATED),
+                     (&quot;unbind&quot; , responsecode.CREATED),
+                 ):
+-                    collection_path = os.path.join(self.docroot, name)
++                    collection_path = os.path.join(docroot, name)
+                     path = os.path.join(collection_path, &quot;dst&quot;)

+                     if os.path.isfile(path):
+@@ -276,22 +368,45 @@
+                     elif os.path.isdir(path):
+                         os.rmdir(path)

+-                    request = SimpleRequest(self.site, method, &quot;/&quot; + name + &quot;/dst&quot;)
++                    site = waitForDeferred(self.site)
++                    yield site
++                    site = site.getResult()
++                    request = SimpleRequest(site, method, &quot;/&quot; + name + &quot;/dst&quot;)
+                     _add_auth_header(request)

+                     def test(response, code=code, path=path):
+                         if response.code != code:
+-                            return self.oops(request, response, code, method, name)
++                            d = waitForDeferred(self.oops(request, response, code, &quot;DELETE&quot;, name))
++                            yield d
++                            d = d.getResult()
++                            yield d
++                            return

+-                    yield (request, test)
++                    results.append((request, test))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++
+     def test_PUT_exists(self):
+         &quot;&quot;&quot;
+         Verify access controls during PUT of existing file.
+         &quot;&quot;&quot;
+         def work():
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
+             for name, code in (
+                 (&quot;none&quot;       , responsecode.FORBIDDEN),
+                 (&quot;read&quot;       , responsecode.FORBIDDEN),
+@@ -299,19 +414,38 @@
+                 (&quot;unlock&quot;     , responsecode.FORBIDDEN),
+                 (&quot;all&quot;        , responsecode.NO_CONTENT),
+             ):
+-                path = os.path.join(self.docroot, name)
++                path = os.path.join(docroot, name)

+-                request = SimpleRequest(self.site, &quot;PUT&quot;, &quot;/&quot; + name)
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++                request = SimpleRequest(site, &quot;PUT&quot;, &quot;/&quot; + name)
+                 _add_auth_header(request)

+                 def test(response, code=code, path=path):
+                     if response.code != code:
+-                        return self.oops(request, response, code, &quot;PUT&quot;, name)
++                        d = waitForDeferred(self.oops(request, response, code, &quot;PUT&quot;, name))
++                        yield d
++                        d = d.getResult()
++                        yield d
++                        return

+-                yield (request, test)
++                results.append((request, test))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++
+     def test_PROPFIND(self):
+         &quot;&quot;&quot;
+         Verify access controls during PROPFIND.
+@@ -325,6 +459,10 @@
+         Verify access controls during PROPPATCH.
+         &quot;&quot;&quot;
+         def work():
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
+             for name, code in (
+                 (&quot;none&quot;       , responsecode.FORBIDDEN),
+                 (&quot;read&quot;       , responsecode.FORBIDDEN),
+@@ -332,9 +470,12 @@
+                 (&quot;unlock&quot;     , responsecode.FORBIDDEN),
+                 (&quot;all&quot;        , responsecode.MULTI_STATUS),
+             ):
+-                path = os.path.join(self.docroot, name)
++                path = os.path.join(docroot, name)

+-                request = SimpleRequest(self.site, &quot;PROPPATCH&quot;, &quot;/&quot; + name)
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++                request = SimpleRequest(site, &quot;PROPPATCH&quot;, &quot;/&quot; + name)
+                 request.stream = MemoryStream(
+                     davxml.WebDAVDocument(davxml.PropertyUpdate()).toxml()
+                 )
+@@ -342,17 +483,36 @@

+                 def test(response, code=code, path=path):
+                     if response.code != code:
+-                        return self.oops(request, response, code, &quot;PROPPATCH&quot;, name)
++                        d = waitForDeferred(self.oops(request, response, code, &quot;PROPPATCH&quot;, name))
++                        yield d
++                        d = d.getResult()
++                        yield d
++                        return

+-                yield (request, test)
++                results.append((request, test))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
+     def test_GET_REPORT(self):
+         &quot;&quot;&quot;
+         Verify access controls during GET and REPORT.
+         &quot;&quot;&quot;
+         def work():
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
+             for method in (&quot;GET&quot;, &quot;REPORT&quot;):
+                 if method == &quot;GET&quot;:
+                     ok = responsecode.OK
+@@ -368,9 +528,12 @@
+                     (&quot;unlock&quot;     , responsecode.FORBIDDEN),
+                     (&quot;all&quot;        , ok),
+                 ):
+-                    path = os.path.join(self.docroot, name)
++                    path = os.path.join(docroot, name)

+-                    request = SimpleRequest(self.site, method, &quot;/&quot; + name)
++                    site = waitForDeferred(self.site)
++                    yield site
++                    site = site.getResult()
++                    request = SimpleRequest(site, method, &quot;/&quot; + name)
+                     if method == &quot;REPORT&quot;:
+                         request.stream = MemoryStream(davxml.PrincipalPropertySearch().toxml())

+@@ -378,12 +541,27 @@

+                     def test(response, code=code, path=path):
+                         if response.code != code:
+-                            return self.oops(request, response, code, method, name)
++                            d = waitForDeferred(self.oops(request, response, code, method, name))
++                            yield d
++                            d = d.getResult()
++                            yield d

+-                    yield (request, test)
++                    results.append((request, test))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++
+     def oops(self, request, response, code, method, name):
+         def gotResponseData(doc):
+             if doc is None:
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_copypatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_copy.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_copy.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_copy.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,136 @@
</span><ins>+Index: twisted/web2/dav/test/test_copy.py
+===================================================================
+--- twisted/web2/dav/test/test_copy.py        (revision 26969)
++++ twisted/web2/dav/test/test_copy.py        (working copy)
+@@ -26,6 +26,7 @@
+ import os
+ import urllib

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ import twisted.web2.dav.test.util
+ from twisted.web2 import responsecode
+ from twisted.web2.test.test_server import SimpleRequest
+@@ -78,8 +79,17 @@
+                 self.fail(&quot;Source %s is neither a file nor a directory&quot;
+                           % (path,))

+-        return serialize(self.send, work(self, test))
++        d = waitForDeferred(work(self, test))
++        yield d
++        d = d.getResult( )

++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_create = deferredGenerator(test_COPY_create)
++
+     def test_COPY_exists(self):
+         &quot;&quot;&quot;
+         COPY to existing resource.
+@@ -92,8 +102,18 @@
+                 # FIXME: Check XML error code (2518bis)
+                 pass

+-        return serialize(self.send, work(self, test, overwrite=False))
++        d = waitForDeferred(work(self, test, overwrite=False))
++        yield d
++        d = d.getResult( )

++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_exists = deferredGenerator(test_COPY_exists)
++
++
+     def test_COPY_overwrite(self):
+         &quot;&quot;&quot;
+         COPY to existing resource with overwrite header.
+@@ -108,8 +128,17 @@

+             self.failUnless(os.path.exists(dst_path), &quot;COPY didn't produce file: %s&quot; % (dst_path,))

+-        return serialize(self.send, work(self, test, overwrite=True))
++        d = waitForDeferred(work(self, test, overwrite=True))
++        yield d
++        d = d.getResult( )

++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_overwrite = deferredGenerator(test_COPY_overwrite)
++
+     def test_COPY_no_parent(self):
+         &quot;&quot;&quot;
+         COPY to resource with no parent.
+@@ -122,18 +151,35 @@
+                 # FIXME: Check XML error code (2518bis)
+                 pass

+-        return serialize(self.send, work(self, test, dst=os.path.join(self.docroot, &quot;elvislives!&quot;)))
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

++        d = waitForDeferred(work(self, test, dst=os.path.join(docroot, &quot;elvislives!&quot;)))
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_COPY_no_parent = deferredGenerator(test_COPY_no_parent)
++
+ def work(self, test, overwrite=None, dst=None, depths=(&quot;0&quot;, &quot;infinity&quot;, None)):
++    docroot = waitForDeferred(self.docroot)
++    yield docroot
++    docroot = docroot.getResult()
++    results = []
+     if dst is None:
+-        dst = os.path.join(self.docroot, &quot;dst&quot;)
++        dst = os.path.join(docroot, &quot;dst&quot;)
+         os.mkdir(dst)

+-    for basename in os.listdir(self.docroot):
++    for basename in os.listdir(docroot):
+         if basename == &quot;dst&quot;: continue

+         uri = urllib.quote(&quot;/&quot; + basename)
+-        path = os.path.join(self.docroot, basename)
++        path = os.path.join(docroot, basename)
+         isfile = os.path.isfile(path)
+         sum = sumFile(path)
+         dst_path = os.path.join(dst, basename)
+@@ -151,15 +197,23 @@
+             def do_test(response, path=path, isfile=isfile, sum=sum, uri=uri, depth=depth, dst_path=dst_path):
+                 test(response, path, isfile, sum, uri, depth, dst_path)

+-            request = SimpleRequest(self.site, self.__class__.__name__, uri)
++            site = waitForDeferred(self.site)
++            yield site
++            site = site.getResult()
++            request = SimpleRequest(site, self.__class__.__name__, uri)
+             request.headers.setHeader(&quot;destination&quot;, dst_uri)
+             if depth is not None:
+                 request.headers.setHeader(&quot;depth&quot;, depth)
+             if overwrite is not None:
+                 request.headers.setHeader(&quot;overwrite&quot;, overwrite)

+-            yield (request, do_test)
++            results.append((request, do_test))

++    yield results
++
++work = deferredGenerator(work)
++
++
+ def sumFile(path):
+     m = md5()

</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_deletepatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_delete.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_delete.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_delete.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+Index: twisted/web2/dav/test/test_delete.py
+===================================================================
+--- twisted/web2/dav/test/test_delete.py        (revision 26969)
++++ twisted/web2/dav/test/test_delete.py        (working copy)
+@@ -26,6 +26,7 @@
+ import urllib
+ import random

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ from twisted.web2 import responsecode
+ from twisted.web2.iweb import IResponse
+ from twisted.web2.test.test_server import SimpleRequest
+@@ -54,8 +55,13 @@
+                 self.fail(&quot;DELETE did not remove path %s&quot; % (path,))

+         def work():
+-            for filename in os.listdir(self.docroot):
+-                path = os.path.join(self.docroot, filename)
++            docroot = waitForDeferred(self.docroot)
++            yield docroot
++            docroot = docroot.getResult()
++            results = []
++
++            for filename in os.listdir(docroot):
++                path = os.path.join(docroot, filename)
+                 uri = urllib.quote(&quot;/&quot; + filename)

+                 if os.path.isdir(path): uri = uri + &quot;/&quot;
+@@ -63,12 +69,26 @@
+                 def do_test(response, path=path):
+                     return check_result(response, path)

+-                request = SimpleRequest(self.site, &quot;DELETE&quot;, uri)
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++                request = SimpleRequest(site, &quot;DELETE&quot;, uri)

+                 depth = random.choice((&quot;infinity&quot;, None))
+                 if depth is not None:
+                     request.headers.setHeader(&quot;depth&quot;, depth)

+-                yield (request, do_test)
++                results.append((request, do_test))

+-        return serialize(self.send, work())
++            yield results
++
++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        d = d.getResult( )
++
++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult( )
++        yield d
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_mkcolpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_mkcol.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_mkcol.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_mkcol.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+Index: twisted/web2/dav/test/test_mkcol.py
+===================================================================
+--- twisted/web2/dav/test/test_mkcol.py        (revision 26969)
++++ twisted/web2/dav/test/test_mkcol.py        (working copy)
+@@ -24,6 +24,7 @@

+ import os

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ from twisted.web2 import responsecode
+ from twisted.web2.iweb import IResponse
+ from twisted.web2.stream import MemoryStream
+@@ -35,6 +36,7 @@
+     &quot;&quot;&quot;
+     MKCOL request
+     &quot;&quot;&quot;
++
+     # FIXME:
+     # Try in nonexistant parent collection.
+     # Try on existing resource.
+@@ -43,7 +45,9 @@
+         &quot;&quot;&quot;
+         MKCOL request
+         &quot;&quot;&quot;
+-        path, uri = self.mkdtemp(&quot;collection&quot;)
++        d = waitForDeferred(self.mkdtemp(&quot;collection&quot;))
++        yield d
++        path, uri = d.getResult()

+         rmdir(path)

+@@ -56,17 +60,28 @@
+             if not os.path.isdir(path):
+                 self.fail(&quot;MKCOL did not create directory %s&quot; % (path,))

+-        request = SimpleRequest(self.site, &quot;MKCOL&quot;, uri)
++        site = waitForDeferred(self.site)
++        yield site
++        site = site.getResult()

+-        return self.send(request, check_result)
++        request = SimpleRequest(site, &quot;MKCOL&quot;, uri)

++        d = waitForDeferred(self.send(request, check_result))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_MKCOL = deferredGenerator(test_MKCOL)
++
+     def test_MKCOL_invalid_body(self):
+         &quot;&quot;&quot;
+         MKCOL request with invalid request body
+         (Any body at all is invalid in our implementation; there is no
+         such thing as a valid body.)
+         &quot;&quot;&quot;
+-        path, uri = self.mkdtemp(&quot;collection&quot;)
++        d = waitForDeferred(self.mkdtemp(&quot;collection&quot;))
++        yield d
++        path, uri = d.getResult()

+         rmdir(path)

+@@ -79,7 +94,15 @@
+             if os.path.isdir(path):
+                 self.fail(&quot;MKCOL incorrectly created directory %s&quot; % (path,))

+-        request = SimpleRequest(self.site, &quot;MKCOL&quot;, uri)
++        site = waitForDeferred(self.site)
++        yield site
++        site = site.getResult()
++        request = SimpleRequest(site, &quot;MKCOL&quot;, uri)
+         request.stream = MemoryStream(&quot;This is not a valid MKCOL request body.&quot;)

+-        return self.send(request, check_result)
++        d = waitForDeferred(self.send(request, check_result))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_MKCOL_invalid_body = deferredGenerator(test_MKCOL_invalid_body)
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_movepatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_move.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_move.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_move.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,103 @@
</span><ins>+Index: twisted/web2/dav/test/test_move.py
+===================================================================
+--- twisted/web2/dav/test/test_move.py        (revision 26969)
++++ twisted/web2/dav/test/test_move.py        (working copy)
+@@ -24,6 +24,7 @@

+ import os

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ import twisted.web2.dav.test.util
+ import twisted.web2.dav.test.test_copy
+ from twisted.web2 import responsecode
+@@ -60,8 +61,21 @@
+                 if sum != sumFile(dst_path):
+                     self.fail(&quot;isdir %s produced different directory&quot; % (uri,))

+-        return serialize(self.send, work(self, test))
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

++        d = waitForDeferred(work(self, test))
++        yield d
++        d = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult( )
++        yield d
++
++    test_MOVE_create = deferredGenerator(test_MOVE_create)
++
+     def test_MOVE_exists(self):
+         &quot;&quot;&quot;
+         MOVE to existing resource.
+@@ -74,8 +88,21 @@
+                 # FIXME: Check XML error code (2518bis)
+                 pass

+-        return serialize(self.send, work(self, test, overwrite=False))
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

++        d = waitForDeferred(work(self, test, overwrite=False))
++        yield d
++        d = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult( )
++        yield d
++
++    test_MOVE_exists = deferredGenerator(test_MOVE_exists)
++
+     def test_MOVE_overwrite(self):
+         &quot;&quot;&quot;
+         MOVE to existing resource with overwrite header.
+@@ -88,8 +115,21 @@
+                 # FIXME: Check XML error code (2518bis)
+                 pass

+-        return serialize(self.send, work(self, test, overwrite=True))
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

++        d = waitForDeferred(work(self, test, overwrite=True))
++        yield d
++        d = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult( )
++        yield d
++
++    test_MOVE_overwrite = deferredGenerator(test_MOVE_overwrite)
++
+     def test_MOVE_no_parent(self):
+         &quot;&quot;&quot;
+         MOVE to resource with no parent.
+@@ -102,7 +142,20 @@
+                 # FIXME: Check XML error code (2518bis)
+                 pass

+-        return serialize(self.send, work(self, test, dst=os.path.join(self.docroot, &quot;elvislives!&quot;)))
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

++        d = waitForDeferred(work(self, test, dst=os.path.join(docroot, &quot;elvislives!&quot;)))
++        yield d
++        d = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(d)))
++        yield d
++        d = d.getResult( )
++        yield d
++
++    test_MOVE_no_parent = deferredGenerator(test_MOVE_no_parent)
++
+ def work(self, test, overwrite=None, dst=None):
+     return twisted.web2.dav.test.test_copy.work(self, test, overwrite, dst, depths=(None,))
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_optionspatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_options.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_options.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_options.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+Index: twisted/web2/dav/test/test_options.py
+===================================================================
+--- twisted/web2/dav/test/test_options.py        (revision 26969)
++++ twisted/web2/dav/test/test_options.py        (working copy)
+@@ -31,6 +31,16 @@
+     &quot;&quot;&quot;
+     OPTIONS request
+     &quot;&quot;&quot;
++    def setUp(self):
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++        twisted.web2.dav.test.util.TestCase.setUp(self)
++        self._getSite()
++
++
++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
+     def test_DAV1(self):
+         &quot;&quot;&quot;
+         DAV level 1
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_proppatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_prop.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_prop.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_prop.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+Index: twisted/web2/dav/test/test_prop.py
+===================================================================
+--- twisted/web2/dav/test/test_prop.py        (revision 26969)
++++ twisted/web2/dav/test/test_prop.py        (working copy)
+@@ -26,6 +26,7 @@

+ import random

++from twisted.internet.defer import deferredGenerator, waitForDeferred
+ from twisted.trial.unittest import SkipTest
+ from twisted.web2 import responsecode
+ from twisted.web2.iweb import IResponse
+@@ -57,6 +58,15 @@
+     PROPFIND, PROPPATCH requests
+     &quot;&quot;&quot;

++    def setUp(self):
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++        twisted.web2.dav.test.util.TestCase.setUp(self)
++        self._getSite()
++
++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
+     def liveProperties(self):
+         return [lookupElement(qname)() for qname in self.resource_class.liveProperties if (qname[0] == dav_namespace) and qname not in dynamicLiveProperties]

</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_putpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_put.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_put.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_put.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,208 @@
</span><ins>+Index: twisted/web2/dav/test/test_put.py
+===================================================================
+--- twisted/web2/dav/test/test_put.py        (revision 26969)
++++ twisted/web2/dav/test/test_put.py        (working copy)
+@@ -25,6 +25,7 @@
+ import os
+ import filecmp

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ from twisted.web2 import responsecode
+ from twisted.web2.iweb import IResponse
+ from twisted.web2.stream import FileStream
+@@ -42,27 +43,38 @@
+         &quot;&quot;&quot;
+         PUT request
+         &quot;&quot;&quot;
+-        dst_path = os.path.join(self.docroot, &quot;dst&quot;)
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()

+-        def checkResult(response, path):
+-            response = IResponse(response)
++        dst_path = os.path.join(docroot, &quot;dst&quot;)

+-            if response.code not in (
+-                responsecode.CREATED,
+-                responsecode.NO_CONTENT
+-            ):
+-                self.fail(&quot;PUT failed: %s&quot; % (response.code,))
++        def makeClosure(path):

+-            if not os.path.isfile(dst_path):
+-                self.fail(&quot;PUT failed to create file %s.&quot; % (dst_path,))
++            # Return a function with 'path' closed

+-            if not filecmp.cmp(path, dst_path):
+-                self.fail(&quot;PUT failed to preserve data for file %s in file %s.&quot; % (path, dst_path))
++            def checkResult(response):
++                response = IResponse(response)

+-            etag = response.headers.getHeader(&quot;etag&quot;)
+-            if not etag:
+-                self.fail(&quot;No etag header in PUT response %r.&quot; % (response,))
++                if response.code not in (
++                    responsecode.CREATED,
++                    responsecode.NO_CONTENT
++                ):
++                    self.fail(&quot;PUT failed: %s&quot; % (response.code,))

++                if not os.path.isfile(dst_path):
++                    self.fail(&quot;PUT failed to create file %s.&quot; % (dst_path,))
++
++                if not filecmp.cmp(path, dst_path):
++                    import pdb; pdb.set_trace()
++
++                    self.fail(&quot;PUT failed to preserve data for file %s in file %s.&quot; % (path, dst_path))
++
++                etag = response.headers.getHeader(&quot;etag&quot;)
++                if not etag:
++                    self.fail(&quot;No etag header in PUT response %r.&quot; % (response,))
++            return checkResult
++
+         #
+         # We need to serialize these request &amp; test iterations because they can
+         # interfere with each other.
+@@ -70,52 +82,79 @@
+         def work():
+             dst_uri = &quot;/dst&quot;

+-            for name in os.listdir(self.docroot):
++            results = []
++            for name in os.listdir(docroot):
+                 if name == &quot;dst&quot;:
+                     continue

+-                path = os.path.join(self.docroot, name)
++                path = os.path.join(docroot, name)

+                 # Can't really PUT something you can't read
+                 if not os.path.isfile(path): continue
+-    
+-                def do_test(response): checkResult(response, path)
+-    
+-                request = SimpleRequest(self.site, &quot;PUT&quot;, dst_uri)
++
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++
++                request = SimpleRequest(site, &quot;PUT&quot;, dst_uri)
+                 request.stream = FileStream(file(path, &quot;rb&quot;))
+-    
+-                yield (request, do_test)

+-        return serialize(self.send, work())
++                results.append((request, makeClosure(path)))

++            yield results
++
++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_PUT_simple = deferredGenerator(test_PUT_simple)
++
++
+     def test_PUT_again(self):
+         &quot;&quot;&quot;
+         PUT on existing resource with If-None-Match header
+         &quot;&quot;&quot;
+-        dst_path = os.path.join(self.docroot, &quot;dst&quot;)
++        docroot = waitForDeferred(self.docroot)
++        yield docroot
++        docroot = docroot.getResult()
++
++        dst_path = os.path.join(docroot, &quot;dst&quot;)
+         dst_uri = &quot;/dst&quot;

+         def work():
++            results = []
+             for code in (
+                 responsecode.CREATED,
+                 responsecode.PRECONDITION_FAILED,
+                 responsecode.NO_CONTENT,
+                 responsecode.PRECONDITION_FAILED,
+                 responsecode.NO_CONTENT,
+-                responsecode.CREATED,
+             ):
+-                def checkResult(response, code=code):
+-                    response = IResponse(response)
++                def makeClosure(code):
++                    def checkResult(response, code=code):
++                        response = IResponse(response)

+-                    if response.code != code:
+-                        self.fail(&quot;Incorrect response code for PUT (%s != %s)&quot;
+-                                  % (response.code, code))
++                        if response.code != code:
++                            self.fail(&quot;Incorrect response code for PUT (%s != %s)&quot;
++                                      % (response.code, code))
++                    return checkResult

+                 def onError(f):
+                     f.trap(HTTPError)
+                     return checkResult(f.value.response)

+-                request = SimpleRequest(self.site, &quot;PUT&quot;, dst_uri)
++                site = waitForDeferred(self.site)
++                yield site
++                site = site.getResult()
++
++                request = SimpleRequest(site, &quot;PUT&quot;, dst_uri)
+                 request.stream = FileStream(file(__file__, &quot;rb&quot;))
+     
+                 if code == responsecode.CREATED:
+@@ -125,10 +164,23 @@
+                 elif code == responsecode.PRECONDITION_FAILED:
+                     request.headers.setHeader(&quot;if-none-match&quot;, (&quot;*&quot;,))
+     
+-                yield (request, (checkResult, onError))
++                results.append((request, (makeClosure(code), onError)))

+-        return serialize(self.send, work())
++            yield results

++        work = deferredGenerator(work)
++
++        d = waitForDeferred(work())
++        yield d
++        results = d.getResult()
++
++        d = waitForDeferred(serialize(self.send, iter(results)))
++        yield d
++        d = d.getResult()
++        yield d
++
++    test_PUT_again = deferredGenerator(test_PUT_again)
++
+     def test_PUT_no_parent(self):
+         &quot;&quot;&quot;
+         PUT with no parent
+@@ -142,7 +194,16 @@
+                 self.fail(&quot;Incorrect response code for PUT with no parent (%s != %s)&quot;
+                           % (response.code, responsecode.CONFLICT))

+-        request = SimpleRequest(self.site, &quot;PUT&quot;, dst_uri)
++        site = waitForDeferred(self.site)
++        yield site
++        site = site.getResult()
++
++        request = SimpleRequest(site, &quot;PUT&quot;, dst_uri)
+         request.stream = FileStream(file(__file__, &quot;rb&quot;))

+-        return self.send(request, checkResult)
++        result = waitForDeferred(self.send(request, checkResult))
++        yield result
++        result = result.getResult()
++        yield result
++
++    test_PUT_no_parent = deferredGenerator(test_PUT_no_parent)
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_quotapatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_quota.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_quota.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_quota.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Index: twisted/web2/dav/test/test_quota.py
+===================================================================
+--- twisted/web2/dav/test/test_quota.py        (revision 26969)
++++ twisted/web2/dav/test/test_quota.py        (working copy)
+@@ -22,6 +22,7 @@
+ # DRI: Wilfredo Sanchez, wsanchez@apple.com
+ ##

++from twisted.internet.defer import waitForDeferred, deferredGenerator
+ from twisted.web2 import responsecode
+ from twisted.web2.iweb import IResponse
+ from twisted.web2.stream import FileStream
+@@ -34,16 +35,31 @@

+ class QuotaBase(twisted.web2.dav.test.util.TestCase):

+-    def createDocumentRoot(self):
++    def setUp(self):
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++
++        twisted.web2.dav.test.util.TestCase.setUp(self)
++
+         docroot = self.mktemp()
+         os.mkdir(docroot)
+         rootresource = self.resource_class(docroot)
+-        rootresource.setAccessControlList(self.grantInherit(davxml.All()))
+-        self.site = Site(rootresource)
+-        self.site.resource.setQuotaRoot(None, 100000)
+-        return docroot
++        d = waitForDeferred(rootresource.setAccessControlList(self.grantInherit(davxml.All())))
++        yield d
++        d = d.getResult()

++        self._site = Site(rootresource)
++        d = waitForDeferred(self._site.resource.setQuotaRoot(None, 100000))
++        yield d
++        d = d.getResult()
++        yield d

++    setUp = deferredGenerator(setUp)
++
++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
++
+     def checkQuota(self, value):
+         def _defer(quota):
+             self.assertEqual(quota, value)
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_reportpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_report.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_report.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_report.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+Index: twisted/web2/dav/test/test_report.py
+===================================================================
+--- twisted/web2/dav/test/test_report.py        (revision 26969)
++++ twisted/web2/dav/test/test_report.py        (working copy)
+@@ -34,6 +34,16 @@
+     &quot;&quot;&quot;
+     REPORT request
+     &quot;&quot;&quot;
++
++    def setUp(self):
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++        twisted.web2.dav.test.util.TestCase.setUp(self)
++        self._getSite()
++
++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
+     def test_REPORT_no_body(self):
+         &quot;&quot;&quot;
+         REPORT request with no body
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_resourcepatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_resource.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_resource.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_resource.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,7 +1,40 @@
</span><del>-=== modified file 'twisted/web2/dav/test/test_resource.py'
---- twisted/web2/dav/test/test_resource.py        2009-05-07 20:35:07 +0000
-+++ twisted/web2/dav/test/test_resource.py        2009-07-15 23:30:18 +0000
-@@ -376,7 +376,7 @@
</del><ins>+Index: twisted/web2/dav/test/test_resource.py
+===================================================================
+--- twisted/web2/dav/test/test_resource.py        (revision 26969)
++++ twisted/web2/dav/test/test_resource.py        (working copy)
+@@ -39,7 +39,13 @@
+     def setUp(self):
+         twisted.web2.dav.test.util.TestCase.setUp(self)
+         TestResource._cachedPropertyStores = {}
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++        self._getSite()

++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
+ class GenericDAVResource(TestCase):
+     def setUp(self):
+         TestCase.setUp(self)
+@@ -60,7 +66,7 @@
+             })
+         })

+-        self.site = Site(rootresource)
++        self._site = Site(rootresource)

+     def test_findChildren(self):
+         &quot;&quot;&quot;
+@@ -234,7 +240,7 @@
+         loginInterfaces = (IPrincipal,)

+         self.rootresource = rootresource
+-        self.site = Site(AuthenticationWrapper(
++        self._site = Site(AuthenticationWrapper(
+             self.rootresource,
+             portal,
+             credentialFactories,
+@@ -376,7 +382,7 @@
</ins><span class="cx">          return self.children is not None
</span><span class="cx">  
</span><span class="cx">      def listChildren(self):
</span><span class="lines">@@ -10,4 +43,11 @@
</span><span class="cx">  
</span><span class="cx">      def supportedPrivileges(self, request):
</span><span class="cx">          return succeed(davPrivilegeSet)
</span><del>-
</del><ins>+@@ -398,6 +404,7 @@

+     def setAccessControlList(self, acl):
+         self.acl = acl
++        return succeed(self.acl)

+     def accessControlList(self, request, **kwargs):
+         return succeed(self.acl)
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_staticpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_static.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_static.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_static.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+Index: twisted/web2/dav/test/test_static.py
+===================================================================
+--- twisted/web2/dav/test/test_static.py        (revision 26969)
++++ twisted/web2/dav/test/test_static.py        (working copy)
+@@ -28,6 +28,16 @@
+ from twisted.web2.test.test_server import SimpleRequest

+ class DAVFileTest(util.TestCase):
++
++    def setUp(self):
++        # Pre-fetch site, so the rest of the test doesn't have to defer
++        util.TestCase.setUp(self)
++        self._getSite()
++
++    def _getStoredSite(self):
++        return self._site
++    site = property(_getStoredSite)
++
+     def test_renderPrivileges(self):
+         &quot;&quot;&quot;
+         Verify that a directory listing includes children which you
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtesttest_xattrpropspatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_xattrprops.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_xattrprops.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.test_xattrprops.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,170 @@
</span><ins>+Index: twisted/web2/dav/test/test_xattrprops.py
+===================================================================
+--- twisted/web2/dav/test/test_xattrprops.py        (revision 26969)
++++ twisted/web2/dav/test/test_xattrprops.py        (working copy)
+@@ -5,10 +5,13 @@
+ Tests for L{twisted.web2.dav.xattrprops}.
+ &quot;&quot;&quot;

++import sys
+ from zlib import compress, decompress
+ from pickle import dumps
+ from cPickle import UnpicklingError

++from twisted.internet.defer import inlineCallbacks, returnValue
++from twisted.python import failure
+ from twisted.python.filepath import FilePath
+ from twisted.trial.unittest import TestCase
+ from twisted.web2.responsecode import NOT_FOUND, INTERNAL_SERVER_ERROR
+@@ -42,16 +45,18 @@
+         self.propertyStore = xattrPropertyStore(self.resource)


++    @inlineCallbacks
+     def test_getAbsent(self):
+         &quot;&quot;&quot;
+         L{xattrPropertyStore.get} raises L{HTTPError} with a I{NOT FOUND}
+         response code if passed the name of an attribute for which there is no
+         corresponding value.
+         &quot;&quot;&quot;
+-        error = self.assertRaises(HTTPError, self.propertyStore.get, (&quot;foo&quot;, &quot;bar&quot;))
++        error = (yield self.assertRaisesDeferred(HTTPError, self.propertyStore.get, (&quot;foo&quot;, &quot;bar&quot;)))
+         self.assertEquals(error.response.code, NOT_FOUND)


++    @inlineCallbacks
+     def _forbiddenTest(self, method):
+         # Remove access to the directory containing the file so that getting
+         # extended attributes from it fails with EPERM.
+@@ -62,10 +67,10 @@

+         # Try to get a property from it - and fail.
+         document = self._makeValue()
+-        error = self.assertRaises(
++        error = (yield self.assertRaisesDeferred(
+             HTTPError,
+             getattr(self.propertyStore, method),
+-            document.root_element.qname())
++            document.root_element.qname()))

+         # Make sure that the status is FORBIDDEN, a roughly reasonable mapping
+         # of the EPERM failure.
+@@ -106,11 +111,12 @@
+         return self.attrs[attribute]


++    @inlineCallbacks
+     def _checkValue(self, originalDocument):
+         property = originalDocument.root_element.qname()

+         # Try to load it via xattrPropertyStore.get
+-        loadedDocument = self.propertyStore.get(property)
++        loadedDocument = (yield self.propertyStore.get(property))

+         # XXX Why isn't this a WebDAVDocument?
+         self.assertIsInstance(loadedDocument, Depth)
+@@ -178,6 +184,7 @@
+             decompress(self._getValue(document)), document.toxml())


++    @inlineCallbacks
+     def test_getInvalid(self):
+         &quot;&quot;&quot;
+         If the value associated with the property name passed to
+@@ -190,7 +197,7 @@
+             &quot;random garbage goes here! \0 that nul is definitely garbage&quot;)

+         property = document.root_element.qname()
+-        error = self.assertRaises(HTTPError, self.propertyStore.get, property)
++        error = (yield self.assertRaisesDeferred(HTTPError, self.propertyStore.get, property))
+         self.assertEquals(error.response.code, INTERNAL_SERVER_ERROR)
+         self.assertEquals(
+             len(self.flushLoggedErrors(UnpicklingError)), 1)
+@@ -227,6 +234,7 @@
+         self.assertRaises(KeyError, self._getValue, document)


++    @inlineCallbacks
+     def test_deleteErrors(self):
+         &quot;&quot;&quot;
+         If there is a problem deleting the specified property (aside from the
+@@ -240,15 +248,16 @@

+         # Try to delete a property from it - and fail.
+         document = self._makeValue()
+-        error = self.assertRaises(
++        error = (yield self.assertRaisesDeferred(
+             HTTPError,
+-            self.propertyStore.delete, document.root_element.qname())
++            self.propertyStore.delete, document.root_element.qname()))

+         # Make sure that the status is NOT FOUND, a roughly reasonable mapping
+         # of the EEXIST failure.
+         self.assertEquals(error.response.code, NOT_FOUND)


++    @inlineCallbacks
+     def test_contains(self):
+         &quot;&quot;&quot;
+         L{xattrPropertyStore.contains} returns C{True} if the given property
+@@ -256,10 +265,10 @@
+         &quot;&quot;&quot;
+         document = self._makeValue()
+         self.assertFalse(
+-            self.propertyStore.contains(document.root_element.qname()))
++            (yield self.propertyStore.contains(document.root_element.qname())))
+         self._setValue(document, document.toxml())
+         self.assertTrue(
+-            self.propertyStore.contains(document.root_element.qname()))
++            (yield self.propertyStore.contains(document.root_element.qname())))


+     def test_containsError(self):
+@@ -272,6 +281,7 @@
+         self._forbiddenTest('contains')


++    @inlineCallbacks
+     def test_list(self):
+         &quot;&quot;&quot;
+         L{xattrPropertyStore.list} returns a C{list} of property names
+@@ -281,10 +291,11 @@
+         self.attrs[prefix + '{foo}bar'] = 'baz'
+         self.attrs[prefix + '{bar}baz'] = 'quux'
+         self.assertEquals(
+-            set(self.propertyStore.list()),
++            set((yield self.propertyStore.list())),
+             set([(u'foo', u'bar'), (u'bar', u'baz')]))


++    @inlineCallbacks
+     def test_listError(self):
+         &quot;&quot;&quot;
+         If there is a problem checking if the specified property exists (aside
+@@ -301,8 +312,25 @@

+         # Try to get a property from it - and fail.
+         document = self._makeValue()
+-        error = self.assertRaises(HTTPError, self.propertyStore.list)
++        error = (yield self.assertRaisesDeferred(HTTPError, self.propertyStore.list))

+         # Make sure that the status is FORBIDDEN, a roughly reasonable mapping
+         # of the EPERM failure.
+         self.assertEquals(error.response.code, FORBIDDEN)
++
++
++    @inlineCallbacks
++    def assertRaisesDeferred(self, exception, f, *args, **kwargs):
++        try:
++            result = (yield f(*args, **kwargs))
++        except exception, inst:
++            returnValue(inst)
++        except:
++            raise self.failureException('%s raised instead of %s:\n %s'
++                                        % (sys.exc_info()[0],
++                                           exception.__name__,
++                                           failure.Failure().getTraceback()))
++        else:
++            raise self.failureException('%s not raised (%r returned)'
++                                        % (exception.__name__, result))
++
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davtestutilpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.util.patch (0 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.util.patch                                (rev 0)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.test.util.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+Index: twisted/web2/dav/test/util.py
+===================================================================
+--- twisted/web2/dav/test/util.py        (revision 26969)
++++ twisted/web2/dav/test/util.py        (working copy)
+@@ -31,7 +31,7 @@

+ from twisted.python import log
+ from twisted.trial import unittest
+-from twisted.internet.defer import Deferred
++from twisted.internet.defer import Deferred, waitForDeferred, deferredGenerator, succeed

+ from twisted.web2.http import HTTPError, StatusResponse
+ from twisted.web2 import responsecode
+@@ -60,22 +60,24 @@
+             ))

+         doc = davxml.WebDAVDocument.fromString(property)
+-        return doc.root_element
++        return succeed(doc.root_element)

+     def set(self, property):
+         self._dict[property.qname()] = property.toxml()
++        return succeed(None)

+     def delete(self, qname):
+         try:
+             del(self._dict[qname])
+         except KeyError:
+             pass
++        return succeed(None)

+     def contains(self, qname):
+-        return qname in self._dict
++        return succeed(qname in self._dict)

+     def list(self):
+-        return self._dict.keys()
++        return succeed(self._dict.keys())

+ class TestFile (DAVFile):
+     _cachedPropertyStores = {}
+@@ -121,7 +123,9 @@
+         docroot = self.mktemp()
+         os.mkdir(docroot)
+         rootresource = self.resource_class(docroot)
+-        rootresource.setAccessControlList(self.grantInherit(davxml.All()))
++        d = waitForDeferred(rootresource.setAccessControlList(self.grantInherit(davxml.All())))
++        yield d
++        d = d.getResult()

+         dirnames = (
+             os.path.join(docroot, &quot;dir1&quot;),                          # 0
+@@ -149,17 +153,23 @@
+         for dirname in (docroot,) + dirnames[3:8+1]:
+             for filename in filenames[:5]:
+                 copy(filename, dirname)
+-        return docroot
++        yield docroot

++    createDocumentRoot = deferredGenerator(createDocumentRoot)

++
+     def _getDocumentRoot(self):
+         if not hasattr(self, &quot;_docroot&quot;):
+             log.msg(&quot;Setting up docroot for %s&quot; % (self.__class__,))

+-            self._docroot = self.createDocumentRoot()
++            d = waitForDeferred(self.createDocumentRoot())
++            yield d
++            self._docroot = d.getResult()

+-        return self._docroot
++        yield self._docroot

++    _getDocumentRoot = deferredGenerator(_getDocumentRoot)
++
+     def _setDocumentRoot(self, value):
+         self._docroot = value

+@@ -167,10 +177,13 @@

+     def _getSite(self):
+         if not hasattr(self, &quot;_site&quot;):
+-            rootresource = self.resource_class(self.docroot)
++            d = waitForDeferred(self.docroot)
++            yield d
++            rootresource = self.resource_class(d.getResult())
+             rootresource.setAccessControlList(self.grantInherit(davxml.All()))
+             self._site = Site(rootresource)
+-        return self._site
++        yield self._site
++    _getSite = deferredGenerator(_getSite)

+     def _setSite(self, site):
+         self._site = site
+@@ -191,11 +204,15 @@
+         Creates a new directory in the document root and returns its path and
+         URI.
+         &quot;&quot;&quot;
+-        path = mkdtemp(prefix=prefix + &quot;_&quot;, dir=self.docroot)
++        d = waitForDeferred(self.docroot)
++        yield d
++        path = mkdtemp(prefix=prefix + &quot;_&quot;, dir=d.getResult())
+         uri  = joinURL(&quot;/&quot;, url_quote(os.path.basename(path))) + &quot;/&quot;

+-        return (path, uri)
++        yield (path, uri)

++    mkdtemp = deferredGenerator(mkdtemp)
++
+     def send(self, request, callback):
+         log.msg(&quot;Sending %s request for URI %s&quot; % (request.method, request.uri))

</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2davxattrpropspatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,20 +1,120 @@
</span><del>-=== modified file 'twisted/web2/dav/xattrprops.py'
---- twisted/web2/dav/xattrprops.py        2009-06-03 23:46:41 +0000
-+++ twisted/web2/dav/xattrprops.py        2009-07-15 23:30:18 +0000
-@@ -49,6 +49,7 @@
</del><ins>+Index: twisted/web2/dav/xattrprops.py
+===================================================================
+--- twisted/web2/dav/xattrprops.py        (revision 26969)
++++ twisted/web2/dav/xattrprops.py        (working copy)
+@@ -47,6 +47,8 @@
+ if getattr(xattr, 'xattr', None) is None:
+     raise ImportError(&quot;wrong xattr package imported&quot;)
</ins><span class="cx">  
</span><ins>++from twisted.internet.defer import inlineCallbacks, returnValue, succeed
++
</ins><span class="cx">  from twisted.python.util import untilConcludes
</span><span class="cx">  from twisted.python.failure import Failure
</span><del>-+from twisted.internet.defer import succeed
</del><span class="cx">  from twisted.python import log
</span><del>- from twisted.web2 import responsecode
- from twisted.web2.http import HTTPError, StatusResponse
-@@ -188,6 +189,7 @@
</del><ins>+@@ -124,18 +126,18 @@
+         try:
+             data = self.attrs.get(self._encode(qname))
+         except KeyError:
+-            raise HTTPError(StatusResponse(
++            return Failure(HTTPError(StatusResponse(
+                     responsecode.NOT_FOUND,
+-                    &quot;No such property: {%s}%s&quot; % qname))
++                    &quot;No such property: {%s}%s&quot; % qname)))
+         except IOError, e:
+             if e.errno in _ATTR_MISSING:
+-                raise HTTPError(StatusResponse(
++                return Failure(HTTPError(StatusResponse(
+                         responsecode.NOT_FOUND,
+-                        &quot;No such property: {%s}%s&quot; % qname))
++                        &quot;No such property: {%s}%s&quot; % qname)))
+             else:
+-                raise HTTPError(StatusResponse(
++                return Failure(HTTPError(StatusResponse(
+                         statusForFailure(Failure()),
+-                        &quot;Unable to read property: {%s}%s&quot; % qname))
++                        &quot;Unable to read property: {%s}%s&quot; % qname)))
</ins><span class="cx">  
</span><ins>+         #
+         # Unserialize XML data from an xattr.  The storage format has changed
+@@ -165,15 +167,15 @@
+                 format = &quot;Invalid property value stored on server: {%s}%s %s&quot;
+                 msg = format % (qname[0], qname[1], data)
+                 log.err(None, msg)
+-                raise HTTPError(
+-                    StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg))
++                return Failure (HTTPError(
++                    StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg)))
+             else:
+                 legacy = True

+         if legacy:
+             self.set(doc.root_element)

+-        return doc.root_element
++        return succeed(doc.root_element)


+     def set(self, property):
+@@ -188,6 +190,7 @@

</ins><span class="cx">          # Update the resource because we've modified it
</span><span class="cx">          self.resource.fp.restat()
</span><span class="cx"> +        return succeed(None)
</span><span class="cx">  
</span><span class="cx">  
</span><span class="cx">      def delete(self, qname):
</span><del>-
</del><ins>+@@ -208,10 +211,11 @@
+                 if e.errno not in _ATTR_MISSING:
+                     raise
+         except:
+-            raise HTTPError(
++            return Failure(HTTPError(
+                 StatusResponse(
+                     statusForFailure(Failure()),
+-                    &quot;Unable to delete property: &quot; + key))
++                    &quot;Unable to delete property: &quot; + key)))
++        return succeed(None)


+     def contains(self, qname):
+@@ -228,16 +232,16 @@
+         try:
+             self.attrs.get(key)
+         except KeyError:
+-            return False
++            return succeed(False)
+         except IOError, e:
+             if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT:
+-                return False
+-            raise HTTPError(
++                return succeed(False)
++            return Failure(HTTPError(
+                 StatusResponse(
+                     statusForFailure(Failure()),
+-                    &quot;Unable to read property: &quot; + key))
++                    &quot;Unable to read property: &quot; + key)))
+         else:
+-            return True
++            return succeed(True)


+     def list(self):
+@@ -252,13 +256,14 @@
+         try:
+             attrs = iter(self.attrs)
+         except IOError, e:
+-            raise HTTPError(
++            return Failure(HTTPError(
+                 StatusResponse(
+                     statusForFailure(Failure()),
+-                    &quot;Unable to list properties: &quot; + self.resource.fp.path))
++                    &quot;Unable to list properties: &quot; + self.resource.fp.path)))
+         else:
+-            return [
+-                self._decode(name)
++            return succeed(
++                [self._decode(name)
+                 for name
+                 in attrs
+                 if name.startswith(prefix)]
++            )
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2errorpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.error.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.error.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.error.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><del>-=== modified file 'twisted/web2/error.py'
---- twisted/web2/error.py        2005-11-22 22:59:59 +0000
-+++ twisted/web2/error.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/error.py
+===================================================================
+--- twisted/web2/error.py        (revision 26969)
++++ twisted/web2/error.py        (working copy)
</ins><span class="cx"> @@ -92,7 +92,7 @@
</span><span class="cx">              &quot;&lt;body&gt;&lt;h1&gt;%s&lt;/h1&gt;%s&lt;/body&gt;&lt;/html&gt;&quot;) % (
</span><span class="cx">          response.code, title, title, message)
</span><span class="lines">@@ -10,4 +11,3 @@
</span><span class="cx">      response.stream = stream.MemoryStream(body)
</span><span class="cx">      
</span><span class="cx">      return response
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2serverpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.server.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.server.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.server.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -28,4 +28,3 @@
</span><span class="cx">          # This is where CONNECT would go if we wanted it
</span><span class="cx">          return None
</span><span class="cx">  
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3libpatchesTwistedtwistedweb2staticpatch"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.static.patch (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.static.patch        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/lib-patches/Twisted/twisted.web2.static.patch        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -1,16 +1,88 @@
</span><del>-=== modified file 'twisted/web2/static.py'
---- twisted/web2/static.py        2009-04-20 17:38:06 +0000
-+++ twisted/web2/static.py        2009-07-15 23:30:18 +0000
</del><ins>+Index: twisted/web2/static.py
+===================================================================
+--- twisted/web2/static.py        (revision 26969)
++++ twisted/web2/static.py        (working copy)
</ins><span class="cx"> @@ -16,7 +16,7 @@
</span><span class="cx">  
</span><span class="cx">  # Twisted Imports
</span><span class="cx">  from twisted.python import filepath
</span><span class="cx"> -from twisted.internet.defer import maybeDeferred
</span><del>-+from twisted.internet.defer import maybeDeferred, succeed
</del><ins>++from twisted.internet.defer import maybeDeferred, succeed, deferredGenerator, waitForDeferred
</ins><span class="cx">  from zope.interface import implements
</span><span class="cx">  
</span><span class="cx">  class MetaDataMixin(object):
</span><del>-@@ -291,12 +291,13 @@
</del><ins>+@@ -28,7 +28,7 @@
+         &quot;&quot;&quot;
+         @return: The current etag for the resource if available, None otherwise.
+         &quot;&quot;&quot;
+-        return None
++        return succeed(None)

+     def lastModified(self):
+         &quot;&quot;&quot;
+@@ -76,18 +76,26 @@
+     def checkPreconditions(self, request):
+         # This code replaces the code in resource.RenderMixin
+         if request.method not in (&quot;GET&quot;, &quot;HEAD&quot;):
++            etag = waitForDeferred(self.etag())
++            yield etag
++            etag = etag.getResult()
+             http.checkPreconditions(
+                 request,
+                 entityExists = self.exists(),
+-                etag = self.etag(),
++                etag = etag,
+                 lastModified = self.lastModified(),
+             )

+         # Check per-method preconditions
+         method = getattr(self, &quot;preconditions_&quot; + request.method, None)
+         if method:
+-            return method(request)
++            result = waitForDeferred(method(request))
++            yield result
++            result = result.getResult()
++            yield result

++    checkPreconditions = deferredGenerator(checkPreconditions)
++
+     def renderHTTP(self, request):
+         &quot;&quot;&quot;
+         See L{resource.RenderMixIn.renderHTTP}.
+@@ -132,8 +140,8 @@

+     def etag(self):
+         lastModified = self.lastModified()
+-        return http_headers.ETag(&quot;%X-%X&quot; % (lastModified, hash(self.data)),
+-                                 weak=(time.time() - lastModified &lt;= 1))
++        return succeed(http_headers.ETag(&quot;%X-%X&quot; % (lastModified, hash(self.data)),
++                                 weak=(time.time() - lastModified &lt;= 1)))

+     def lastModified(self):
+         return self.creationDate()
+@@ -217,7 +225,7 @@
+         return self.fp.exists()

+     def etag(self):
+-        if not self.fp.exists(): return None
++        if not self.fp.exists(): return succeed(None)

+         st = self.fp.statinfo

+@@ -228,10 +236,10 @@
+         #
+         weak = (time.time() - st.st_mtime &lt;= 1)

+-        return http_headers.ETag(
++        return succeed(http_headers.ETag(
+             &quot;%X-%X-%X&quot; % (st.st_ino, st.st_size, st.st_mtime),
+             weak=weak
+-        )
++        ))

+     def lastModified(self):
+         if self.fp.exists():
+@@ -291,12 +299,13 @@
</ins><span class="cx">          self.ignoredExts.append(ext)
</span><span class="cx">  
</span><span class="cx">      def directoryListing(self):
</span><span class="lines">@@ -30,7 +102,7 @@
</span><span class="cx">      def putChild(self, name, child):
</span><span class="cx">          &quot;&quot;&quot;
</span><span class="cx">          Register a child with the given name with this resource.
</span><del>-@@ -329,7 +330,7 @@
</del><ins>+@@ -329,7 +338,7 @@
</ins><span class="cx">          children = self.putChildren.keys()
</span><span class="cx">          if self.fp.isdir():
</span><span class="cx">              children += [c for c in self.fp.listdir() if c not in children]
</span><span class="lines">@@ -39,7 +111,7 @@
</span><span class="cx">  
</span><span class="cx">      def locateChild(self, req, segments):
</span><span class="cx">          &quot;&quot;&quot;
</span><del>-@@ -387,17 +388,17 @@
</del><ins>+@@ -387,17 +396,17 @@
</ins><span class="cx">                  ifp = self.fp.childSearchPreauth(*self.indexNames)
</span><span class="cx">                  if ifp:
</span><span class="cx">                      # Render from the index file
</span><span class="lines">@@ -66,4 +138,3 @@
</span><span class="cx">  
</span><span class="cx">          try:
</span><span class="cx">              f = self.fp.open()
</span><del>-
</del></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavdirectorycalendarpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/directory/calendar.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/directory/calendar.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/directory/calendar.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -299,9 +299,10 @@
</span><span class="cx">         if hasattr(self, &quot;clientNotifier&quot;):
</span><span class="cx">             self.clientNotifier.disableNotify()
</span><span class="cx"> 
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def setupFreeBusy(_, child):
</span><span class="cx">             # Default calendar is initially opaque to freebusy
</span><del>-            child.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
</del><ins>+            yield child.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
</ins><span class="cx"> 
</span><span class="cx">             # FIXME: Shouldn't have to call provision() on another resource
</span><span class="cx">             # We cheat here because while inbox will auto-provision itself when located,
</span><span class="lines">@@ -314,9 +315,9 @@
</span><span class="cx">             inbox.processFreeBusyCalendar(childURL, True)
</span><span class="cx"> 
</span><span class="cx">             # Default calendar is marked as the default for scheduling
</span><del>-            inbox.writeDeadProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(childURL)))
</del><ins>+            yield inbox.writeDeadProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(childURL)))
</ins><span class="cx"> 
</span><del>-            return self
</del><ins>+            returnValue(self)
</ins><span class="cx"> 
</span><span class="cx">         try:
</span><span class="cx">             d = self.provision()
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmailpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/mail.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/mail.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/mail.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -245,7 +245,7 @@
</span><span class="cx">         return None
</span><span class="cx"> 
</span><span class="cx">     def checkPreconditions(self, request):
</span><del>-        return None
</del><ins>+        return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">     def render(self, request):
</span><span class="cx">         output = &quot;&quot;&quot;&lt;html&gt;
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmemcachepropspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/memcacheprops.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/memcacheprops.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/memcacheprops.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> from twisted.python.filepath import FilePath
</span><span class="cx"> from twisted.web2 import responsecode
</span><span class="cx"> from twisted.web2.http import HTTPError, StatusResponse
</span><ins>+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
</ins><span class="cx"> 
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.log import LoggingMixIn, Logger
</span><span class="lines">@@ -68,6 +69,7 @@
</span><span class="cx"> 
</span><span class="cx">         return MemcachePropertyCollection._memcacheClient
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def propertyCache(self):
</span><span class="cx">         # The property cache has this format:
</span><span class="cx">         #  {
</span><span class="lines">@@ -82,13 +84,14 @@
</span><span class="cx">         #    ...,
</span><span class="cx">         #  }
</span><span class="cx">         if not hasattr(self, &quot;_propertyCache&quot;):
</span><del>-            self._propertyCache = self._loadCache()
-        return self._propertyCache
</del><ins>+            self._propertyCache = (yield self._loadCache())
+        returnValue(self._propertyCache)
</ins><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def childCache(self, child):
</span><span class="cx">         path = child.fp.path
</span><span class="cx">         key = self._keyForPath(path)
</span><del>-        propertyCache = self.propertyCache()
</del><ins>+        propertyCache = (yield self.propertyCache())
</ins><span class="cx"> 
</span><span class="cx">         try:
</span><span class="cx">             childCache, token = propertyCache[key]
</span><span class="lines">@@ -100,7 +103,7 @@
</span><span class="cx">             #log.error(message)
</span><span class="cx">             #raise AssertionError(message)
</span><span class="cx"> 
</span><del>-        return propertyCache, key, childCache, token
</del><ins>+        returnValue((propertyCache, key, childCache, token))
</ins><span class="cx"> 
</span><span class="cx">     def _keyForPath(self, path):
</span><span class="cx">         key = &quot;|&quot;.join((
</span><span class="lines">@@ -109,6 +112,7 @@
</span><span class="cx">         ))
</span><span class="cx">         return md5(key).hexdigest()
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def _loadCache(self, childNames=None):
</span><span class="cx">         if childNames is None:
</span><span class="cx">             abortIfMissing = False
</span><span class="lines">@@ -117,14 +121,14 @@
</span><span class="cx">             if childNames:
</span><span class="cx">                 abortIfMissing = True
</span><span class="cx">             else:
</span><del>-                return {}
</del><ins>+                returnValue({})
</ins><span class="cx"> 
</span><span class="cx">         self.log_debug(&quot;Loading cache for %s&quot; % (self.collection,))
</span><span class="cx"> 
</span><span class="cx">         client = self.memcacheClient()
</span><span class="cx">         assert client is not None, &quot;OMG no cache!&quot;
</span><span class="cx">         if client is None:
</span><del>-            return None
</del><ins>+            returnValue(None)
</ins><span class="cx"> 
</span><span class="cx">         keys = tuple((
</span><span class="cx">             (self._keyForPath(self.collection.fp.child(childName).path), childName)
</span><span class="lines">@@ -153,12 +157,12 @@
</span><span class="cx">             if abortIfMissing:
</span><span class="cx">                 raise MemcacheError(&quot;Unable to fully load cache for %s&quot; % (self.collection,))
</span><span class="cx"> 
</span><del>-            loaded = self._buildCache(childNames=missing)
-            loaded = self._loadCache(childNames=(FilePath(name).basename() for name in loaded.iterkeys()))
</del><ins>+            loaded = (yield self._buildCache(childNames=missing))
+            loaded = (yield self._loadCache(childNames=(FilePath(name).basename() for name in loaded.iterkeys())))
</ins><span class="cx"> 
</span><span class="cx">             result.update(loaded.iteritems())
</span><span class="cx"> 
</span><del>-        return result
</del><ins>+        returnValue(result)
</ins><span class="cx"> 
</span><span class="cx">     def _storeCache(self, cache):
</span><span class="cx">         self.log_debug(&quot;Storing cache for %s&quot; % (self.collection,))
</span><span class="lines">@@ -173,36 +177,33 @@
</span><span class="cx">         if client is not None:
</span><span class="cx">             client.set_multi(values, time=self.cacheTimeout)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def _buildCache(self, childNames=None):
</span><span class="cx">         if childNames is None:
</span><span class="cx">             childNames = self.collection.listChildren()
</span><span class="cx">         elif not childNames:
</span><del>-            return {}
</del><ins>+            returnValue({})
</ins><span class="cx"> 
</span><span class="cx">         self.log_debug(&quot;Building cache for %s&quot; % (self.collection,))
</span><span class="cx"> 
</span><span class="cx">         cache = {}
</span><span class="cx">         ds = []
</span><span class="cx">         for childName in childNames:
</span><del>-            d = self.collection.getChild(childName)
-            def _gotChild(child):
-                if child is not None:
-                    propertyStore = child.deadProperties()
-                    props = {}
-                    for qname in propertyStore.list(cache=False):
-                        props[qname] = propertyStore.get(qname, cache=False)
</del><ins>+            child = (yield self.collection.getChild(childName))
+            if child is not None:
+                propertyStore = child.deadProperties()
+                props = {}
+                for qname in (yield propertyStore.list(cache=False)):
+                    props[qname] = (yield propertyStore.get(qname, cache=False))
</ins><span class="cx"> 
</span><del>-                    cache[child.fp.path] = props
-            d.addCallback(_gotChild)
-            ds.append(d)
-        def _collectedChildren(_):
-            self._storeCache(cache)
-            return cache
-        return DeferredList(ds).addCallback(_collectedChildren)
</del><ins>+                cache[child.fp.path] = props
+        self._storeCache(cache)
+        returnValue(cache)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def setProperty(self, child, property, delete=False):
</span><del>-        propertyCache, key, childCache, token = self.childCache(child)
</del><ins>+        propertyCache, key, childCache, token = (yield self.childCache(child))
</ins><span class="cx"> 
</span><span class="cx">         if delete:
</span><span class="cx">             qname = property
</span><span class="lines">@@ -230,12 +231,12 @@
</span><span class="cx"> 
</span><span class="cx">                 finally:
</span><span class="cx">                     # Re-fetch the properties for this child
</span><del>-                    loaded = self._loadCache(childNames=(child.fp.basename(),))
</del><ins>+                    loaded = (yield self._loadCache(childNames=(child.fp.basename(),)))
</ins><span class="cx">                     propertyCache.update(loaded.iteritems())
</span><span class="cx"> 
</span><span class="cx">                 retries -= 1
</span><span class="cx"> 
</span><del>-                propertyCache, key, childCache, token = self.childCache(child)
</del><ins>+                propertyCache, key, childCache, token = (yield self.childCache(child))
</ins><span class="cx"> 
</span><span class="cx">                 if delete:
</span><span class="cx">                     if childCache.has_key(qname):
</span><span class="lines">@@ -253,10 +254,11 @@
</span><span class="cx">     def deleteProperty(self, child, qname):
</span><span class="cx">         return self.setProperty(child, qname, delete=True)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def flushCache(self, child):
</span><span class="cx">         path = child.fp.path
</span><span class="cx">         key = self._keyForPath(path)
</span><del>-        propertyCache = self.propertyCache()
</del><ins>+        propertyCache = (yield self.propertyCache())
</ins><span class="cx"> 
</span><span class="cx">         if key in propertyCache:
</span><span class="cx">             del propertyCache[key]
</span><span class="lines">@@ -276,20 +278,22 @@
</span><span class="cx">             self.child = child
</span><span class="cx">             self.childPropertyStore = childPropertyStore
</span><span class="cx"> 
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def propertyCache(self):
</span><span class="cx">             path = self.child.fp.path
</span><span class="cx">             key = self.parentPropertyCollection._keyForPath(path)
</span><del>-            parentPropertyCache = self.parentPropertyCollection.propertyCache()
-            return parentPropertyCache.get(key, ({}, None))[0]
</del><ins>+            parentPropertyCache = (yield self.parentPropertyCollection.propertyCache())
+            returnValue(parentPropertyCache.get(key, ({}, None))[0])
</ins><span class="cx"> 
</span><span class="cx">         def flushCache(self):
</span><span class="cx">             self.parentPropertyCollection.flushCache(self.child)
</span><span class="cx"> 
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def get(self, qname, cache=True):
</span><span class="cx">             if cache:
</span><del>-                propertyCache = self.propertyCache()
</del><ins>+                propertyCache = (yield self.propertyCache())
</ins><span class="cx">                 if qname in propertyCache:
</span><del>-                    return propertyCache[qname]
</del><ins>+                    returnValue(propertyCache[qname])
</ins><span class="cx">                 else:
</span><span class="cx">                     raise HTTPError(StatusResponse(
</span><span class="cx">                         responsecode.NOT_FOUND,
</span><span class="lines">@@ -298,7 +302,7 @@
</span><span class="cx"> 
</span><span class="cx">             self.log_debug(&quot;Read for %s on %s&quot;
</span><span class="cx">                            % (qname, self.childPropertyStore.resource.fp.path))
</span><del>-            return self.childPropertyStore.get(qname)
</del><ins>+            returnValue((yield self.childPropertyStore.get(qname)))
</ins><span class="cx"> 
</span><span class="cx">         def set(self, property):
</span><span class="cx">             self.log_debug(&quot;Write for %s on %s&quot;
</span><span class="lines">@@ -306,6 +310,7 @@
</span><span class="cx"> 
</span><span class="cx">             self.parentPropertyCollection.setProperty(self.child, property)
</span><span class="cx">             self.childPropertyStore.set(property)
</span><ins>+            return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">         def delete(self, qname):
</span><span class="cx">             self.log_debug(&quot;Delete for %s on %s&quot;
</span><span class="lines">@@ -313,21 +318,24 @@
</span><span class="cx"> 
</span><span class="cx">             self.parentPropertyCollection.deleteProperty(self.child, qname)
</span><span class="cx">             self.childPropertyStore.delete(qname)
</span><ins>+            return succeed(None)
</ins><span class="cx"> 
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def contains(self, qname, cache=True):
</span><span class="cx">             if cache:
</span><del>-                propertyCache = self.propertyCache()
-                return qname in propertyCache
</del><ins>+                propertyCache = (yield self.propertyCache())
+                returnValue(qname in propertyCache)
</ins><span class="cx"> 
</span><span class="cx">             self.log_debug(&quot;Contains for %s&quot;
</span><span class="cx">                            % (self.childPropertyStore.resource.fp.path,))
</span><del>-            return self.childPropertyStore.contains(qname)
</del><ins>+            returnValue(self.childPropertyStore.contains(qname))
</ins><span class="cx"> 
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def list(self, cache=True):
</span><span class="cx">             if cache:
</span><del>-                propertyCache = self.propertyCache()
-                return propertyCache.iterkeys()
</del><ins>+                propertyCache = (yield self.propertyCache())
+                returnValue(propertyCache.iterkeys())
</ins><span class="cx"> 
</span><span class="cx">             self.log_debug(&quot;List for %s&quot;
</span><span class="cx">                            % (self.childPropertyStore.resource.fp.path,))
</span><del>-            return self.childPropertyStore.list()
</del><ins>+            returnValue(self.childPropertyStore.list())
</ins></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethoddelete_commonpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/delete_common.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/delete_common.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/delete_common.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">         self.depth = depth
</span><span class="cx">         self.internal_request = internal_request
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def validIfScheduleMatch(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Check for If-ScheduleTag-Match header behavior.
</span><span class="lines">@@ -63,8 +64,8 @@
</span><span class="cx">             if header:
</span><span class="cx">                 # Do &quot;precondition&quot; test
</span><span class="cx">                 matched = False
</span><del>-                if self.resource.exists() and self.resource.hasDeadProperty(ScheduleTag):
-                    scheduletag = self.resource.readDeadProperty(ScheduleTag)
</del><ins>+                if self.resource.exists() and (yield self.resource.hasDeadProperty(ScheduleTag)):
+                    scheduletag = (yield self.resource.readDeadProperty(ScheduleTag))
</ins><span class="cx">                     matched = (scheduletag == header)
</span><span class="cx">                 if not matched:
</span><span class="cx">                     log.debug(&quot;If-Schedule-Tag-Match: header value '%s' does not match resource value '%s'&quot; % (header, scheduletag,))
</span><span class="lines">@@ -130,7 +131,7 @@
</span><span class="cx">         # as the iTIP operation may fail and may need to prevent the delete from happening.
</span><span class="cx">     
</span><span class="cx">         # Do If-Schedule-Tag-Match behavior first
</span><del>-        self.validIfScheduleMatch()
</del><ins>+        yield self.validIfScheduleMatch()
</ins><span class="cx"> 
</span><span class="cx">         # Do quota checks before we start deleting things
</span><span class="cx">         myquota = (yield delresource.quota(self.request))
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethodgetpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/get.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/get.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/get.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     # Look for calendar access restriction on existing resource.
</span><span class="cx">     if self.exists():
</span><span class="cx">         try:
</span><del>-            access = self.readDeadProperty(TwistedCalendarAccessProperty)
</del><ins>+            access = (yield self.readDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx">         except HTTPError:
</span><span class="cx">             access = None
</span><span class="cx">             
</span><span class="lines">@@ -65,8 +65,8 @@
</span><span class="cx">     response = (yield super(CalDAVFile, self).http_GET(request))
</span><span class="cx">     
</span><span class="cx">     # Add Schedule-Tag header if property is present
</span><del>-    if self.exists() and self.hasDeadProperty(ScheduleTag):
-        scheduletag = self.readDeadProperty(ScheduleTag)
</del><ins>+    if self.exists() and (yield self.hasDeadProperty(ScheduleTag)):
+        scheduletag = (yield self.readDeadProperty(ScheduleTag))
</ins><span class="cx">         if scheduletag:
</span><span class="cx">             response.headers.setHeader(&quot;Schedule-Tag&quot;, str(scheduletag))
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethodmkcalendarpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/mkcalendar.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/mkcalendar.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/mkcalendar.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx">             for property in makecalendar.children[0].children[0].children:
</span><span class="cx">                 try:
</span><span class="cx">                     if property.qname() == (caldavxml.caldav_namespace, &quot;supported-calendar-component-set&quot;):
</span><del>-                        self.writeDeadProperty(property)
</del><ins>+                        (yield self.writeDeadProperty(property))
</ins><span class="cx">                     else:
</span><span class="cx">                         yield self.writeProperty(property, request)
</span><span class="cx">                 except HTTPError:
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethodput_commonpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/put_common.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/put_common.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/put_common.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -281,7 +281,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Basic validation
</span><span class="cx">         yield self.validCopyMoveOperation()
</span><del>-        self.validIfScheduleMatch()
</del><ins>+        yield self.validIfScheduleMatch()
</ins><span class="cx"> 
</span><span class="cx">         if self.destinationcal:
</span><span class="cx">             # Valid resource name check
</span><span class="lines">@@ -393,6 +393,7 @@
</span><span class="cx">                     log.debug(msg)
</span><span class="cx">                     raise HTTPError(StatusResponse(responsecode.FORBIDDEN, msg))
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def validIfScheduleMatch(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Check for If-ScheduleTag-Match header behavior.
</span><span class="lines">@@ -404,12 +405,14 @@
</span><span class="cx">             header = self.request.headers.getHeader(&quot;If-Schedule-Tag-Match&quot;)
</span><span class="cx">             if header:
</span><span class="cx">                 # Do &quot;precondition&quot; test
</span><del>-                
</del><ins>+
</ins><span class="cx">                 # If COPY/MOVE get Schedule-Tag on source, else use destination
</span><del>-                def _getScheduleTag(resource):
-                    return resource.readDeadProperty(ScheduleTag) if resource.exists() and resource.hasDeadProperty(ScheduleTag) else None
</del><ins>+                resource = self.source if self.source else self.destination
+                if resource.exists() and (yield resource.hasDeadProperty(ScheduleTag)):
+                    scheduletag = (yield resource.readDeadProperty(ScheduleTag))
+                else:
+                    scheduletag = None
</ins><span class="cx"> 
</span><del>-                scheduletag = _getScheduleTag(self.source if self.source else self.destination)
</del><span class="cx">                 if scheduletag != header:
</span><span class="cx">                     log.debug(&quot;If-Schedule-Tag-Match: header value '%s' does not match resource value '%s'&quot; % (header, scheduletag,))
</span><span class="cx">                     raise HTTPError(responsecode.PRECONDITION_FAILED)
</span><span class="lines">@@ -539,6 +542,7 @@
</span><span class="cx"> 
</span><span class="cx">         return result, message
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def validAccess(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Make sure that the X-CALENDARSERVER-ACCESS property is properly dealt with.
</span><span class="lines">@@ -553,25 +557,19 @@
</span><span class="cx">                 
</span><span class="cx">             # Only DAV:owner is able to set the property to other than PUBLIC
</span><span class="cx">             if not self.internal_request:
</span><del>-                def _callback(parent_owner):
-                    
-                    authz = self.destinationparent.currentPrincipal(self.request)
-                    if davxml.Principal(parent_owner) != authz and self.access != Component.ACCESS_PUBLIC:
-                        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (calendarserver_namespace, &quot;valid-access-restriction-change&quot;)))
-                    
-                    return None
-    
-                d = self.destinationparent.owner(self.request)
-                d.addCallback(_callback)
-                return d
</del><ins>+                parentOwner = (yield self.destinationparent.owner(self.request))
+                authz = self.destinationparent.currentPrincipal(self.request)
+                if davxml.Principal(parentOwner) != authz and self.access != Component.ACCESS_PUBLIC:
+                    raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (calendarserver_namespace, &quot;valid-access-restriction-change&quot;)))
+
</ins><span class="cx">         else:
</span><span class="cx">             # Check whether an access property was present before and write that into the calendar data
</span><del>-            if not self.source and self.destination.exists() and self.destination.hasDeadProperty(TwistedCalendarAccessProperty):
-                old_access = str(self.destination.readDeadProperty(TwistedCalendarAccessProperty))
</del><ins>+            if not self.source and self.destination.exists() and (yield self.destination.hasDeadProperty(TwistedCalendarAccessProperty)):
+                old_access = str((yield self.destination.readDeadProperty(TwistedCalendarAccessProperty)))
</ins><span class="cx">                 self.calendar.addProperty(Property(name=Component.ACCESS_PROPERTY, value=old_access))
</span><span class="cx">                 self.calendardata = str(self.calendar)
</span><span class="cx">                 
</span><del>-        return succeed(None)
</del><ins>+        returnValue(None)
</ins><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def noUIDConflict(self, uid):
</span><span class="lines">@@ -687,6 +685,7 @@
</span><span class="cx">         else:
</span><span class="cx">             return False
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def preservePrivateComments(self):
</span><span class="cx">         # Check for private comments on the old resource and the new resource and re-insert
</span><span class="cx">         # ones that are lost.
</span><span class="lines">@@ -695,7 +694,7 @@
</span><span class="cx">         # the X- property is missing.
</span><span class="cx">         new_has_private_comments = False
</span><span class="cx">         if config.Scheduling.CalDAV.get(&quot;EnablePrivateComments&quot;, True) and self.calendar is not None:
</span><del>-            old_has_private_comments = self.destination.exists() and self.destinationcal and self.destination.hasDeadProperty(TwistedCalendarHasPrivateCommentsProperty)
</del><ins>+            old_has_private_comments = self.destination.exists() and self.destinationcal and (yield self.destination.hasDeadProperty(TwistedCalendarHasPrivateCommentsProperty))
</ins><span class="cx">             new_has_private_comments = self.calendar.hasPropertyInAnyComponent((
</span><span class="cx">                 &quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;,
</span><span class="cx">                 &quot;X-CALENDARSERVER-ATTENDEE-COMMENT&quot;,
</span><span class="lines">@@ -704,19 +703,23 @@
</span><span class="cx">             if old_has_private_comments and not new_has_private_comments:
</span><span class="cx">                 # Transfer old comments to new calendar
</span><span class="cx">                 log.debug(&quot;Private Comments properties were entirely removed by the client. Restoring existing properties.&quot;)
</span><del>-                self.destination.iCalendar().addCallback(self.calendar.transferProperties,
-                                                         (&quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;,
-                                                          &quot;X-CALENDARSERVER-ATTENDEE-COMMENT&quot;))
</del><ins>+                old_calendar = (yield self.destination.iCalendar())
+                self.calendar.transferProperties(old_calendar,
+                    (
+                        &quot;X-CALENDARSERVER-PRIVATE-COMMENT&quot;,
+                        &quot;X-CALENDARSERVER-ATTENDEE-COMMENT&quot;,
+                    )
+                )
</ins><span class="cx">                 self.calendardata = None
</span><span class="cx">         
</span><del>-        return new_has_private_comments
</del><ins>+        returnValue(new_has_private_comments)
</ins><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def doImplicitScheduling(self):
</span><span class="cx"> 
</span><span class="cx">         # Get any existing schedule-tag property on the resource
</span><del>-        if self.destination.exists() and self.destination.hasDeadProperty(ScheduleTag):
-            self.scheduletag = self.destination.readDeadProperty(ScheduleTag)
</del><ins>+        if self.destination.exists() and (yield self.destination.hasDeadProperty(ScheduleTag)):
+            self.scheduletag = (yield self.destination.readDeadProperty(ScheduleTag))
</ins><span class="cx">             if self.scheduletag:
</span><span class="cx">                 self.scheduletag = str(self.scheduletag)
</span><span class="cx">         else:
</span><span class="lines">@@ -795,13 +798,13 @@
</span><span class="cx">     
</span><span class="cx">         # Update calendar-access property value on the resource
</span><span class="cx">         if self.access:
</span><del>-            self.destination.writeDeadProperty(TwistedCalendarAccessProperty(self.access))
</del><ins>+            (yield self.destination.writeDeadProperty(TwistedCalendarAccessProperty(self.access)))
</ins><span class="cx">             
</span><span class="cx">         # Do not remove the property if access was not specified and we are storing in a calendar.
</span><span class="cx">         # This ensure that clients that do not preserve the iCalendar property do not cause access
</span><span class="cx">         # restrictions to be lost.
</span><span class="cx">         elif not self.destinationcal:
</span><del>-            self.destination.removeDeadProperty(TwistedCalendarAccessProperty)                
</del><ins>+            (yield self.destination.removeDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx"> 
</span><span class="cx">         returnValue(IResponse(response))
</span><span class="cx"> 
</span><span class="lines">@@ -816,7 +819,7 @@
</span><span class="cx">         # Finish MD5 calculation and write dead property
</span><span class="cx">         md5.close()
</span><span class="cx">         md5 = md5.getMD5()
</span><del>-        self.destination.writeDeadProperty(TwistedGETContentMD5.fromString(md5))
</del><ins>+        yield self.destination.writeDeadProperty(TwistedGETContentMD5.fromString(md5))
</ins><span class="cx"> 
</span><span class="cx">         returnValue(response)
</span><span class="cx"> 
</span><span class="lines">@@ -880,6 +883,7 @@
</span><span class="cx">                 ))
</span><span class="cx">             return None
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def doDestinationIndex(self, caltoindex):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Do destination resource indexing, replacing any index previous stored.
</span><span class="lines">@@ -908,10 +912,10 @@
</span><span class="cx"> 
</span><span class="cx">         content_type = self.request.headers.getHeader(&quot;content-type&quot;)
</span><span class="cx">         if not self.internal_request and content_type is not None:
</span><del>-            self.destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(content_type)))
</del><ins>+            yield self.destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(content_type)))
</ins><span class="cx">         else:
</span><del>-            self.destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(MimeType(&quot;text&quot;, &quot;calendar&quot;, params={&quot;charset&quot;:&quot;utf-8&quot;}))))
-        return None
</del><ins>+            yield self.destination.writeDeadProperty(davxml.GETContentType.fromString(generateContentType(MimeType(&quot;text&quot;, &quot;calendar&quot;, params={&quot;charset&quot;:&quot;utf-8&quot;}))))
+        returnValue(None)
</ins><span class="cx"> 
</span><span class="cx">     def doRemoveDestinationIndex(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -962,7 +966,7 @@
</span><span class="cx">             rruleChanged = self.truncateRecurrence()
</span><span class="cx"> 
</span><span class="cx">             # Preserve private comments
</span><del>-            new_has_private_comments = self.preservePrivateComments()
</del><ins>+            new_has_private_comments = (yield self.preservePrivateComments())
</ins><span class="cx">     
</span><span class="cx">             # Do scheduling
</span><span class="cx">             implicit_result = (yield self.doImplicitScheduling())
</span><span class="lines">@@ -1021,7 +1025,7 @@
</span><span class="cx"> 
</span><span class="cx">             # Check for scheduling object resource and write property
</span><span class="cx">             if is_scheduling_resource:
</span><del>-                self.destination.writeDeadProperty(TwistedSchedulingObjectResource.fromString(&quot;true&quot;))
</del><ins>+                yield self.destination.writeDeadProperty(TwistedSchedulingObjectResource.fromString(&quot;true&quot;))
</ins><span class="cx"> 
</span><span class="cx">                 # Need to figure out when to change the schedule tag:
</span><span class="cx">                 #
</span><span class="lines">@@ -1043,7 +1047,7 @@
</span><span class="cx"> 
</span><span class="cx">                 if change_scheduletag or self.scheduletag is None:
</span><span class="cx">                     self.scheduletag = str(uuid.uuid4())
</span><del>-                self.destination.writeDeadProperty(ScheduleTag.fromString(self.scheduletag))
</del><ins>+                yield self.destination.writeDeadProperty(ScheduleTag.fromString(self.scheduletag))
</ins><span class="cx"> 
</span><span class="cx">                 # Add a response header
</span><span class="cx">                 response.headers.setHeader(&quot;Schedule-Tag&quot;, self.scheduletag)                
</span><span class="lines">@@ -1056,25 +1060,25 @@
</span><span class="cx">                     else:
</span><span class="cx">                         # Schedule-Tag did not change =&gt; add current ETag to list of those that can
</span><span class="cx">                         # be used in a weak pre-condition test
</span><del>-                        if self.destination.hasDeadProperty(TwistedScheduleMatchETags):
-                            etags = self.destination.readDeadProperty(TwistedScheduleMatchETags).children
</del><ins>+                        if (yield self.destination.hasDeadProperty(TwistedScheduleMatchETags)):
+                            etags = (yield self.destination.readDeadProperty(TwistedScheduleMatchETags)).children
</ins><span class="cx">                         else:
</span><span class="cx">                             etags = ()
</span><span class="cx">                     etags += (davxml.GETETag.fromString(self.destination.etag().tag),)
</span><del>-                    self.destination.writeDeadProperty(TwistedScheduleMatchETags(*etags))
</del><ins>+                    yield self.destination.writeDeadProperty(TwistedScheduleMatchETags(*etags))
</ins><span class="cx">                 else:
</span><del>-                    self.destination.removeDeadProperty(TwistedScheduleMatchETags)                
</del><ins>+                    yield self.destination.removeDeadProperty(TwistedScheduleMatchETags)                
</ins><span class="cx">             else:
</span><del>-                self.destination.writeDeadProperty(TwistedSchedulingObjectResource.fromString(&quot;false&quot;))                
-                self.destination.removeDeadProperty(ScheduleTag)                
-                self.destination.removeDeadProperty(TwistedScheduleMatchETags)                
</del><ins>+                yield self.destination.writeDeadProperty(TwistedSchedulingObjectResource.fromString(&quot;false&quot;))                
+                yield self.destination.removeDeadProperty(ScheduleTag)                
+                yield self.destination.removeDeadProperty(TwistedScheduleMatchETags)                
</ins><span class="cx"> 
</span><span class="cx">             # Check for existence of private comments and write property
</span><span class="cx">             if config.Scheduling.CalDAV.get(&quot;EnablePrivateComments&quot;, True):
</span><span class="cx">                 if new_has_private_comments:
</span><del>-                    self.destination.writeDeadProperty(TwistedCalendarHasPrivateCommentsProperty())
</del><ins>+                    yield self.destination.writeDeadProperty(TwistedCalendarHasPrivateCommentsProperty())
</ins><span class="cx">                 elif not self.destinationcal:
</span><del>-                    self.destination.removeDeadProperty(TwistedCalendarHasPrivateCommentsProperty)                
</del><ins>+                    yield self.destination.removeDeadProperty(TwistedCalendarHasPrivateCommentsProperty)                
</ins><span class="cx"> 
</span><span class="cx">             # Delete the original source if needed.
</span><span class="cx">             if self.deletesource:
</span><span class="lines">@@ -1082,7 +1086,7 @@
</span><span class="cx">     
</span><span class="cx">             # Index the new resource if storing to a calendar.
</span><span class="cx">             if self.destinationcal:
</span><del>-                result = self.doDestinationIndex(self.calendar)
</del><ins>+                result = (yield self.doDestinationIndex(self.calendar))
</ins><span class="cx">                 if result is not None:
</span><span class="cx">                     self.rollback.Rollback()
</span><span class="cx">                     returnValue(result)
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethodreport_calquerypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_calquery.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_calquery.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_calquery.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -116,6 +116,7 @@
</span><span class="cx">         @param uri: the uri for the calendar collecton resource.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         
</span><ins>+        @inlineCallbacks
</ins><span class="cx">         def queryCalendarObjectResource(resource, uri, name, calendar, timezone, query_ok=False, isowner=True):
</span><span class="cx">             &quot;&quot;&quot;
</span><span class="cx">             Run a query on the specified calendar.
</span><span class="lines">@@ -128,7 +129,7 @@
</span><span class="cx">             # Handle private events access restrictions
</span><span class="cx">             if not isowner:
</span><span class="cx">                 try:
</span><del>-                    access = resource.readDeadProperty(TwistedCalendarAccessProperty)
</del><ins>+                    access = (yield resource.readDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx">                 except HTTPError:
</span><span class="cx">                     access = None
</span><span class="cx">             else:
</span><span class="lines">@@ -145,9 +146,9 @@
</span><span class="cx">                 else:
</span><span class="cx">                     href = davxml.HRef.fromString(uri)
</span><span class="cx">             
</span><del>-                return report_common.responseForHref(request, responses, href, resource, calendar, timezone, propertiesForResource, query, isowner)
</del><ins>+                returnValue(report_common.responseForHref(request, responses, href, resource, calendar, timezone, propertiesForResource, query, isowner))
</ins><span class="cx">             else:
</span><del>-                return succeed(None)
</del><ins>+                returnValue(None)
</ins><span class="cx">     
</span><span class="cx">         # Check whether supplied resource is a calendar or a calendar object resource
</span><span class="cx">         if calresource.isPseudoCalendarCollection():
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavmethodreport_commonpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_common.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_common.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/method/report_common.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -246,7 +246,7 @@
</span><span class="cx">             # Handle private events access restrictions
</span><span class="cx">             if not isowner:
</span><span class="cx">                 try:
</span><del>-                    access = resource.readDeadProperty(TwistedCalendarAccessProperty)
</del><ins>+                    access = (yield resource.readDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx">                 except HTTPError:
</span><span class="cx">                     access = None
</span><span class="cx">             else:
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/resource.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/resource.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/resource.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -230,8 +230,8 @@
</span><span class="cx">         elif namespace == caldav_namespace:
</span><span class="cx">             if name == &quot;supported-calendar-component-set&quot;:
</span><span class="cx">                 # CalDAV-access-09, section 5.2.3
</span><del>-                if self.hasDeadProperty(qname):
-                    returnValue(self.readDeadProperty(qname))
</del><ins>+                if (yield self.hasDeadProperty(qname)):
+                    returnValue((yield self.readDeadProperty(qname)))
</ins><span class="cx">                 returnValue(self.supportedCalendarComponentSet)
</span><span class="cx">             elif name == &quot;supported-calendar-data&quot;:
</span><span class="cx">                 # CalDAV-access-09, section 5.2.4
</span><span class="lines">@@ -258,13 +258,13 @@
</span><span class="cx">             elif name == &quot;schedule-calendar-transp&quot;:
</span><span class="cx">                 # For backwards compatibility, if the property does not exist we need to create
</span><span class="cx">                 # it and default to the old free-busy-set value.
</span><del>-                if self.isCalendarCollection() and not self.hasDeadProperty(property):
</del><ins>+                if self.isCalendarCollection() and not (yield self.hasDeadProperty(property)):
</ins><span class="cx">                     # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
</span><span class="cx">                     principal = (yield self.ownerPrincipal(request))
</span><span class="cx">                     fbset = (yield principal.calendarFreeBusyURIs(request))
</span><span class="cx">                     url = (yield self.canonicalURL(request))
</span><span class="cx">                     opaque = url in fbset
</span><del>-                    self.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque() if opaque else caldavxml.Transparent()))
</del><ins>+                    (yield self.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()) if opaque else caldavxml.Transparent()))
</ins><span class="cx"> 
</span><span class="cx">         result = (yield super(CalDAVResource, self).readProperty(property, request))
</span><span class="cx">         returnValue(result)
</span><span class="lines">@@ -325,12 +325,7 @@
</span><span class="cx">         result = (yield super(CalDAVResource, self).writeProperty(property, request))
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><del>-    def writeDeadProperty(self, property):
-        val = super(CalDAVResource, self).writeDeadProperty(property)
</del><span class="cx"> 
</span><del>-        return val
-
-
</del><span class="cx">     ##
</span><span class="cx">     # ACL
</span><span class="cx">     ##
</span><span class="lines">@@ -341,8 +336,8 @@
</span><span class="cx">         acls = (yield super(CalDAVResource, self).accessControlList(request, *args, **kwargs))
</span><span class="cx"> 
</span><span class="cx">         # Look for private events access classification
</span><del>-        if self.hasDeadProperty(TwistedCalendarAccessProperty):
-            access = self.readDeadProperty(TwistedCalendarAccessProperty)
</del><ins>+        if (yield self.hasDeadProperty(TwistedCalendarAccessProperty)):
+            access = (yield self.readDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx">             if access.getValue() in (Component.ACCESS_PRIVATE, Component.ACCESS_CONFIDENTIAL, Component.ACCESS_RESTRICTED,):
</span><span class="cx">                 # Need to insert ACE to prevent non-owner principals from seeing this resource
</span><span class="cx">                 owner = (yield self.owner(request))
</span><span class="lines">@@ -461,20 +456,21 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self.isSpecialCollection(caldavxml.Calendar)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def isSpecialCollection(self, collectiontype):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         See L{ICalDAVResource.isSpecialCollection}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if not self.isCollection(): return False
</del><ins>+        if not self.isCollection(): returnValue(False)
</ins><span class="cx"> 
</span><span class="cx">         try:
</span><del>-            resourcetype = self.readDeadProperty((dav_namespace, &quot;resourcetype&quot;))
</del><ins>+            resourcetype = (yield self.readDeadProperty((dav_namespace, &quot;resourcetype&quot;)))
</ins><span class="cx">         except HTTPError, e:
</span><span class="cx">             assert e.response.code == responsecode.NOT_FOUND, (
</span><span class="cx">                 &quot;Unexpected response code: %s&quot; % (e.response.code,)
</span><span class="cx">             )
</span><del>-            return False
-        return bool(resourcetype.childrenOfType(collectiontype))
</del><ins>+            returnValue(False)
+        returnValue(bool(resourcetype.childrenOfType(collectiontype)))
</ins><span class="cx"> 
</span><span class="cx">     def isPseudoCalendarCollection(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -572,21 +568,22 @@
</span><span class="cx"> 
</span><span class="cx">             inbox = (yield request.locateResource(inboxURL))
</span><span class="cx">             inbox.processFreeBusyCalendar(request.path, False)
</span><del>-            inbox.processFreeBusyCalendar(destination_uri, destination.isCalendarOpaque())
</del><ins>+            inbox.processFreeBusyCalendar(destination_uri, (yield destination.isCalendarOpaque()))
</ins><span class="cx">             
</span><span class="cx">             # Adjust the default calendar setting if necessary
</span><span class="cx">             if defaultCalendar:
</span><span class="cx">                 yield inbox.writeProperty(caldavxml.ScheduleDefaultCalendarURL(davxml.HRef(destination_path)), request)               
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def isCalendarOpaque(self):
</span><span class="cx">         
</span><span class="cx">         assert self.isCalendarCollection()
</span><span class="cx">         
</span><del>-        if self.hasDeadProperty((caldav_namespace, &quot;schedule-calendar-transp&quot;)):
-            property = self.readDeadProperty((caldav_namespace, &quot;schedule-calendar-transp&quot;))
-            return property.children[0] == caldavxml.Opaque()
</del><ins>+        if (yield self.hasDeadProperty((caldav_namespace, &quot;schedule-calendar-transp&quot;))):
+            property = (yield self.readDeadProperty((caldav_namespace, &quot;schedule-calendar-transp&quot;)))
+            returnValue(property.children[0] == caldavxml.Opaque())
</ins><span class="cx">         else:
</span><del>-            return False
</del><ins>+            returnValue(False)
</ins><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def isDefaultCalendar(self, request):
</span><span class="lines">@@ -922,20 +919,22 @@
</span><span class="cx"> 
</span><span class="cx">         return super(CalendarPrincipalResource, self).writeProperty(property, request)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def calendarHomeURLs(self):
</span><del>-        if self.hasDeadProperty((caldav_namespace, &quot;calendar-home-set&quot;)):
-            home_set = self.readDeadProperty((caldav_namespace, &quot;calendar-home-set&quot;))
-            return [str(h) for h in home_set.children]
</del><ins>+        if (yield self.hasDeadProperty((caldav_namespace, &quot;calendar-home-set&quot;))):
+            home_set = (yield self.readDeadProperty((caldav_namespace, &quot;calendar-home-set&quot;)))
+            returnValue([str(h) for h in home_set.children])
</ins><span class="cx">         else:
</span><del>-            return ()
</del><ins>+            returnValue(())
</ins><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def calendarUserAddresses(self):
</span><del>-        if self.hasDeadProperty((caldav_namespace, &quot;calendar-user-address-set&quot;)):
-            addresses = self.readDeadProperty((caldav_namespace, &quot;calendar-user-address-set&quot;))
-            return [str(h) for h in addresses.children]
</del><ins>+        if (yield self.hasDeadProperty((caldav_namespace, &quot;calendar-user-address-set&quot;))):
+            addresses = (yield self.readDeadProperty((caldav_namespace, &quot;calendar-user-address-set&quot;)))
+            returnValue([str(h) for h in addresses.children])
</ins><span class="cx">         else:
</span><span class="cx">             # Must have a valid address of some kind so use the principal uri
</span><del>-            return (self.principalURL(),)
</del><ins>+            returnValue((self.principalURL(),))
</ins><span class="cx"> 
</span><span class="cx">     def calendarFreeBusyURIs(self, request):
</span><span class="cx">         def gotInbox(inbox):
</span><span class="lines">@@ -967,32 +966,35 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self.scheduleInboxURL().addCallback(request.locateResource)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def scheduleInboxURL(self):
</span><del>-        if self.hasDeadProperty((caldav_namespace, &quot;schedule-inbox-URL&quot;)):
-            inbox = self.readDeadProperty((caldav_namespace, &quot;schedule-inbox-URL&quot;))
-            return succeed(str(inbox.children[0]))
</del><ins>+        if (yield self.hasDeadProperty((caldav_namespace, &quot;schedule-inbox-URL&quot;))):
+            inbox = (yield self.readDeadProperty((caldav_namespace, &quot;schedule-inbox-URL&quot;)))
+            returnValue(str(inbox.children[0]))
</ins><span class="cx">         else:
</span><del>-            return succeed(None)
</del><ins>+            returnValue(None)
</ins><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def scheduleOutboxURL(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the schedule outbox URL for this principal.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if self.hasDeadProperty((caldav_namespace, &quot;schedule-outbox-URL&quot;)):
-            outbox = self.readDeadProperty((caldav_namespace, &quot;schedule-outbox-URL&quot;))
-            return succeed(str(outbox.children[0]))
</del><ins>+        if (yield self.hasDeadProperty((caldav_namespace, &quot;schedule-outbox-URL&quot;))):
+            outbox = (yield self.readDeadProperty((caldav_namespace, &quot;schedule-outbox-URL&quot;)))
+            returnValue(str(outbox.children[0]))
</ins><span class="cx">         else:
</span><del>-            return succeed(None)
</del><ins>+            returnValue(None)
</ins><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def dropboxURL(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @return: the drop box home collection URL for this principal.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if self.hasDeadProperty((calendarserver_namespace, &quot;dropbox-home-URL&quot;)):
-            inbox = self.readDeadProperty((caldav_namespace, &quot;dropbox-home-URL&quot;))
-            return succeed(str(inbox.children[0]))
</del><ins>+        if (yield self.hasDeadProperty((calendarserver_namespace, &quot;dropbox-home-URL&quot;))):
+            inbox = (yield self.readDeadProperty((caldav_namespace, &quot;dropbox-home-URL&quot;)))
+            returnValue(str(inbox.children[0]))
</ins><span class="cx">         else:
</span><del>-            return succeed(None)
</del><ins>+            returnValue(None)
</ins><span class="cx"> 
</span><span class="cx">     ##
</span><span class="cx">     # Quota
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavstaticpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/static.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/static.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/static.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx">             return False
</span><span class="cx">         return self.fp.path == other.fp.path
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def checkPreconditions(self, request):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         We override the base class to handle the special implicit scheduling weak ETag behavior
</span><span class="lines">@@ -115,8 +116,8 @@
</span><span class="cx">         
</span><span class="cx">         if config.Scheduling.CalDAV.ScheduleTagCompatibility:
</span><span class="cx">             
</span><del>-            if self.exists() and self.hasDeadProperty(TwistedScheduleMatchETags):
-                etags = self.readDeadProperty(TwistedScheduleMatchETags).children
</del><ins>+            if self.exists() and (yield self.hasDeadProperty(TwistedScheduleMatchETags)):
+                etags = (yield self.readDeadProperty(TwistedScheduleMatchETags)).children
</ins><span class="cx">                 if len(etags) &gt; 1:
</span><span class="cx">                     # This is almost verbatim from twisted.web2.static.checkPreconditions
</span><span class="cx">                     if request.method not in (&quot;GET&quot;, &quot;HEAD&quot;):
</span><span class="lines">@@ -144,13 +145,12 @@
</span><span class="cx">                     # Check per-method preconditions
</span><span class="cx">                     method = getattr(self, &quot;preconditions_&quot; + request.method, None)
</span><span class="cx">                     if method:
</span><del>-                        response = maybeDeferred(method, request)
-                        response.addCallback(lambda _: request)
-                        return response
</del><ins>+                        response = yield(method(request))
+                        returnValue(response)
</ins><span class="cx">                     else:
</span><del>-                        return None
</del><ins>+                        returnValue(None)
</ins><span class="cx"> 
</span><del>-        return super(CalDAVFile, self).checkPreconditions(request)
</del><ins>+        returnValue((yield super(CalDAVFile, self).checkPreconditions(request)))
</ins><span class="cx"> 
</span><span class="cx">     def deadProperties(self, caching=True):
</span><span class="cx">         if not hasattr(self, &quot;_dead_properties&quot;):
</span><span class="lines">@@ -208,29 +208,25 @@
</span><span class="cx">         parent.addCallback(_defer)
</span><span class="cx">         return parent
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def createCalendarCollection(self):
</span><span class="cx">         #
</span><span class="cx">         # Create the collection once we know it is safe to do so
</span><span class="cx">         #
</span><del>-        def onCalendarCollection(status):
-            if status != responsecode.CREATED:
-                raise HTTPError(status)
</del><ins>+        status = (yield self.createSpecialCollection(davxml.ResourceType.calendar))
+        if status != responsecode.CREATED:
+            raise HTTPError(status)
</ins><span class="cx"> 
</span><del>-            # Initialize CTag on the calendar collection
-            d1 = self.updateCTag()
</del><ins>+        # Initialize CTag on the calendar collection
+        yield self.updateCTag()
</ins><span class="cx"> 
</span><del>-            # Calendar is initially transparent to freebusy
-            self.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Transparent()))
</del><ins>+        # Calendar is initially transparent to freebusy
+        yield self.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Transparent()))
</ins><span class="cx"> 
</span><del>-            # Create the index so its ready when the first PUTs come in
-            d1.addCallback(lambda _: self.index().create())
-            d1.addCallback(lambda _: status)
-            return d1
</del><ins>+        # Create the index so its ready when the first PUTs come in
+        self.index().create()
+        returnValue(status)
</ins><span class="cx"> 
</span><del>-        d = self.createSpecialCollection(davxml.ResourceType.calendar)
-        d.addCallback(onCalendarCollection)
-        return d
-
</del><span class="cx">     def createSpecialCollection(self, resourceType=None):
</span><span class="cx">         #
</span><span class="cx">         # Create the collection once we know it is safe to do so
</span><span class="lines">@@ -239,8 +235,9 @@
</span><span class="cx">             if status != responsecode.CREATED:
</span><span class="cx">                 raise HTTPError(status)
</span><span class="cx"> 
</span><del>-            self.writeDeadProperty(resourceType)
-            return status
</del><ins>+            d = self.writeDeadProperty(resourceType)
+            d.addCallback(lambda _: status)
+            return d
</ins><span class="cx"> 
</span><span class="cx">         def onError(f):
</span><span class="cx">             try:
</span><span class="lines">@@ -306,9 +303,10 @@
</span><span class="cx"> 
</span><span class="cx">         raise HTTPError(ErrorResponse(responsecode.BAD_REQUEST))
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def iCalendarTextFiltered(self, isowner):
</span><span class="cx">         try:
</span><del>-            access = self.readDeadProperty(TwistedCalendarAccessProperty)
</del><ins>+            access = (yield self.readDeadProperty(TwistedCalendarAccessProperty))
</ins><span class="cx">         except HTTPError:
</span><span class="cx">             access = None
</span><span class="cx"> 
</span><span class="lines">@@ -317,9 +315,9 @@
</span><span class="cx">             if not isowner:
</span><span class="cx">                 # Now &quot;filter&quot; the resource calendar data through the CALDAV:calendar-data element and apply
</span><span class="cx">                 # access restrictions to the data.
</span><del>-                d = caldavxml.CalendarData().elementFromResourceWithAccessRestrictions(self, access)
-                return d.addCallback(lambda el: el.calendarData())
-        return self.iCalendarText()
</del><ins>+                el = (yield caldavxml.CalendarData().elementFromResourceWithAccessRestrictions(self, access))
+                returnValue(el.calendarData())
+        returnValue((yield self.iCalendarText()))
</ins><span class="cx"> 
</span><span class="cx">     def iCalendarText(self, name=None):
</span><span class="cx">         if self.isPseudoCalendarCollection():
</span><span class="lines">@@ -417,7 +415,7 @@
</span><span class="cx">                         response = (yield original(request))
</span><span class="cx"> 
</span><span class="cx">                         # Wipe the cache
</span><del>-                        similar.deadProperties().flushCache()
</del><ins>+                        yield similar.deadProperties().flushCache()
</ins><span class="cx"> 
</span><span class="cx">                         returnValue(response)
</span><span class="cx"> 
</span><span class="lines">@@ -426,13 +424,15 @@
</span><span class="cx">             return similar
</span><span class="cx">         return d.addCallback(_gotFile)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def updateCTag(self):
</span><span class="cx">         assert self.isCollection()
</span><span class="cx">         try:
</span><del>-            self.writeDeadProperty(customxml.GETCTag(
</del><ins>+            yield self.writeDeadProperty(customxml.GETCTag(
</ins><span class="cx">                     str(datetime.datetime.now())))
</span><span class="cx">         except:
</span><del>-            return fail(Failure())
</del><ins>+            # MOR: was: return fail(Failure())
+            raise Failure()
</ins><span class="cx"> 
</span><span class="cx">         if hasattr(self, 'clientNotifier'):
</span><span class="cx">             self.clientNotifier.notify(op=&quot;update&quot;)
</span><span class="lines">@@ -441,12 +441,12 @@
</span><span class="cx">                       % (self,))
</span><span class="cx"> 
</span><span class="cx">         if hasattr(self, 'cacheNotifier'):
</span><del>-            return self.cacheNotifier.changed()
</del><ins>+            returnValue(self.cacheNotifier.changed())
</ins><span class="cx">         else:
</span><span class="cx">             log.debug(&quot;%r does not have a cacheNotifier but the CTag changed&quot;
</span><span class="cx">                       % (self,))
</span><span class="cx"> 
</span><del>-        return succeed(True)
</del><ins>+        returnValue(True)
</ins><span class="cx"> 
</span><span class="cx">     ##
</span><span class="cx">     # Quota
</span><span class="lines">@@ -950,10 +950,10 @@
</span><span class="cx">         return self._dead_properties
</span><span class="cx"> 
</span><span class="cx">     def etag(self):
</span><del>-        return None
</del><ins>+        return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">     def checkPreconditions(self, request):
</span><del>-        return None
</del><ins>+        return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">     ##
</span><span class="cx">     # ACL
</span><span class="lines">@@ -1075,10 +1075,10 @@
</span><span class="cx">         return self._dead_properties
</span><span class="cx"> 
</span><span class="cx">     def etag(self):
</span><del>-        return None
</del><ins>+        return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">     def checkPreconditions(self, request):
</span><del>-        return None
</del><ins>+        return succeed(None)
</ins><span class="cx"> 
</span><span class="cx">     def checkPrivileges(self, request, privileges, recurse=False, principal=None, inherited_aces=None):
</span><span class="cx">         return succeed(None)
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavtesttest_memcachepropspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_memcacheprops.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_memcacheprops.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_memcacheprops.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="cx"> from twisted.web2.http import HTTPError
</span><del>-from twisted.internet.defer import succeed
</del><ins>+from twisted.internet.defer import succeed, inlineCallbacks, returnValue
</ins><span class="cx"> 
</span><span class="cx"> from twistedcaldav.memcacheprops import MemcachePropertyCollection
</span><span class="cx"> from twistedcaldav.test.util import InMemoryPropertyStore
</span><span class="lines">@@ -99,94 +99,113 @@
</span><span class="cx"> 
</span><span class="cx"> class MemcachePropertyCollectionTestCase(TestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    Test MemcacheProprtyCollection
</del><ins>+    Test MemcachePropertyCollection
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
+    def assertRaisesDeferred(self, exception, f, *args, **kwargs):
+        try:
+            result = (yield f(*args, **kwargs))
+        except exception, inst:
+            returnValue(inst)
+        except:
+            raise self.failureException('%s raised instead of %s:\n %s'
+                                        % (sys.exc_info()[0],
+                                           exception.__name__,
+                                           failure.Failure().getTraceback()))
+        else:
+            raise self.failureException('%s not raised (%r returned)'
+                                        % (exception.__name__, result))
+
+
</ins><span class="cx">     def getColl(self):
</span><span class="cx">         return StubCollection(&quot;calendars&quot;, [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;])
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def test_setget(self):
</span><span class="cx"> 
</span><del>-        child1 = self.getColl().getChild(&quot;a&quot;)
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;))
</del><ins>+        child1 = (yield self.getColl().getChild(&quot;a&quot;))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;)))
</ins><span class="cx"> 
</span><del>-        child2 = self.getColl().getChild(&quot;a&quot;)
-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        child2 = (yield self.getColl().getChild(&quot;a&quot;))
+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val1&quot;)
</span><span class="cx"> 
</span><del>-        child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val2&quot;))
</del><ins>+        (yield child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val2&quot;)))
</ins><span class="cx"> 
</span><span class="cx">         # force memcache to be consulted (once per collection per request)
</span><del>-        child1 = self.getColl().getChild(&quot;a&quot;)
</del><ins>+        child1 = (yield self.getColl().getChild(&quot;a&quot;))
</ins><span class="cx"> 
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val2&quot;)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def test_merge(self):
</span><del>-        child1 = self.getColl().getChild(&quot;a&quot;)
-        child2 = self.getColl().getChild(&quot;a&quot;)
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val0&quot;))
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop2&quot;, value=&quot;val0&quot;))
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val0&quot;))
</del><ins>+        child1 = (yield self.getColl().getChild(&quot;a&quot;))
+        child2 = (yield self.getColl().getChild(&quot;a&quot;))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val0&quot;)))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop2&quot;, value=&quot;val0&quot;)))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val0&quot;)))
</ins><span class="cx"> 
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><span class="cx"> 
</span><del>-        child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;))
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val3&quot;))
</del><ins>+        (yield child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;)))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val3&quot;)))
</ins><span class="cx"> 
</span><span class="cx">         # force memcache to be consulted (once per collection per request)
</span><del>-        child2 = self.getColl().getChild(&quot;a&quot;)
</del><ins>+        child2 = (yield self.getColl().getChild(&quot;a&quot;))
</ins><span class="cx"> 
</span><span class="cx">         # verify properties
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val1&quot;)
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val3&quot;)
</span><span class="cx"> 
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val1&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val3&quot;)
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def test_delete(self):
</span><del>-        child1 = self.getColl().getChild(&quot;a&quot;)
-        child2 = self.getColl().getChild(&quot;a&quot;)
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val0&quot;))
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop2&quot;, value=&quot;val0&quot;))
-        child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val0&quot;))
</del><ins>+        child1 = (yield self.getColl().getChild(&quot;a&quot;))
+        child2 = (yield self.getColl().getChild(&quot;a&quot;))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val0&quot;)))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop2&quot;, value=&quot;val0&quot;)))
+        (yield child1.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop3&quot;, value=&quot;val0&quot;)))
</ins><span class="cx"> 
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop1&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><span class="cx"> 
</span><del>-        child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;))
-        child1.deadProperties().delete((&quot;ns1:&quot;, &quot;prop1&quot;))
-        self.assertRaises(HTTPError, child1.deadProperties().get, (&quot;ns1:&quot;, &quot;prop1&quot;))
</del><ins>+        (yield child2.deadProperties().set(StubProperty(&quot;ns1:&quot;, &quot;prop1&quot;, value=&quot;val1&quot;)))
+        (yield child1.deadProperties().delete((&quot;ns1:&quot;, &quot;prop1&quot;)))
+        self.assertRaisesDeferred(HTTPError, child1.deadProperties().get, (&quot;ns1:&quot;, &quot;prop1&quot;))
</ins><span class="cx"> 
</span><del>-        self.assertFalse(child1.deadProperties().contains((&quot;ns1:&quot;, &quot;prop1&quot;))) 
-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertFalse((yield child1.deadProperties().contains((&quot;ns1:&quot;, &quot;prop1&quot;)))) 
+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child1.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><span class="cx"> 
</span><span class="cx">         # force memcache to be consulted (once per collection per request)
</span><del>-        child2 = self.getColl().getChild(&quot;a&quot;)
</del><ins>+        child2 = (yield self.getColl().getChild(&quot;a&quot;))
</ins><span class="cx"> 
</span><span class="cx">         # verify properties
</span><del>-        self.assertFalse(child2.deadProperties().contains((&quot;ns1:&quot;, &quot;prop1&quot;))) 
-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;)).value,
</del><ins>+        self.assertFalse((yield child2.deadProperties().contains((&quot;ns1:&quot;, &quot;prop1&quot;)))) 
+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop2&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span><del>-        self.assertEquals(child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;)).value,
</del><ins>+        self.assertEquals((yield child2.deadProperties().get((&quot;ns1:&quot;, &quot;prop3&quot;))).value,
</ins><span class="cx">             &quot;val0&quot;)
</span></span></pre></div>
<a id="CalendarServerbranchesmoredeferreds3twistedcaldavtesttest_resourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_resource.py (4507 => 4508)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_resource.py        2009-08-21 21:17:01 UTC (rev 4507)
+++ CalendarServer/branches/more-deferreds-3/twistedcaldav/test/test_resource.py        2009-08-26 17:42:05 UTC (rev 4508)
</span><span class="lines">@@ -31,8 +31,9 @@
</span><span class="cx">         self.resource = CalDAVResource()
</span><span class="cx">         self.resource._dead_properties = InMemoryPropertyStore()
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
</ins><span class="cx">     def test_writeDeadPropertyWritesProperty(self):
</span><span class="cx">         prop = StubProperty()
</span><del>-        self.resource.writeDeadProperty(prop)
-        self.assertEquals(self.resource._dead_properties.get(&quot;StubQname&quot;),
</del><ins>+        yield self.resource.writeDeadProperty(prop)
+        self.assertEquals((yield self.resource._dead_properties.get(&quot;StubQname&quot;)),
</ins><span class="cx">                           prop)
</span></span></pre>
</div>
</div>

</body>
</html>