[CalendarServer-changes] [2476] CalendarServer/branches/users/cdaboo/proxy-db-cached-2451

source_changes at macosforge.org source_changes at macosforge.org
Fri May 23 19:52:22 PDT 2008


Revision: 2476
          http://trac.macosforge.org/projects/calendarserver/changeset/2476
Author:   cdaboo at apple.com
Date:     2008-05-23 19:52:22 -0700 (Fri, 23 May 2008)

Log Message:
-----------
Make group members/membership calls deferred so that we can use a deferred caching protocol
in the future.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.idav.patch
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.resource.patch
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipalmembers.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/resource.py

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.idav.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.idav.patch	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.idav.patch	2008-05-24 02:52:22 UTC (rev 2476)
@@ -120,9 +120,20 @@
  class IDAVPrincipalResource (IDAVResource):
      """
      WebDAV principal resource.  (RFC 3744, section 2)
-@@ -212,3 +283,14 @@
+@@ -203,12 +274,23 @@
+         """
+         Provides the principal URLs of principals that are direct members of
+         this (group) principal.  (RFC 3744, section 4.3)
+-        @return: a iterable of principal URLs.
++        @return: a deferred returning an iterable of principal URLs.
+         """
+ 
+     def groupMemberships():
+         """
+         Provides the URLs of the group principals in which the principal is
          directly a member.  (RFC 3744, section 4.4)
-         @return: a iterable of group principal URLs.
+-        @return: a iterable of group principal URLs.
++        @return: a deferred containing an iterable of group principal URLs.
          """
 +
 +class IDAVPrincipalCollectionResource (IDAVResource):

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	2008-05-24 02:52:22 UTC (rev 2476)
@@ -2,7 +2,7 @@
 ===================================================================
 --- twisted/web2/dav/method/report_principal_match.py	(revision 19773)
 +++ twisted/web2/dav/method/report_principal_match.py	(working copy)
-@@ -89,40 +89,61 @@
+@@ -89,40 +89,64 @@
          responses = []
          matchcount = 0
  
@@ -38,7 +38,10 @@
 +            selfItems = [principal,]
 +            
 +            # Get group memberships for "self" and add each of those
-+            selfItems.extend(principal.groupMemberships())
++            d = waitForDeferred(principal.groupMemberships())
++            yield d
++            memberships = d.getResult()
++            selfItems.extend(memberships)
 +            
 +            # Now add each principal found to the response provided the principal resource is a child of
 +            # the current resource.
@@ -94,12 +97,45 @@
              for child, uri in children:
                  # Try to read the requested property from this resource
                  try:
-@@ -137,7 +158,7 @@
+@@ -137,22 +161,26 @@
                          yield principal
                          principal = principal.getResult()
  
 -                        if principal and isPrincipalResource(principal) and principal.principalMatch(selfPrincipal):
-+                        if principal and isPrincipalResource(principal) and principal.principalMatch(selfPrincipalURL):
-                             # Check size of results is within limit
-                             matchcount += 1
-                             if matchcount > max_number_of_matches:
+-                            # Check size of results is within limit
+-                            matchcount += 1
+-                            if matchcount > max_number_of_matches:
+-                                raise NumberOfMatchesWithinLimits
+-
+-                            d = waitForDeferred(prop_common.responseForHref(
+-                                request,
+-                                responses,
+-                                davxml.HRef.fromString(uri),
+-                                child,
+-                                propertiesForResource,
+-                                propElement
+-                            ))
++                        if principal and isPrincipalResource(principal):
++                            d = waitForDeferred(principal.principalMatch(selfPrincipalURL))
+                             yield d
+-                            d.getResult()
++                            matched = d.getResult()
++                            if matched:
++                                # Check size of results is within limit
++                                matchcount += 1
++                                if matchcount > max_number_of_matches:
++                                    raise NumberOfMatchesWithinLimits
++    
++                                d = waitForDeferred(prop_common.responseForHref(
++                                    request,
++                                    responses,
++                                    davxml.HRef.fromString(uri),
++                                    child,
++                                    propertiesForResource,
++                                    propElement
++                                ))
++                                yield d
++                                d.getResult()
+                 except HTTPError:
+                     # Just ignore a failure to access the property. We treat this like a property that does not exist
+                     # or does not match the principal.

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.resource.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.resource.patch	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/lib-patches/Twisted/twisted.web2.dav.resource.patch	2008-05-24 02:52:22 UTC (rev 2476)
@@ -547,20 +547,48 @@
          # Compare two HRefs and do group membership test as well
          if principal1 == principal2:
              yield True
-@@ -1302,9 +1383,9 @@
-         def testGroup(group):
-             # Get principal resource for principal2
-             if group and isinstance(group, DAVPrincipalResource):
+@@ -1289,6 +1370,7 @@
+ 
+     matchPrincipal = deferredGenerator(matchPrincipal)
+ 
++    @deferredGenerator
+     def principalIsGroupMember(self, principal1, principal2, request):
+         """
+         Check whether one principal is a group member of another.
+@@ -1299,18 +1381,21 @@
+         @return: L{Deferred} with result C{True} if principal1 is a member of principal2, C{False} otherwise
+         """
+         
+-        def testGroup(group):
+-            # Get principal resource for principal2
+-            if group and isinstance(group, DAVPrincipalResource):
 -                members = group.groupMembers()
 -                if principal1 in members:
 -                    return True
-+                for member in group.groupMembers():
-+                    if member.principalURL() == principal1:
-+                        return True
-                 
-             return False
+-                
+-            return False
++        d = waitForDeferred(request.locateResource(principal2))
++        yield d
++        group = d.getResult()
  
-@@ -1351,11 +1432,16 @@
+-        d = request.locateResource(principal2)
+-        d.addCallback(testGroup)
+-        return d
++        # Get principal resource for principal2
++        if group and isinstance(group, DAVPrincipalResource):
++            d = waitForDeferred(group.groupMembers())
++            yield d
++            members = d.getResult()
++            for member in members:
++                if member.principalURL() == principal1:
++                    yield True
++                    return
++            
++        yield False
+         
+     def validPrincipal(self, ace_principal, request):
+         """
+@@ -1351,11 +1436,16 @@
          @return C{True} if C{href_principal} is valid, C{False} otherwise.
  
          This implementation tests for a href element that corresponds to
@@ -580,7 +608,7 @@
          return d
  
      def resolvePrincipal(self, principal, request):
-@@ -1432,7 +1518,7 @@
+@@ -1432,7 +1522,7 @@
                  log.err("DAV:self ACE is set on non-principal resource %r" % (self,))
                  yield None
                  return
@@ -589,7 +617,7 @@
  
          if isinstance(principal, davxml.HRef):
              yield principal
-@@ -1517,6 +1603,270 @@
+@@ -1517,6 +1607,270 @@
          return None
  
      ##
@@ -860,7 +888,7 @@
      # HTTP
      ##
  
-@@ -1525,10 +1875,6 @@
+@@ -1525,10 +1879,6 @@
          #litmus = request.headers.getRawHeaders("x-litmus")
          #if litmus: log.msg("*** Litmus test: %s ***" % (litmus,))
  
@@ -871,7 +899,7 @@
          #
          # If this is a collection and the URI doesn't end in "/", redirect.
          #
-@@ -1567,7 +1913,7 @@
+@@ -1567,7 +1917,7 @@
      def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
          return succeed(None)
  
@@ -880,7 +908,7 @@
      """
      Resource representing a WebDAV principal.  (RFC 3744, section 2)
      """
-@@ -1577,7 +1923,7 @@
+@@ -1577,7 +1927,7 @@
      # WebDAV
      ##
  
@@ -889,7 +917,7 @@
          (dav_namespace, "alternate-URI-set"),
          (dav_namespace, "principal-URL"    ),
          (dav_namespace, "group-member-set" ),
-@@ -1585,14 +1931,11 @@
+@@ -1585,14 +1935,11 @@
      )
  
      def davComplianceClasses(self):
@@ -905,26 +933,60 @@
      def readProperty(self, property, request):
          def defer():
              if type(property) is tuple:
-@@ -1610,10 +1953,10 @@
+@@ -1610,10 +1957,20 @@
                      return davxml.PrincipalURL(davxml.HRef(self.principalURL()))
  
                  if name == "group-member-set":
 -                    return davxml.GroupMemberSet(*[davxml.HRef(p) for p in self.groupMembers()])
-+                    return davxml.GroupMemberSet(*[davxml.HRef(p.principalURL()) for p in self.groupMembers()])
++                    def callback(members):
++                        return davxml.GroupMemberSet(*[davxml.HRef(p.principalURL()) for p in members])
++                    
++                    d = self.groupMembers()
++                    d.addCallback(callback)
++                    return d
  
                  if name == "group-membership":
 -                    return davxml.GroupMembership(*[davxml.HRef(g) for g in self.groupMemberships()])
-+                    return davxml.GroupMembership(*[davxml.HRef(g.principalURL()) for g in self.groupMemberships()])
++                    def callback(memberships):
++                        return davxml.GroupMembership(*[davxml.HRef(g.principalURL()) for g in memberships])
++                    
++                    d = self.groupMemberships()
++                    d.addCallback(callback)
++                    return d
  
                  if name == "resourcetype":
                      if self.isCollection():
-@@ -1677,8 +2020,27 @@
+@@ -1655,7 +2012,7 @@
+         principals.  Subclasses should override this method to provide member
+         URLs for this resource if appropriate.
+         """
+-        return ()
++        return succeed(())
+ 
+     def groupMemberships(self):
+         """
+@@ -1666,6 +2023,7 @@
+         """
+         unimplemented(self)
+ 
++    @deferredGenerator
+     def principalMatch(self, href):
+         """
+         Check whether the supplied principal matches this principal or is a
+@@ -1675,10 +2033,33 @@
+         """
+         uri = str(href)
          if self.principalURL() == uri:
-             return True
+-            return True
++            yield True
++            return
          else:
 -            return uri in self.groupMembers()
-+            member_uris = [member.principalURL() for member in self.groupMembers()]
-+            return uri in member_uris
++            d = waitForDeferred(self.groupMembers())
++            yield d
++            members = d.getResult()
++            member_uris = [member.principalURL() for member in members]
++            yield uri in member_uris
  
 +class DAVPrincipalCollectionResource (DAVResource):
 +    """
@@ -947,7 +1009,7 @@
  class AccessDeniedError(Exception):
      def __init__(self, errors):
          """ 
-@@ -1718,6 +2080,37 @@
+@@ -1718,6 +2099,37 @@
  davxml.registerElement(TwistedACLInheritable)
  davxml.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
  

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-import itertools
 
 """
 Implements a calendar user proxy principal.
@@ -24,6 +23,8 @@
 ]
 
 from twisted.internet.defer import succeed
+from twisted.internet.defer import deferredGenerator
+from twisted.internet.defer import waitForDeferred
 from twisted.web2 import responsecode
 from twisted.web2.dav import davxml
 from twisted.web2.dav.element.base import dav_namespace
@@ -38,6 +39,7 @@
 from twistedcaldav.sql import db_prefix
 from twistedcaldav.static import AutoProvisioningFileMixIn
 
+import itertools
 import os
 
 class PermissionsMixIn (ReadOnlyWritePropertiesResourceMixIn):
@@ -192,46 +194,54 @@
     # HTTP
     ##
 
+    @deferredGenerator
     def renderDirectoryBody(self, request):
         # FIXME: Too much code duplication here from principal.py
         from twistedcaldav.directory.principal import format_list, format_principals, format_link
 
-        def gotSuper(output):
-            return "".join((
-                """<div class="directory-listing">"""
-                """<h1>Principal Details</h1>"""
-                """<pre><blockquote>"""
-                """Directory Information\n"""
-                """---------------------\n"""
-                """Directory GUID: %s\n"""         % (self.parent.record.service.guid,),
-                """Realm: %s\n"""                  % (self.parent.record.service.realmName,),
-                """\n"""
-                """Parent Principal Information\n"""
-                """---------------------\n"""
-                """GUID: %s\n"""                   % (self.parent.record.guid,),
-                """Record type: %s\n"""            % (self.parent.record.recordType,),
-                """Short name: %s\n"""             % (self.parent.record.shortName,),
-                """Full name: %s\n"""              % (self.parent.record.fullName,),
-                """Principal UID: %s\n"""          % (self.parent.principalUID(),),
-                """Principal URL: %s\n"""          % (format_link(self.parent.principalURL()),),
-                """\n"""
-                """Proxy Principal Information\n"""
-                """---------------------\n"""
-               #"""GUID: %s\n"""                   % (self.guid,),
-                """Principal UID: %s\n"""          % (self.principalUID(),),
-                """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
-                """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
-                """\nGroup members (%s):\n""" % ({False:"Locked", True:"Editable"}[self.hasEditableMembership()])
-                                                   , format_principals(self.groupMembers()),
-                """\nGroup memberships:\n"""       , format_principals(self.groupMemberships()),
-                """</pre></blockquote></div>""",
-                output
-            ))
+        d = waitForDeferred(super(CalendarUserProxyPrincipalResource, self).renderDirectoryBody(request))
+        yield d
+        output = d.getResult()
+        
+        d = waitForDeferred(self.groupMembers())
+        yield d
+        members = d.getResult()
+        
+        d = waitForDeferred(self.groupMemberships())
+        yield d
+        memberships = d.getResult() 
+        
+        yield "".join((
+            """<div class="directory-listing">"""
+            """<h1>Principal Details</h1>"""
+            """<pre><blockquote>"""
+            """Directory Information\n"""
+            """---------------------\n"""
+            """Directory GUID: %s\n"""         % (self.parent.record.service.guid,),
+            """Realm: %s\n"""                  % (self.parent.record.service.realmName,),
+            """\n"""
+            """Parent Principal Information\n"""
+            """---------------------\n"""
+            """GUID: %s\n"""                   % (self.parent.record.guid,),
+            """Record type: %s\n"""            % (self.parent.record.recordType,),
+            """Short name: %s\n"""             % (self.parent.record.shortName,),
+            """Full name: %s\n"""              % (self.parent.record.fullName,),
+            """Principal UID: %s\n"""          % (self.parent.principalUID(),),
+            """Principal URL: %s\n"""          % (format_link(self.parent.principalURL()),),
+            """\n"""
+            """Proxy Principal Information\n"""
+            """---------------------\n"""
+           #"""GUID: %s\n"""                   % (self.guid,),
+            """Principal UID: %s\n"""          % (self.principalUID(),),
+            """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
+            """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
+            """\nGroup members (%s):\n""" % ({False:"Locked", True:"Editable"}[self.hasEditableMembership()])
+                                               , format_principals(members),
+            """\nGroup memberships:\n"""       , format_principals(memberships),
+            """</pre></blockquote></div>""",
+            output
+        ))
 
-        d = super(CalendarUserProxyPrincipalResource, self).renderDirectoryBody(request)
-        d.addCallback(gotSuper)
-        return d
-
     ##
     # DAV
     ##
@@ -256,6 +266,7 @@
     def principalCollections(self):
         return self.parent.principalCollections()
 
+    @deferredGenerator
     def _expandMemberUIDs(self, uid=None, relatives=None, uids=None):
         if uid is None:
             uid = self.principalUID()
@@ -269,35 +280,48 @@
             uids.add(uid)
             principal = self.parent.parent.principalForUID(uid)
             if isinstance(principal, CalendarUserProxyPrincipalResource):
-                for member in self._directGroupMembers():
+                d = waitForDeferred(self._directGroupMembers())
+                yield d
+                members = d.getResult()
+                for member in members:
                     if member.principalUID() not in uids:
                         relatives.add(member)
-                        self._expandMemberUIDs(member.principalUID(), relatives, uids)
+                        d = waitForDeferred(self._expandMemberUIDs(member.principalUID(), relatives, uids))
+                        yield d
+                        d.getResult()
             elif isinstance(principal, DirectoryPrincipalResource):
-                relatives.update(principal.groupMembers())
+                d = waitForDeferred(principal.groupMembers())
+                yield d
+                members = d.getResult()
+                relatives.update(members)
 
-        return relatives
+        yield relatives
 
+    @deferredGenerator
     def _directGroupMembers(self):
         if self.hasEditableMembership():
             # Get member UIDs from database and map to principal resources
-            members = self._index().getMembers(self.uid)
-            return [p for p in [self.pcollection.principalForUID(uid) for uid in members] if p]
+            d = waitForDeferred(self._index().getMembers(self.uid))
+            yield d
+            members = d.getResult()
+            yield [p for p in [self.pcollection.principalForUID(uid) for uid in members] if p]
         else:
             # Fixed proxies are only for read-write - the read-only list is empty
             if self.proxyType == "calendar-proxy-write":
-                return self.parent.proxies()
+                yield self.parent.proxies()
             else:
-                return ()
+                yield ()
 
-
     def groupMembers(self):
         return self._expandMemberUIDs()
 
+    @deferredGenerator
     def groupMemberships(self):
         # Get membership UIDs and map to principal resources
-        memberships = self._index().getMemberships(self.uid)
-        return [p for p in [self.pcollection.principalForUID(uid) for uid in memberships] if p]
+        d = waitForDeferred(self._index().getMemberships(self.uid))
+        yield d
+        memberships = d.getResult()
+        yield [p for p in [self.pcollection.principalForUID(uid) for uid in memberships] if p]
 
     def hasEditableMembership(self):
         return self.parent.hasEditableProxyMembership()
@@ -386,6 +410,8 @@
     def getMembers(self, principalUID):
         """
         Return the list of group member UIDs for the specified principal.
+        
+        @return: a deferred returning a C{set} of members.
         """
 
         def _members():
@@ -398,13 +424,15 @@
         if self.dbUseCache:
             if not self._cacheMembers.has_key(principalUID):
                 self._cacheMembers[principalUID] = _members()
-            return self._cacheMembers[principalUID]
+            return succeed(self._cacheMembers[principalUID])
         else:
-            return _members()
+            return succeed(_members())
 
     def getMemberships(self, principalUID):
         """
         Return the list of group principal UIDs the specified principal is a member of.
+        
+        @return: a deferred returning a C{set} of memberships.
         """
 
         def _members():
@@ -417,9 +445,9 @@
         if self.dbUseCache:
             if not self._cacheMemberships.has_key(principalUID):
                 self._cacheMemberships[principalUID] = _members()
-            return self._cacheMemberships[principalUID]
+            return succeed(self._cacheMemberships[principalUID])
         else:
-            return _members()
+            return succeed(_members())
 
     def _add_to_db(self, principalUID, members):
         """

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/principal.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/principal.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -32,7 +32,9 @@
 from urlparse import urlparse
 
 from twisted.python.failure import Failure
+from twisted.internet.defer import deferredGenerator
 from twisted.internet.defer import succeed
+from twisted.internet.defer import waitForDeferred
 from twisted.web2 import responsecode
 from twisted.web2.http import HTTPError
 from twisted.web2.dav import davxml
@@ -408,36 +410,45 @@
     # HTTP
     ##
 
+    @deferredGenerator
     def renderDirectoryBody(self, request):
-        def gotSuper(output):
-            return "".join((
-                """<div class="directory-listing">"""
-                """<h1>Principal Details</h1>"""
-                """<pre><blockquote>"""
-                """Directory Information\n"""
-                """---------------------\n"""
-                """Directory GUID: %s\n"""         % (self.record.service.guid,),
-                """Realm: %s\n"""                  % (self.record.service.realmName,),
-                """\n"""
-                """Principal Information\n"""
-                """---------------------\n"""
-                """GUID: %s\n"""                   % (self.record.guid,),
-                """Record type: %s\n"""            % (self.record.recordType,),
-                """Short name: %s\n"""             % (self.record.shortName,),
-                """Full name: %s\n"""              % (self.record.fullName,),
-                """Principal UID: %s\n"""          % (self.principalUID(),),
-                """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
-                """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
-                """\nGroup members:\n"""           , format_principals(self.groupMembers()),
-                """\nGroup memberships:\n"""       , format_principals(self.groupMemberships()),
-                """</pre></blockquote></div>""",
-                output
-            ))
 
-        d = super(DirectoryPrincipalResource, self).renderDirectoryBody(request)
-        d.addCallback(gotSuper)
-        return d
+        d = waitForDeferred(super(DirectoryPrincipalResource, self).renderDirectoryBody(request))
+        yield d
+        output = d.getResult()
+        
+        d = waitForDeferred(self.groupMembers())
+        yield d
+        members = d.getResult()
+        
+        d = waitForDeferred(self.groupMemberships())
+        yield d
+        memberships = d.getResult()
 
+        yield "".join((
+            """<div class="directory-listing">"""
+            """<h1>Principal Details</h1>"""
+            """<pre><blockquote>"""
+            """Directory Information\n"""
+            """---------------------\n"""
+            """Directory GUID: %s\n"""         % (self.record.service.guid,),
+            """Realm: %s\n"""                  % (self.record.service.realmName,),
+            """\n"""
+            """Principal Information\n"""
+            """---------------------\n"""
+            """GUID: %s\n"""                   % (self.record.guid,),
+            """Record type: %s\n"""            % (self.record.recordType,),
+            """Short name: %s\n"""             % (self.record.shortName,),
+            """Full name: %s\n"""              % (self.record.fullName,),
+            """Principal UID: %s\n"""          % (self.principalUID(),),
+            """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
+            """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
+            """\nGroup members:\n"""           , format_principals(members),
+            """\nGroup memberships:\n"""       , format_principals(memberships),
+            """</pre></blockquote></div>""",
+            output
+        ))
+
     ##
     # DAV
     ##
@@ -503,8 +514,9 @@
         return relatives
 
     def groupMembers(self):
-        return self._getRelatives("members")
+        return succeed(self._getRelatives("members"))
 
+    @deferredGenerator
     def groupMemberships(self):
         groups = self._getRelatives("groups")
 
@@ -514,14 +526,17 @@
 
             # Get proxy group UIDs and map to principal resources
             proxies = []
-            for uid in self._calendar_user_proxy_index().getMemberships(self.principalUID()):
+            d = waitForDeferred(self._calendar_user_proxy_index().getMemberships(self.principalUID()))
+            yield d
+            memberships = d.getResult()
+            for uid in memberships:
                 subprincipal = self.parent.principalForUID(uid)
                 if subprincipal:
                     proxies.append(subprincipal)
 
             groups.update(proxies)
 
-        return groups
+        yield groups
 
 
     def principalCollections(self):
@@ -554,37 +569,46 @@
     """
     Directory calendar principal resource.
     """
+    @deferredGenerator
     def renderDirectoryBody(self, request):
-        def gotSuper(output):
-            return "".join((
-                """<div class="directory-listing">"""
-                """<h1>Principal Details</h1>"""
-                """<pre><blockquote>"""
-                """Directory Information\n"""
-                """---------------------\n"""
-                """Directory GUID: %s\n"""         % (self.record.service.guid,),
-                """Realm: %s\n"""                  % (self.record.service.realmName,),
-                """\n"""
-                """Principal Information\n"""
-                """---------------------\n"""
-                """GUID: %s\n"""                   % (self.record.guid,),
-                """Record type: %s\n"""            % (self.record.recordType,),
-                """Short name: %s\n"""             % (self.record.shortName,),
-                """Full name: %s\n"""              % (self.record.fullName,),
-                """Principal UID: %s\n"""          % (self.principalUID(),),
-                """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
-                """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
-                """\nGroup members:\n"""           , format_principals(self.groupMembers()),
-                """\nGroup memberships:\n"""       , format_principals(self.groupMemberships()),
-                """\nCalendar homes:\n"""          , format_list(format_link(u) for u in self.calendarHomeURLs()),
-                """\nCalendar user addresses:\n""" , format_list(format_link(a) for a in self.calendarUserAddresses()),
-                """</pre></blockquote></div>""",
-                output
-            ))
 
-        d = super(DirectoryPrincipalResource, self).renderDirectoryBody(request)
-        d.addCallback(gotSuper)
-        return d
+        d = waitForDeferred(super(DirectoryPrincipalResource, self).renderDirectoryBody(request))
+        yield d
+        output = d.getResult()
+        
+        d = waitForDeferred(self.groupMembers())
+        yield d
+        members = d.getResult()
+        
+        d = waitForDeferred(self.groupMemberships())
+        yield d
+        memberships = d.getResult()
+        
+        yield "".join((
+            """<div class="directory-listing">"""
+            """<h1>Principal Details</h1>"""
+            """<pre><blockquote>"""
+            """Directory Information\n"""
+            """---------------------\n"""
+            """Directory GUID: %s\n"""         % (self.record.service.guid,),
+            """Realm: %s\n"""                  % (self.record.service.realmName,),
+            """\n"""
+            """Principal Information\n"""
+            """---------------------\n"""
+            """GUID: %s\n"""                   % (self.record.guid,),
+            """Record type: %s\n"""            % (self.record.recordType,),
+            """Short name: %s\n"""             % (self.record.shortName,),
+            """Full name: %s\n"""              % (self.record.fullName,),
+            """Principal UID: %s\n"""          % (self.principalUID(),),
+            """Principal URL: %s\n"""          % (format_link(self.principalURL()),),
+            """\nAlternate URIs:\n"""          , format_list(format_link(u) for u in self.alternateURIs()),
+            """\nGroup members:\n"""           , format_principals(members),
+            """\nGroup memberships:\n"""       , format_principals(memberships),
+            """\nCalendar homes:\n"""          , format_list(format_link(u) for u in self.calendarHomeURLs()),
+            """\nCalendar user addresses:\n""" , format_list(format_link(a) for a in self.calendarUserAddresses()),
+            """</pre></blockquote></div>""",
+            output
+        ))
 
     ##
     # CalDAV

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_principal.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_principal.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -14,15 +14,10 @@
 # limitations under the License.
 ##
 
-#from twisted.web2 import responsecode
-#from twisted.web2.iweb import IResponse
-#from twisted.web2.dav import davxml
-#from twisted.web2.dav.util import davXMLFromStream
-#from twisted.web2.test.test_server import SimpleRequest
-#from twistedcaldav import caldavxml
-
 import os
 
+from twisted.internet.defer import deferredGenerator
+from twisted.internet.defer import waitForDeferred
 from twisted.web2.dav import davxml
 from twisted.web2.dav.fileop import rmdir
 from twisted.web2.dav.resource import AccessDeniedError
@@ -244,19 +239,27 @@
         for provisioningResource, recordType, recordResource, record in self._allRecords():
             self.failUnless(recordResource.displayName())
 
+    @deferredGenerator
     def test_groupMembers(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
         for provisioningResource, recordType, recordResource, record in self._allRecords():
-            self.failUnless(set(record.members()).issubset(set(r.record for r in recordResource.groupMembers())))
+            d = waitForDeferred(recordResource.groupMembers())
+            yield d
+            members = d.getResult()
+            self.failUnless(set(record.members()).issubset(set(r.record for r in members)))
 
+    @deferredGenerator
     def test_groupMemberships(self):
         """
         DirectoryPrincipalResource.groupMemberships()
         """
         for provisioningResource, recordType, recordResource, record in self._allRecords():
-            self.failUnless(set(record.groups()).issubset(set(r.record for r in recordResource.groupMemberships() if hasattr(r, "record"))))
+            d = waitForDeferred(recordResource.groupMemberships())
+            yield d
+            memberships = d.getResult()
+            self.failUnless(set(record.groups()).issubset(set(r.record for r in memberships if hasattr(r, "record"))))
 
     def test_proxies(self):
         """

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -13,10 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
 
 import os
 
+from twisted.internet.defer import deferredGenerator
+from twisted.internet.defer import waitForDeferred
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
 import twistedcaldav.test.util
 
 class ProxyPrincipalDB (twistedcaldav.test.util.TestCase):
@@ -65,7 +67,8 @@
             @return: the schema version assigned to this index.
             """
             return "51"
-            
+    
+    @deferredGenerator
     def test_normalDB(self):
     
         # Get the DB
@@ -73,8 +76,17 @@
         os.mkdir(db_path)
         db = CalendarUserProxyDatabase(db_path)
         db.setGroupMembers("A", ("B", "C", "D",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+        
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+        
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+        
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
 
     def test_DBIndexed(self):
     
@@ -99,15 +111,33 @@
         os.mkdir(db_path)
         db = self.old_CalendarUserProxyDatabase(db_path)
         db.setGroupMembers("A", ("B", "C", "D",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set())
         db._db_close()
         db = None
         
         db = CalendarUserProxyDatabase(db_path)
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set(("GROUPNAMES", "MEMBERS")))
         db._db_close()
         db = None
@@ -119,15 +149,33 @@
         os.mkdir(db_path)
         db = self.old_CalendarUserProxyDatabase(db_path)
         db.setGroupMembers("A", ("B", "C", "D",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set())
         db._db_close()
         db = None
         
         db = self.new_CalendarUserProxyDatabase(db_path)
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set(("GROUPNAMES", "MEMBERS")))
         db._db_close()
         db = None
@@ -139,15 +187,33 @@
         os.mkdir(db_path)
         db = self.new_CalendarUserProxyDatabase(db_path)
         db.setGroupMembers("A", ("B", "C", "D",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set(("GROUPNAMES", "MEMBERS")))
         db._db_close()
         db = None
         
         db = self.newer_CalendarUserProxyDatabase(db_path)
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set(("GROUPNAMES", "MEMBERS")))
         db._db_close()
         db = None
@@ -161,20 +227,62 @@
         
         # Do one insert and check the result
         db.setGroupMembers("A", ("B", "C", "D",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
-        self.assertEqual(db.getMemberships("C"), set(("A",)))
-        self.assertEqual(db.getMemberships("D"), set(("A",)))
-        self.assertEqual(db.getMemberships("E"), set(()))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("C"))
+        yield d
+        membershipsC = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("D"))
+        yield d
+        membershipsD = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("E"))
+        yield d
+        membershipsE = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membershipsB, set(("A",)))
+        self.assertEqual(membershipsC, set(("A",)))
+        self.assertEqual(membershipsD, set(("A",)))
+        self.assertEqual(membershipsE, set(()))
         
         # Change and check the result
         db.setGroupMembers("A", ("B", "C", "E",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "E",)))
-        self.assertEqual(db.getMemberships("B"), set(("A",)))
-        self.assertEqual(db.getMemberships("C"), set(("A",)))
-        self.assertEqual(db.getMemberships("D"), set())
-        self.assertEqual(db.getMemberships("E"), set(("A",)))
 
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("C"))
+        yield d
+        membershipsC = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("D"))
+        yield d
+        membershipsD = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("E"))
+        yield d
+        membershipsE = d.getResult()
+
+        self.assertEqual(db.membersA, set(("B", "C", "E",)))
+        self.assertEqual(membershipsB, set(("A",)))
+        self.assertEqual(membershipsC, set(("A",)))
+        self.assertEqual(membershipsD, set())
+        self.assertEqual(membershipsE, set(("A",)))
+
     def test_cachingDBRemove(self):
     
         # Get the DB
@@ -185,17 +293,54 @@
         # Do one insert and check the result
         db.setGroupMembers("A", ("B", "C", "D",))
         db.setGroupMembers("X", ("B", "C",))
-        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
-        self.assertEqual(db.getMembers("X"), set(("B", "C",)))
-        self.assertEqual(db.getMemberships("B"), set(("A", "X",)))
-        self.assertEqual(db.getMemberships("C"), set(("A", "X",)))
-        self.assertEqual(db.getMemberships("D"), set(("A",)))
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMembers("X"))
+        yield d
+        membersX = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("C"))
+        yield d
+        membershipsC = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("D"))
+        yield d
+        membershipsD = d.getResult()
+
+        self.assertEqual(membersA, set(("B", "C", "D",)))
+        self.assertEqual(membersX, set(("B", "C",)))
+        self.assertEqual(membershipsB, set(("A", "X",)))
+        self.assertEqual(membershipsC, set(("A", "X",)))
+        self.assertEqual(membershipsD, set(("A",)))
         
         # Remove and check the result
         db.removeGroup("A")
-        self.assertEqual(db.getMembers("A"), set())
-        db.setGroupMembers("X", ("B", "C",))
-        self.assertEqual(db.getMemberships("B"), set("X",))
-        self.assertEqual(db.getMemberships("C"), set("X",))
-        self.assertEqual(db.getMemberships("D"), set())
+
+        d = waitForDeferred(db.getMembers("A"))
+        yield d
+        membersA = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("B"))
+        yield d
+        membershipsB = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("C"))
+        yield d
+        membershipsC = d.getResult()
+
+        d = waitForDeferred(db.getMemberships("D"))
+        yield d
+        membershipsD = d.getResult()
+
+        self.assertEqual(membersA, set())
+        self.assertEqual(membershipsB, set("X",))
+        self.assertEqual(membershipsC, set("X",))
+        self.assertEqual(membershipsD, set())
         
\ No newline at end of file

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -16,6 +16,8 @@
 
 import os
 
+from twisted.internet.defer import deferredGenerator
+from twisted.internet.defer import waitForDeferred
 from twisted.web2.dav.fileop import rmdir
 from twisted.web2.dav import davxml
 
@@ -52,66 +54,90 @@
 
         self.principalRootResources[directoryService.__class__.__name__] = provisioningResource
 
+    @deferredGenerator
     def test_groupMembersRegular(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_groups, "both_coasts").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_groups, "both_coasts").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Chris Lecroy', 'David Reid', 'Wilfredo Sanchez', 'West Coast', 'East Coast', 'Cyrus Daboo',)))
 
+    @deferredGenerator
     def test_groupMembersRecursive(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_groups, "recursive1_coasts").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_groups, "recursive1_coasts").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Wilfredo Sanchez', 'Recursive2 Coasts', 'Cyrus Daboo',)))
 
+    @deferredGenerator
     def test_groupMembersProxySingleUser(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_locations, "gemini").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_locations, "gemini").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Wilfredo Sanchez',)))
 
+    @deferredGenerator
     def test_groupMembersProxySingleGroup(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_locations, "mercury").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_locations, "mercury").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Chris Lecroy', 'David Reid', 'Wilfredo Sanchez', 'West Coast',)))
 
+    @deferredGenerator
     def test_groupMembersProxySingleGroupWithNestedGroups(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_locations, "apollo").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_locations, "apollo").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Chris Lecroy', 'David Reid', 'Wilfredo Sanchez', 'West Coast', 'East Coast', 'Cyrus Daboo', 'Both Coasts',)))
 
+    @deferredGenerator
     def test_groupMembersProxySingleGroupWithNestedRecursiveGroups(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_locations, "orion").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_locations, "orion").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Wilfredo Sanchez', 'Cyrus Daboo', 'Recursive1 Coasts', 'Recursive2 Coasts',)))
 
+    @deferredGenerator
     def test_groupMembersProxySingleGroupWithNonCalendarGroup(self):
         """
         DirectoryPrincipalResource.groupMembers()
         """
-        members = self._getRecordByShortName(DirectoryService.recordType_resources, "non_calendar_proxy").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_resources, "non_calendar_proxy").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set(('Chris Lecroy', 'Cyrus Daboo', 'Non-calendar group')))
 
-        memberships = self._getRecordByShortName(DirectoryService.recordType_groups, "non_calendar_group").groupMemberships()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_groups, "non_calendar_group").groupMemberships())
+        yield d
+        memberships = d.getResult()
         memberships = set([p.principalUID() for p in memberships])
         self.assertEquals(memberships, set(('non_calendar_proxy#calendar-proxy-write',)))
 
+    @deferredGenerator
     def test_groupMembersProxyMissingUser(self):
         """
         DirectoryPrincipalResource.groupMembers()
@@ -120,15 +146,20 @@
         # Setup the fake entry in the DB
         proxy = self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo")
         proxy_group = proxy.getChild("calendar-proxy-write")
-        members = proxy_group._index().getMembers("%s#calendar-proxy-write" % (proxy.principalUID(),))
+        d = waitForDeferred(proxy_group._index().getMembers("%s#calendar-proxy-write" % (proxy.principalUID(),)))
+        yield d
+        members = d.getResult()
         members.add("12345")
         proxy_group._index().setGroupMembers("%s#calendar-proxy-write" % (proxy.principalUID(),), members)
 
         # Do the failing lookup
-        members = self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo").getChild("calendar-proxy-write").groupMembers()
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo").getChild("calendar-proxy-write").groupMembers())
+        yield d
+        members = d.getResult()
         members = set([p.displayName() for p in members])
         self.assertEquals(members, set())
 
+    @deferredGenerator
     def test_groupMembershipsMissingUser(self):
         """
         DirectoryPrincipalResource.groupMembers()
@@ -138,14 +169,18 @@
         fake_uid = "12345"
         proxy = self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo")
         proxy_group = proxy.getChild("calendar-proxy-write")
-        members = proxy_group._index().getMembers("%s#calendar-proxy-write" % (fake_uid,))
+        d = waitForDeferred(proxy_group._index().getMembers("%s#calendar-proxy-write" % (fake_uid,)))
+        yield d
+        members = d.getResult()
         members.add("%s#calendar-proxy-write" % (proxy.principalUID(),))
         proxy_group._index().setGroupMembers("%s#calendar-proxy-write" % (fake_uid,), members)
 
         # Do the failing lookup
-        members = self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo").getChild("calendar-proxy-write").groupMemberships()
-        members = set([p.displayName() for p in members])
-        self.assertEquals(members, set())
+        d = waitForDeferred(self._getRecordByShortName(DirectoryService.recordType_users, "cdaboo").getChild("calendar-proxy-write").groupMemberships())
+        yield d
+        memberships = d.getResult()
+        memberships = set([p.displayName() for p in memberships])
+        self.assertEquals(memberships, set())
 
     def _getRecordByShortName(self, type, name):
         """

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/resource.py	2008-05-24 02:36:15 UTC (rev 2475)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/resource.py	2008-05-24 02:52:22 UTC (rev 2476)
@@ -641,10 +641,10 @@
         return maybeDeferred(defer)
 
     def groupMembers(self):
-        return ()
+        return succeed(())
 
     def groupMemberships(self):
-        return ()
+        return succeed(())
 
     def calendarHomeURLs(self):
         if self.hasDeadProperty((caldav_namespace, "calendar-home-set")):

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080523/2a005648/attachment-0001.htm 


More information about the calendarserver-changes mailing list