[CalendarServer-changes] [4121] CalendarServer/trunk/twistedcaldav/directory

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 30 16:09:51 PDT 2009


Revision: 4121
          http://trac.macosforge.org/projects/calendarserver/changeset/4121
Author:   sagen at apple.com
Date:     2009-04-30 16:09:50 -0700 (Thu, 30 Apr 2009)
Log Message:
-----------
Replacing the email-address index with a calendar-user-address index, to allow multiple records with the same email address, but not calendar user address.  Also, we only index (internally and in memcached) on the attribute+value that we faulted the record in on, in order to avoid index collisions.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py
    CalendarServer/trunk/twistedcaldav/directory/cachingxmlfile.py
    CalendarServer/trunk/twistedcaldav/directory/directory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -42,6 +42,7 @@
 
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.directory.directory import DirectoryError, UnknownRecordTypeError
+from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 
 class OpenDirectoryService(DirectoryService):
     """
@@ -280,9 +281,17 @@
                 self._storage(recordType)["disabled names"].add(shortName)
             return record
 
-    def recordWithEmailAddress(self, emailAddress):
-        return self._recordWithAttribute("emails", "disabled emails", "email", emailAddress)
+    def recordWithCalendarUserAddress(self, address):
+        address = normalizeCUAddr(address)
+        record = None
+        if address.startswith("urn:uuid:"):
+            guid = address[9:]
+            record = self.recordWithGUID(guid)
+        elif address.startswith("mailto:"):
+            record = self._recordWithAttribute("cuas", "disabled cuas", "cua", address)
 
+        return record if record and record.enabledForCalendaring else None
+
     def recordWithGUID(self, guid):
         return self._recordWithAttribute("guids", "disabled guids", "guid", guid)
 
@@ -510,13 +519,13 @@
             records = {}
             guids   = {}
             authIDs = {}
-            emails  = {}
+            cuas  = {}
 
             disabledNames   = set()
             disabledGUIDs   = set()
             disabledAuthIDs = set()
-            disabledEmails  = set()
-            
+            disabledCUAs    = set()
+
             if recordType == self.recordType_groups:
                 groupsForGUID = {}
             elif recordType in (self.recordType_resources, self.recordType_locations):
@@ -528,13 +537,13 @@
             records = storage["records"]
             guids   = storage["guids"]
             authIDs = storage["authIDs"]
-            emails  = storage["emails"]
+            cuas    = storage["cuas"]
 
             disabledNames   = storage["disabled names"]
             disabledGUIDs   = storage["disabled guids"]
             disabledAuthIDs = storage["disabled authIDs"]
-            disabledEmails  = storage["disabled emails"]
-            
+            disabledCUAs    = storage["disabled cuas"]
+
             if recordType == self.recordType_groups:
                 groupsForGUID = storage["groupsForGUID"]
             elif recordType in (self.recordType_resources, self.recordType_locations):
@@ -657,7 +666,7 @@
                 disabledGUIDs.add(guid)
                 disabledNames.update(record.shortNames)
                 disabledAuthIDs.update(record.authIDs)
-                disabledEmails.update(record.emailAddresses)
+                disabledCUAs.update(record.calendarUserAddresses)
 
                 if guid in guids:
                     try:
@@ -674,9 +683,9 @@
                         del authIDs[authID]
                     except KeyError:
                         pass
-                for email in record.emailAddresses:
+                for cua in record.calendarUserAddresses:
                     try:
-                        del emails[email]
+                        del cuas[cua]
                     except KeyError:
                         pass
 
@@ -747,28 +756,31 @@
                             else:
                                 authIDs[authID] = record
         
-                    # Index non-duplicate emails
-                    def disableEmail(emailAddress, record):
-                        self.log_warn("Email address %s disabled due to conflict for record: %s"
-                                      % (emailAddress, record))
+                    # Index non-duplicate CUAs
+                    def disableCUA(cua, record):
+                        self.log_warn("CUA %s disabled due to conflict for record: %s"
+                                      % (cua, record))
         
-                        record.emailAddresses.remove(emailAddress)
-                        disabledEmails.add(emailAddress)
+                        record.calendarUserAddresses.remove(cua)
+                        disabledCUAs.add(cua)
         
-                        if emailAddress in emails:
-                            del emails[emailAddress]
+                        if cua in cuas:
+                            del cuas[cua]
+
+                        if cua in records:
+                            del records[cua]
         
-                    for email in frozenset(recordEmailAddresses):
-                        if email in disabledEmails:
-                            disableEmail(email, record)
+                    for cua in frozenset(calendarUserAddresses):
+                        if cua in disabledCUAs:
+                            disableCUA(cua, record)
                         else:
                             # Check for duplicates
-                            existing_record = emails.get(email)
+                            existing_record = cuas.get(cua)
                             if existing_record is not None:
-                                disableEmail(email, record)
-                                disableEmail(email, existing_record)
+                                disableCUA(cua, record)
+                                disableCUA(cua, existing_record)
                             else:
-                                emails[email] = record
+                                cuas[cua] = record
 
         if lookup is None:
             #
@@ -779,11 +791,11 @@
                 "records"          : records,
                 "guids"            : guids,
                 "authIDs"          : authIDs,
-                "emails"           : emails,
+                "cuas"             : cuas,
                 "disabled names"   : disabledNames,
                 "disabled guids"   : disabledGUIDs,
                 "disabled authIDs" : disabledAuthIDs,
-                "disabled emails"  : disabledEmails,
+                "disabled cuas"    : disabledCUAs,
             }
 
             # Add group indexing if needed
@@ -819,6 +831,7 @@
                 "Added %d (%d enabled) records to %s OD record cache; expires in %d seconds"
                 % (len(self._records[recordType]["guids"]), enabled_count, recordType, cacheTimeout)
             )
+            print self._records[recordType]
 
     def _queryDirectory(self, recordType, lookup=None):
         attrs = [
@@ -891,15 +904,28 @@
 
         query = None
         if lookup is not None:
-            queryattr = {
-                "shortName" : dsattributes.kDSNAttrRecordName,
-                "guid"      : dsattributes.kDS1AttrGeneratedUID,
-                "authID"    : dsattributes.kDSNAttrAltSecurityIdentities,
-                "email"     : dsattributes.kDSNAttrEMailAddress,
-            }.get(lookup[0])
-            assert queryattr is not None, "Invalid type for record faulting query"
-            query = dsquery.match(queryattr, lookup[1], dsattributes.eDSExact)
+            indexType, indexKey = lookup
+            origIndexKey = indexKey
 
+            if indexType == "cua":
+                # The directory doesn't contain CUAs, so we need to convert
+                # the CUA to the appropriate field name and value:
+                queryattr, indexKey = cuAddressConverter(indexKey)
+                # queryattr will be one of:
+                # guid, emailAddresses, or recordName
+                # ...which will need to be mapped to DS
+                queryattr = self._ODFields[queryattr]['odField']
+
+            else:
+                queryattr = {
+                    "shortName" : dsattributes.kDSNAttrRecordName,
+                    "guid"      : dsattributes.kDS1AttrGeneratedUID,
+                    "authID"    : dsattributes.kDSNAttrAltSecurityIdentities,
+                }.get(indexType)
+                assert queryattr is not None, "Invalid type for record faulting query"
+
+            query = dsquery.match(queryattr, indexKey, dsattributes.eDSExact)
+
         try:
             if query:
                 self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (

Modified: CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -44,6 +44,7 @@
     CachingDirectoryRecord
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.directory.directory import DirectoryError, UnknownRecordTypeError
+from twistedcaldav.directory.principal import cuAddressConverter
 
 class OpenDirectoryService(CachingDirectoryService):
     """
@@ -444,6 +445,26 @@
             dsattributes.kDSNAttrMetaNodeLocation,
         ]
 
+        origIndexKey = indexKey
+        if indexType == self.INDEX_TYPE_CUA:
+            # The directory doesn't contain CUAs, so we need to convert
+            # the CUA to the appropriate field name and value:
+            queryattr, indexKey = cuAddressConverter(indexKey)
+            # queryattr will be one of:
+            # guid, emailAddresses, or recordName
+            # ...which will need to be mapped to DS
+            queryattr = self._ODFields[queryattr]['odField']
+
+        else:
+            queryattr = {
+                self.INDEX_TYPE_SHORTNAME : dsattributes.kDSNAttrRecordName,
+                self.INDEX_TYPE_GUID      : dsattributes.kDS1AttrGeneratedUID,
+            }.get(indexType)
+            assert queryattr is not None, "Invalid type for record faulting query"
+
+        query = dsquery.match(queryattr, indexKey, dsattributes.eDSExact)
+
+
         listRecordTypes = []
         for recordType in recordTypes:
             if recordType == DirectoryService.recordType_users:
@@ -455,15 +476,13 @@
                 attrs.append(dsattributes.kDSNAttrNestedGroups)
     
             elif recordType == DirectoryService.recordType_locations:
-                # Email addresses and locations don't mix
-                if indexType != self.INDEX_TYPE_EMAIL:
+                if queryattr != dsattributes.kDSNAttrEMailAddress:
                     listRecordTypes.append(dsattributes.kDSStdRecordTypePlaces)
                 # MOR: possibly can be removed
                 attrs.append(dsattributes.kDSNAttrResourceInfo)
             
             elif recordType == DirectoryService.recordType_resources:
-                # Email addresses and resources don't mix
-                if indexType != self.INDEX_TYPE_EMAIL:
+                if queryattr != dsattributes.kDSNAttrEMailAddress:
                     listRecordTypes.append(dsattributes.kDSStdRecordTypeResources)
                 # MOR: possibly can be removed
                 attrs.append(dsattributes.kDSNAttrResourceInfo)
@@ -471,13 +490,6 @@
             else:
                 raise UnknownRecordTypeError("Unknown Open Directory record type: %s" % (recordType))
 
-        queryattr = {
-            self.INDEX_TYPE_SHORTNAME : dsattributes.kDSNAttrRecordName,
-            self.INDEX_TYPE_GUID      : dsattributes.kDS1AttrGeneratedUID,
-            self.INDEX_TYPE_EMAIL     : dsattributes.kDSNAttrEMailAddress,
-        }.get(indexType)
-        assert queryattr is not None, "Invalid type for record faulting query"
-        query = dsquery.match(queryattr, indexKey, dsattributes.eDSExact)
 
         try:
             self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (
@@ -508,8 +520,6 @@
                 self.log_error("Open Directory (node=%s) error: %s" % (self.realmName, str(ex)))
                 raise
 
-        enabled_count = 0
-
         def _uniqueTupleFromAttribute(attribute):
             if attribute:
                 if isinstance(attribute, str):
@@ -528,7 +538,10 @@
                     return set([item.lower() if lower else item for item in attribute])
             else:
                 return ()
-            
+
+        enabledRecords = []
+        disabledRecords = []
+
         for (recordShortName, value) in results:
 
             # Now get useful record info.
@@ -607,7 +620,6 @@
                     enabledForCalendaring = True
 
             if enabledForCalendaring:
-                enabled_count += 1
                 calendarUserAddresses = self._calendarUserAddresses(recordType, value)
             else:
                 # Some records we want to keep even though they are not enabled for calendaring.
@@ -658,8 +670,21 @@
                 enabledForCalendaring = enabledForCalendaring,
                 memberGUIDs           = memberGUIDs,
             )
-            self.recordCacheForType(recordType).addRecord(record)
+            if enabledForCalendaring:
+                enabledRecords.append(record)
+            else:
+                disabledRecords.append(record)
 
+        record = None
+        if len(enabledRecords) == 1:
+            record = enabledRecords[0]
+        elif len(enabledRecords) == 0 and len(disabledRecords) == 1:
+            record = disabledRecords[0]
+
+        if record:
+            self.log_debug("Storing (%s %s) %s in internal cache" % (indexType, origIndexKey, record))
+            self.recordCacheForType(recordType).addRecord(record, indexType, origIndexKey)
+
     def _parseResourceInfo(self, plist, guid, recordType, shortname):
         """
         Parse OD ResourceInfo attribute and extract information that the server needs.

Modified: CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/cachingdirectory.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -30,8 +30,10 @@
 import memcacheclient
 import base64
 
-from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord, DirectoryError
 from twistedcaldav.config import config
+from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord, DirectoryError
+from twistedcaldav.log import LoggingMixIn
+from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 
 
 class RecordTypeCache(object):
@@ -44,19 +46,16 @@
         self.directoryService = directoryService
         self.recordType = recordType
 
-    def addRecord(self, record):
+    def addRecord(self, record, indexType, indexKey, useMemcache=True):
         raise NotImplementedError()
     
     def removeRecord(self, record):
         raise NotImplementedError()
         
-    def replaceRecord(self, oldRecord, newRecord):
-        raise NotImplementedError()
-
     def findRecord(self, indexType, indexKey):
         raise NotImplementedError()
         
-class DictRecordTypeCache(RecordTypeCache):
+class DictRecordTypeCache(RecordTypeCache, LoggingMixIn):
     """
     Cache implementation using a dict. Does not share the cache with other instances.
     """
@@ -68,28 +67,23 @@
         self.recordsIndexedBy = {
             CachingDirectoryService.INDEX_TYPE_GUID     : {},
             CachingDirectoryService.INDEX_TYPE_SHORTNAME: {},
-            CachingDirectoryService.INDEX_TYPE_EMAIL    : {},
+            CachingDirectoryService.INDEX_TYPE_CUA    : {},
             CachingDirectoryService.INDEX_TYPE_AUTHID   : {},
         }
 
-    def addRecord(self, record):
-        
+    def addRecord(self, record, indexType, indexKey, useMemcache=True):
+
+        useMemcache == useMemcache and config.Memcached.ClientEnabled
+
         self.records.add(record)
-        for indexType in self.directoryService.indexTypes():
-            try:
-                indexData = getattr(record, CachingDirectoryService.indexTypeToRecordAttribute[indexType])
-            except AttributeError:
-                continue
-            if isinstance(indexData, str):
-                indexData = (indexData,)
-            if type(indexData) in (types.ListType, types.TupleType, set):
-                for item in indexData:
-                    self.recordsIndexedBy[indexType][item] = record
-            elif indexData is None:
-                pass
-            else:
-                raise AssertionError("Data from record attribute must be str, list or tuple")
-    
+
+        self.recordsIndexedBy[indexType][indexKey] = record
+        if useMemcache:
+            key = "dir|%s|%s" % (indexType, indexKey)
+            self.log_debug("Memcache: storing %s" % (key,))
+            self.directoryService.memcacheSet(key, record)
+
+
     def removeRecord(self, record):
         
         if record in self.records:
@@ -110,10 +104,6 @@
                 else:
                     raise AssertionError("Data from record attribute must be str, list or tuple")
         
-    def replaceRecord(self, oldRecord, newRecord):
-        self.removeRecord(oldRecord)
-        self.addRecord(newRecord)
-
     def findRecord(self, indexType, indexKey):
         return self.recordsIndexedBy[indexType].get(indexKey)
 
@@ -126,13 +116,13 @@
 
     INDEX_TYPE_GUID      = "guid"
     INDEX_TYPE_SHORTNAME = "shortname"
-    INDEX_TYPE_EMAIL     = "email"
+    INDEX_TYPE_CUA     = "cua"
     INDEX_TYPE_AUTHID    = "authid"
 
     indexTypeToRecordAttribute = {
         "guid"     : "guid",
         "shortname": "shortNames",
-        "email"    : "emailAddresses",
+        "cua"      : "calendarUserAddresses",
         "authid"   : "authIDs",
     }
 
@@ -209,7 +199,7 @@
         return (
             CachingDirectoryService.INDEX_TYPE_GUID,
             CachingDirectoryService.INDEX_TYPE_SHORTNAME,
-            CachingDirectoryService.INDEX_TYPE_EMAIL,
+            CachingDirectoryService.INDEX_TYPE_CUA,
             CachingDirectoryService.INDEX_TYPE_AUTHID,
         )
 
@@ -222,9 +212,17 @@
     def recordWithShortName(self, recordType, shortName):
         return self._lookupRecord((recordType,), CachingDirectoryService.INDEX_TYPE_SHORTNAME, shortName)
 
-    def recordWithEmailAddress(self, emailAddress):
-        return self._lookupRecord(None, CachingDirectoryService.INDEX_TYPE_EMAIL, emailAddress)
+    def recordWithCalendarUserAddress(self, address):
+        address = normalizeCUAddr(address)
+        record = None
+        if address.startswith("urn:uuid:"):
+            guid = address[9:]
+            record = self.recordWithGUID(guid)
+        elif address.startswith("mailto:"):
+            record = self._lookupRecord(None, CachingDirectoryService.INDEX_TYPE_CUA, address)
 
+        return record if record and record.enabledForCalendaring else None
+
     def recordWithAuthID(self, authID):
         return self._lookupRecord(None, CachingDirectoryService.INDEX_TYPE_AUTHID, authID)
 
@@ -273,7 +271,7 @@
                     self.log_debug("Memcache: miss %s" % (key,))
                 else:
                     self.log_debug("Memcache: hit %s" % (key,))
-                    self.recordCacheForType(record.recordType).addRecord(record)
+                    self.recordCacheForType(record.recordType).addRecord(record, indexType, indexKey, useMemcache=False)
                     return record
 
                 # Check negative memcache
@@ -291,24 +289,6 @@
             record = lookup()
             if record:
                 self.log_debug("Found record for attribute '%s' with value '%s'" % (indexType, indexKey,))
-
-                if config.Memcached.ClientEnabled:
-                    # share with others via memcache
-                    for shortName in record.shortNames:
-                        key = "dir|%s|%s" % (CachingDirectoryService.INDEX_TYPE_SHORTNAME, shortName)
-                        self.log_debug("Memcache: storing %s" % (key,))
-                        self.memcacheSet(key, record)
-                    for emailAddress in record.emailAddresses:
-                        key = "dir|%s|%s" % (CachingDirectoryService.INDEX_TYPE_EMAIL, emailAddress)
-                        self.log_debug("Memcache: storing %s" % (key,))
-                        self.memcacheSet(key, record)
-                    for authID in record.authIDs:
-                        key = "dir|%s|%s" % (CachingDirectoryService.INDEX_TYPE_AUTHID, authID)
-                        self.log_debug("Memcache: storing %s" % (key,))
-                        self.memcacheSet(key, record)
-                    key = "dir|%s|%s" % (CachingDirectoryService.INDEX_TYPE_GUID, record.guid)
-                    self.log_debug("Memcache: storing %s" % (key,))
-                    self.memcacheSet(key, record)
                 return record
 
 

Modified: CalendarServer/trunk/twistedcaldav/directory/cachingxmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/cachingxmlfile.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/cachingxmlfile.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -76,8 +76,8 @@
                     matched = indexKey == xmlPrincipal.guid
                 elif indexType == self.INDEX_TYPE_SHORTNAME:
                     matched = indexKey in xmlPrincipal.shortNames
-                elif indexType == self.INDEX_TYPE_EMAIL:
-                    matched = indexKey in xmlPrincipal.emailAddresses
+                elif indexType == self.INDEX_TYPE_CUA:
+                    matched = indexKey in xmlPrincipal.calendarUserAddresses
                 
                 if matched:
                     record = XMLDirectoryRecord(

Modified: CalendarServer/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -149,18 +149,14 @@
             guid = address[9:]
             record = self.recordWithGUID(guid)
         elif address.startswith("mailto:"):
-            email = address[7:]
-            record = self.recordWithEmailAddress(email)
+            for record in self.allRecords():
+                if address in record.calendarUserAddresses:
+                    break
+            else:
+                return None
 
         return record if record and record.enabledForCalendaring else None
 
-    def recordWithEmailAddress(self, email):
-        for record in self.allRecords():
-            if email in record.emailAddresses:
-                return record
-                
-        return None
-
     def allRecords(self):
         for recordType in self.recordTypes():
             for record in self.listRecords(recordType):

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_cachedirectory.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -42,7 +42,7 @@
                 cacheIt = False
                 if indexType in (
                     CachingDirectoryService.INDEX_TYPE_SHORTNAME,
-                    CachingDirectoryService.INDEX_TYPE_EMAIL,
+                    CachingDirectoryService.INDEX_TYPE_CUA,
                     CachingDirectoryService.INDEX_TYPE_AUTHID,
                 ):
                     if indexKey in record[indexType]:
@@ -62,10 +62,11 @@
                         firstName             = "",
                         lastName              = "",
                         emailAddresses        = record.get("email"),
-                        calendarUserAddresses = record.get("email"),
+                        calendarUserAddresses = record.get("cua"),
                         enabledForCalendaring = True,
                     ) 
-                    self.recordCacheForType(recordType).addRecord(cacheRecord)
+                    self.recordCacheForType(recordType).addRecord(cacheRecord,
+                        indexType, indexKey)
 
 class CachingDirectoryTest(TestCase):
     
@@ -109,6 +110,7 @@
             "guid": guid,
             "shortname": shortNames,
             "email": emails,
+            "cua": tuple(["mailto:%s" % email for email in emails]),
             "authid": tuple(["Kerberos:%s" % email for email in emails])
         }
         
@@ -202,8 +204,8 @@
     def test_cacheoneemail(self):
         self.dummyRecords()
 
-        self.assertTrue(self.service.recordWithEmailAddress(
-            "user03 at example.com"
+        self.assertTrue(self.service.recordWithCalendarUserAddress(
+            "mailto:user03 at example.com"
         ) is not None)
         self.assertTrue(self.service.queried)
         self.verifyRecords(DirectoryService.recordType_users, set((
@@ -215,8 +217,8 @@
 
         # Make sure it really is cached and won't cause another query
         self.service.queried = False
-        self.assertTrue(self.service.recordWithEmailAddress(
-            "user03 at example.com"
+        self.assertTrue(self.service.recordWithCalendarUserAddress(
+            "mailto:user03 at example.com"
         ) is not None)
         self.assertFalse(self.service.queried)
 

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2009-04-30 21:49:32 UTC (rev 4120)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2009-04-30 23:09:50 UTC (rev 4121)
@@ -308,7 +308,7 @@
             self.assertFalse(self.service.recordWithShortName(DirectoryService.recordType_users, "user02").authIDs)
             self.assertFalse(self.service.recordWithShortName(DirectoryService.recordType_users, "user03").authIDs)
 
-        def test_duplicateEmail(self):
+        def test_duplicateCUAs(self):
             self.loadRecords({
                 DirectoryService.recordType_users: [
                     fakeODRecord("User 01"),
@@ -320,9 +320,9 @@
             self.verifyRecords(DirectoryService.recordType_users, ("user01", "user02", "user03"))
             self.verifyDisabledRecords(DirectoryService.recordType_users, (), ())
 
-            self.assertTrue (self.service.recordWithShortName(DirectoryService.recordType_users, "user01").emailAddresses)
-            self.assertFalse(self.service.recordWithShortName(DirectoryService.recordType_users, "user02").emailAddresses)
-            self.assertFalse(self.service.recordWithShortName(DirectoryService.recordType_users, "user03").emailAddresses)
+            self.assertTrue (self.service.recordWithShortName(DirectoryService.recordType_users, "user01").calendarUserAddresses)
+            self.assertFalse("mailto:shared at example.com" in self.service.recordWithShortName(DirectoryService.recordType_users, "user02").calendarUserAddresses)
+            self.assertFalse("mailto:shared at example.com" in self.service.recordWithShortName(DirectoryService.recordType_users, "user03").calendarUserAddresses)
 
         def test_duplicateRecords(self):
             self.loadRecords({
@@ -648,7 +648,7 @@
             self.verifyQuery(self.service.recordWithAuthID, "Kerberos:location05 at example.com")
             self.verifyNoQuery(self.service.recordWithAuthID, "Kerberos:location05 at example.com")
 
-        def test_negativeCacheEmailAddress(self):
+        def test_negativeCacheCalendarUserAddress(self):
             self.loadRecords({
                 DirectoryService.recordType_users: [
                     fakeODRecord("User 01"),
@@ -676,21 +676,22 @@
                 ],
             })
 
-            self.assertTrue(self.service.recordWithEmailAddress("user01 at example.com"))
-            self.verifyQuery(self.service.recordWithEmailAddress, "user05 at example.com")
-            self.verifyNoQuery(self.service.recordWithEmailAddress, "user05 at example.com")
+            self.assertTrue(self.service.recordWithCalendarUserAddress("mailto:user01 at example.com"))
+            self.verifyQuery(self.service.recordWithCalendarUserAddress, "mailto:user05 at example.com")
+            self.verifyNoQuery(self.service.recordWithCalendarUserAddress, "mailto:user05 at example.com")
 
-            self.assertTrue(self.service.recordWithEmailAddress("group01 at example.com"))
-            self.verifyQuery(self.service.recordWithEmailAddress, "group05 at example.com")
-            self.verifyNoQuery(self.service.recordWithEmailAddress, "group05 at example.com")
+            # Groups don't have CUAs
+            # self.assertTrue(self.service.recordWithCalendarUserAddress("mailto:group01 at example.com"))
+            # self.verifyQuery(self.service.recordWithCalendarUserAddress, "mailto:group05 at example.com")
+            # self.verifyNoQuery(self.service.recordWithCalendarUserAddress, "mailto:group05 at example.com")
 
-            self.assertTrue(self.service.recordWithEmailAddress("resource01 at example.com"))
-            self.verifyQuery(self.service.recordWithEmailAddress, "resource05 at example.com")
-            self.verifyNoQuery(self.service.recordWithEmailAddress, "resource05 at example.com")
+            self.assertTrue(self.service.recordWithCalendarUserAddress("mailto:resource01 at example.com"))
+            self.verifyQuery(self.service.recordWithCalendarUserAddress, "mailto:resource05 at example.com")
+            self.verifyNoQuery(self.service.recordWithCalendarUserAddress, "mailto:resource05 at example.com")
 
-            self.assertTrue(self.service.recordWithEmailAddress("location01 at example.com"))
-            self.verifyQuery(self.service.recordWithEmailAddress, "location05 at example.com")
-            self.verifyNoQuery(self.service.recordWithEmailAddress, "location05 at example.com")
+            self.assertTrue(self.service.recordWithCalendarUserAddress("mailto:location01 at example.com"))
+            self.verifyQuery(self.service.recordWithCalendarUserAddress, "mailto:location05 at example.com")
+            self.verifyNoQuery(self.service.recordWithCalendarUserAddress, "mailto:location05 at example.com")
 
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090430/78bc7320/attachment-0001.html>


More information about the calendarserver-changes mailing list