[CalendarServer-changes] [1204] CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Sat Feb 17 10:01:38 PST 2007


Revision: 1204
          http://trac.macosforge.org/projects/calendarserver/changeset/1204
Author:   cdaboo at apple.com
Date:     2007-02-17 10:01:37 -0800 (Sat, 17 Feb 2007)

Log Message:
-----------
Merge forward.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/__init__.py
    CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sql.py
    CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/static.py

Added Paths:
-----------
    CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sqlprops.py
    CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/test/test_sqlprops.py

Modified: CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/__init__.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/__init__.py	2007-02-17 17:42:22 UTC (rev 1203)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/__init__.py	2007-02-17 18:01:37 UTC (rev 1204)
@@ -45,6 +45,7 @@
     "root",
     "schedule",
     "sql",
+    "sqlprops",
     "static",
 ]
 

Modified: CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sql.py	2007-02-17 17:42:22 UTC (rev 1203)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sql.py	2007-02-17 18:01:37 UTC (rev 1204)
@@ -35,14 +35,16 @@
     A generic SQL database.
     """
 
-    def __init__(self, dbpath, version):
+    def __init__(self, dbpath, version, utf8=False):
         """
-        @param resource: the L{twistedcaldav.static.CalDAVFile} resource to
-            index. C{resource} must be a calendar collection (ie.
-            C{resource.isPseudoCalendarCollection()} returns C{True}.)
+        @param dppath: C{str} containing the file path to the database file.
+        @param version: C{str} containing the version for the database schema.
+        @param utf8: C{True} if utf8 encoded C{str} should be returned for SQl TEXT data,
+            C{False} if C{unicode} should be returned.
         """
         self.dbpath = dbpath
         self.version = version
+        self.utf8 = utf8
 
     def _db_type(self):
         """
@@ -58,6 +60,8 @@
         if not hasattr(self, "_db_connection"):
             db_filename = self.dbpath
             self._db_connection = sqlite.connect(db_filename)
+            if self.utf8:
+                self._db_connection.text_factory = str
 
             #
             # Set up the schema

Copied: CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sqlprops.py (from rev 1203, CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/sqlprops.py)
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sqlprops.py	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/sqlprops.py	2007-02-17 18:01:37 UTC (rev 1204)
@@ -0,0 +1,395 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# DRI: Wilfredo Sanchez, wsanchez at apple.com
+##
+
+"""
+DAV Property store an sqlite database.
+
+This API is considered private to static.py and is therefore subject to
+change.
+"""
+
+__all__ = ["sqlPropertyStore"]
+
+import cPickle
+import os
+
+from twisted.python import log
+from twisted.web2 import responsecode
+from twisted.web2.http import HTTPError, StatusResponse
+
+from twistedcaldav.root import RootResource
+from twistedcaldav.sql import AbstractSQLDatabase
+
+DEBUG_LOG = False
+
+class sqlPropertyStore (object):
+    """
+    A dead property store that uses an SQLite database backend.
+    """
+ 
+    def __init__(self, resource):
+        self.resource = resource
+        if os.path.exists(os.path.dirname(resource.fp.path)):
+            if resource.isCollection() and isinstance(resource, RootResource):
+                self.rname = ""
+                indexpath = resource.fp.path
+            else:
+                self.rname = os.path.basename(resource.fp.path)
+                indexpath = os.path.dirname(resource.fp.path)
+            self.index = SQLPropertiesDatabase(indexpath)
+        else:
+            self.index = None
+
+    def get(self, qname):
+        """
+        Read property from index.
+        
+        @param qname: C{tuple} of property namespace and name.
+        """
+        if not self.index:
+            raise HTTPError(StatusResponse(
+                responsecode.NOT_FOUND,
+                "No such property: {%s}%s" % qname
+            ))
+            
+        value = self.index.getPropertyValue(self.rname, qname)
+        if not value:
+            raise HTTPError(StatusResponse(
+                responsecode.NOT_FOUND,
+                "No such property: {%s}%s" % qname
+            ))
+            
+        return value
+
+    def getAll(self, qnames):
+        """
+        Read properties from index.
+        
+        @param qnames: C{list} of C{tuple} of property namespace and name.
+        @return: a C{list} of property classes
+        """
+        if not qnames:
+            return None
+
+        if not self.index:
+            raise HTTPError(StatusResponse(
+                responsecode.NOT_FOUND,
+                "No such property: {%s}%s" % qnames[0]
+            ))
+            
+        return self.index.getAllPropertyValues(self.rname, qnames)
+
+    def getAllResources(self, qnames):
+        """
+        Read properties for all child resources from index.
+        
+        @param qnames: C{list} of C{tuple} of property namespace and name.
+        @return: a C{dict} with resource name as keys and C{dict} of property name/classes as values
+        """
+        if not qnames:
+            return None
+
+        if not self.index:
+            raise HTTPError(StatusResponse(
+                responsecode.NOT_FOUND,
+                "No such property: {%s}%s" % qnames[0]
+            ))
+            
+        return self.index.getAllResourcePropertyValues(qnames)
+
+    def set(self, property):
+        """
+        Write property into index.
+        
+        @param property: C{Property} to write
+        """
+
+        if self.index:
+            self.index.setPropertyValue(self.rname, property.qname(), property)
+
+    def delete(self, qname):
+        """
+        Delete proeprty from index.
+
+        DELETE from PROPERTIES where NAME=<<rname>> and PROPNAME=<<pname>>
+
+        @param qname:
+        """
+        
+        if self.index:
+            self.index.removeProperty(self.rname, qname)
+
+    def deleteAll(self):
+        """
+        Delete proeprty from index.
+
+        DELETE from PROPERTIES where NAME=<<rname>> and PROPNAME=<<pname>>
+
+        @param qname:
+        """
+        
+        if self.index:
+            self.index.removeResource(self.rname)
+
+    def contains(self, qname):
+        if self.index:
+            value = self.index.getPropertyValue(self.rname, qname)
+            return value is not None
+        else:
+            return False
+
+    def list(self):
+        """
+        List all property names for this resource.
+        
+        SELECT PROPNAME from PROPERTIES where NAME=<<rname>>
+        
+        """
+
+        if self.index:
+            return self.index.listProperties(self.rname)
+        else:
+            return ()
+
+class SQLPropertiesDatabase(AbstractSQLDatabase):
+    """
+    A database to maintain calendar user proxy group memberships.
+
+    SCHEMA:
+    
+    Properties Database:
+    
+    ROW: RESOURCENAME, PROPERTYNAME, PROPERTYVALUE
+    
+    """
+    
+    dbType = "SQLPROPERTIES"
+    dbFilename = ".db.sqlproperties"
+    dbFormatVersion = "1"
+
+    def _encode(clazz, name):
+        return "{%s}%s" % name
+
+    def _decode(clazz, name):
+        index = name.find("}")
+    
+        if (index is -1 or not len(name) > index or not name[0] == "{"):
+            raise ValueError("Invalid encoded name: %r" % (name,))
+    
+        return (name[1:index], name[index+1:])
+
+    _encode = classmethod(_encode)
+    _decode = classmethod(_decode)
+
+    def __init__(self, path):
+        path = os.path.join(path, SQLPropertiesDatabase.dbFilename)
+        super(SQLPropertiesDatabase, self).__init__(path, SQLPropertiesDatabase.dbFormatVersion, utf8=True)
+
+    def setPropertyValue(self, rname, pname, pvalue):
+        """
+        Add a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to set.
+        @param pvalue: a C{str} containing the property value to set.
+        """
+        
+        # Remove what is there, then add it back.
+        self._delete_from_db(rname, self._encode(pname))
+        self._add_to_db(rname, self._encode(pname), cPickle.dumps(pvalue))
+        self._db_commit()
+
+    def getPropertyValue(self, rname, pname):
+        """
+        Get a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to get.
+        @return: a C{str} containing the property value.
+        """
+        
+        # Remove what is there, then add it back.
+        if DEBUG_LOG:
+            log.msg("getPropertyValue: %s \"%s\" \"%s\"" % (self.dbpath, rname, pname))
+        members = []
+        for row in self._db_execute("select PROPERTYVALUE from PROPERTIES where RESOURCENAME = :1 and PROPERTYNAME = :2", rname, self._encode(pname)):
+            members.append(row[0])
+        setlength =  len(members)
+        if setlength == 0:
+            return None
+        elif setlength == 1:
+            return cPickle.loads(members[0])
+        else:
+            raise ValueError("Multiple properties of the same name \"%s\" stored for resource \"%s\"" % (pname, rname,))
+
+    def getAllPropertyValues(self, rname, pnames):
+        """
+        Get specified property values from specific resource.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pnames: a C{list} of C{str} containing the name of the properties to get.
+        @return: a C{dict} containing property name/value.
+        """
+        
+        # Remove what is there, then add it back.
+        if DEBUG_LOG:
+            log.msg("getAllPropertyValues: %s \"%s\"" % (self.dbpath, pnames))
+        properties = {}
+        statement = "select PROPERTYNAME, PROPERTYVALUE from PROPERTIES where RESOURCENAME = :1 and ("
+        args = [rname]
+        for i, pname in enumerate(pnames):
+            if i != 0:
+                statement += " or "
+            statement += "PROPERTYNAME=:%s" % (i + 2,)
+            args.append(self._encode(pname))
+        statement += ")"
+
+        for row in self._db_execute(statement, *args):
+            properties[self._decode(row[0])] = cPickle.loads(row[1])
+
+        return properties
+
+    def getAllResourcePropertyValues(self, pnames):
+        """
+        Get specified property values from all resources.
+    
+        @param pnames: a C{list} of C{str} containing the name of the properties to get.
+        @return: a C{dict} containing C{str} keys (names of child resources) and C{dict} values of property name/value.
+        """
+        
+        # Remove what is there, then add it back.
+        if DEBUG_LOG:
+            log.msg("getAllPropertyValues: %s \"%s\"" % (self.dbpath, pnames))
+        members = {}
+        statement = "select RESOURCENAME, PROPERTYNAME, PROPERTYVALUE from PROPERTIES where "
+        args = []
+        for i, pname in enumerate(pnames):
+            if i != 0:
+                statement += " or "
+            statement += "PROPERTYNAME=:%s" % (i + 1,)
+            args.append(self._encode(pname))
+
+        for row in self._db_execute(statement, *args):
+            members.setdefault(row[0], {})[self._decode(row[1])] = cPickle.loads(row[2])
+
+        return members
+
+    def removeProperty(self, rname, pname):
+        """
+        Remove a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to get.
+        @return: a C{str} containing the property value.
+        """
+
+        self._delete_from_db(rname, self._encode(pname))
+        self._db_commit()
+
+    def removeResource(self, rname):
+        """
+        Remove all properties for resource.
+    
+        @param rname: a C{str} containing the resource name.
+        @return: a C{str} containing the property value.
+        """
+
+        self._delete_all_from_db(rname)
+        self._db_commit()
+
+    def listProperties(self, rname):
+        """
+        List all properties in resource.
+    
+        @param rname: a C{str} containing the resource name.
+        @return: a C{set} containing the property names.
+        """
+
+        members = set()
+        for row in self._db_execute("select PROPERTYNAME from PROPERTIES where RESOURCENAME = :1", rname):
+            members.add(self._decode(row[0]))
+        return members
+
+    def _add_to_db(self, rname, pname, pvalue):
+        """
+        Add a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to set.
+        @param pvalue: a C{str} containing the property value to set.
+        """
+        
+        self._db_execute(
+            """
+            insert into PROPERTIES (RESOURCENAME, PROPERTYNAME, PROPERTYVALUE)
+            values (:1, :2, :3)
+            """, rname, pname, pvalue
+        )
+       
+    def _delete_all_from_db(self, rname):
+        """
+        Remove a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to get.
+        @return: a C{str} containing the property value.
+        """
+
+        self._db_execute("delete from PROPERTIES where RESOURCENAME = :1", rname)
+    
+    def _delete_from_db(self, rname, pname):
+        """
+        Remove a property.
+    
+        @param rname: a C{str} containing the resource name.
+        @param pname: a C{str} containing the name of the property to get.
+        @return: a C{str} containing the property value.
+        """
+
+        self._db_execute("delete from PROPERTIES where RESOURCENAME = :1 and PROPERTYNAME = :2", rname, pname)
+    
+    def _db_type(self):
+        """
+        @return: the collection type assigned to this index.
+        """
+        return SQLPropertiesDatabase.dbType
+        
+    def _db_init_data_tables(self, q):
+        """
+        Initialise the underlying database tables.
+        @param q:           a database cursor to use.
+        """
+
+        #
+        # PROPERTIES table
+        #
+        q.execute(
+            """
+            create table PROPERTIES (
+                RESOURCENAME   text,
+                PROPERTYNAME   text,
+                PROPERTYVALUE  text
+            )
+            """
+        )

Modified: CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/static.py	2007-02-17 17:42:22 UTC (rev 1203)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/static.py	2007-02-17 18:01:37 UTC (rev 1204)
@@ -61,6 +61,7 @@
 from twistedcaldav.notifications import NotificationsCollectionResource, NotificationResource
 from twistedcaldav.resource import CalDAVResource, isCalendarCollectionResource, isPseudoCalendarCollectionResource
 from twistedcaldav.schedule import ScheduleInboxResource, ScheduleOutboxResource
+from twistedcaldav.sqlprops import sqlPropertyStore, SQLPropertiesDatabase
 from twistedcaldav.dropbox import DropBoxHomeResource, DropBoxCollectionResource, DropBoxChildResource
 from twistedcaldav.directory.calendar import DirectoryCalendarHomeProvisioningResource
 from twistedcaldav.directory.calendar import DirectoryCalendarHomeTypeProvisioningResource
@@ -71,6 +72,10 @@
     """
     CalDAV-accessible L{DAVFile} resource.
     """
+
+    db_names = (db_basename, SQLPropertiesDatabase.dbFilename)
+
+
     def __repr__(self):
         if self.isCalendarCollection():
             return "<%s (calendar collection): %s>" % (self.__class__.__name__, self.fp.path)
@@ -81,6 +86,14 @@
     # CalDAV
     ##
 
+    def deadProperties(self):
+        if not hasattr(self, "_dead_properties"):
+            #if self.fp.path.find("user01") != -1:
+                self._dead_properties = sqlPropertyStore(self)
+            #else:
+            #    self._dead_properties = xattrPropertyStore(self)
+        return self._dead_properties
+
     def resourceType(self):
 	if self.isCalendarCollection():
 	    return davxml.ResourceType.calendar
@@ -261,7 +274,7 @@
     def listChildren(self):
         return [
             child for child in super(CalDAVFile, self).listChildren()
-            if child != db_basename
+            if child not in CalDAVFile.db_names
         ]
 
     ##
@@ -289,7 +302,7 @@
                 for f in top.listdir():
     
                     # Ignore the database
-                    if top_level and f == db_basename:
+                    if top_level and f in CalDAVFile.db_names:
                         continue
     
                     child = top.child(f)

Copied: CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/test/test_sqlprops.py (from rev 1203, CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/test/test_sqlprops.py)
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/test/test_sqlprops.py	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1202/twistedcaldav/test/test_sqlprops.py	2007-02-17 18:01:37 UTC (rev 1204)
@@ -0,0 +1,187 @@
+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# DRI: Wilfredo Sanchez, wsanchez at apple.com
+##
+
+import os
+import time
+
+from twisted.web2.dav import davxml
+
+from twistedcaldav import caldavxml, customxml
+from twistedcaldav.root import RootResource
+from twistedcaldav.sqlprops import sqlPropertyStore, SQLPropertiesDatabase
+from twistedcaldav.static import CalDAVFile
+import twistedcaldav.test.util
+
+class SQLProps (twistedcaldav.test.util.TestCase):
+    """
+    SQL properties tests
+    """
+
+    props = (
+        davxml.DisplayName.fromString("My Name"),
+        davxml.ACL(
+            davxml.ACE(
+                davxml.Principal(davxml.Authenticated()),
+                davxml.Grant(davxml.Privilege(davxml.Read())),
+                davxml.Protected(),
+            ),
+        ),
+        caldavxml.CalendarDescription.fromString("My Calendar"),
+        customxml.TwistedScheduleAutoRespond(),
+    )
+    
+    def _setUpIndex(self):
+        self.collection_name, self.collection_uri = self.mkdtemp("sql")
+        rsrc = CalDAVFile(os.path.join(self.collection_name, "file.ics"))
+        return sqlPropertyStore(rsrc)
+        
+    def _setOnePropertyAndTest(self, prop):
+        index = self._setUpIndex()
+        index.set(prop)
+        self.assertTrue(index.contains(prop.qname()),
+                        msg="Could not find property %s." % prop)
+        self.assertTrue(index.get(prop.qname()) == prop,
+                        msg="Could not get property %s." % prop)
+        
+    def _setProperty(self, index, prop):
+        index.set(prop)
+        
+    def _testProperty(self, index, prop):
+        self.assertTrue(index.contains(prop.qname()),
+                        msg="Could not find property %s." % prop)
+        self.assertTrue(index.get(prop.qname()) == prop,
+                        msg="Could not get property %s." % prop)
+    
+    def _testPropertyList(self, proplist):
+        self.assertTrue(len(proplist) == len(SQLProps.props),
+                        msg="Number of properties returned %s not equal to number queried %s." % (len(proplist), len(SQLProps.props),))
+        for prop in SQLProps.props:
+            for k, v in proplist.iteritems():
+                if prop == v:
+                    del proplist[k]
+                    break
+        self.assertTrue(len(proplist) == 0,
+                        msg="Incorrect properties returned %s." % proplist)
+
+    def _testResourcePropertyList(self, num_resources, resourcedict):
+        self.assertTrue(len(resourcedict) == num_resources,
+                        msg="Number of resources returned %s not equal to number queried %s." % (len(resourcedict), num_resources,))
+        for i in xrange(num_resources):
+            fname = "file%04s.ics" % (i,)
+            self.assertTrue(resourcedict.has_key(fname),
+                            msg="Resource %s not returned in query results" % (fname,))
+            self._testPropertyList(resourcedict[fname])
+
+    def _setupMultipleResources(self, number):
+        self.collection_name, self.collection_uri = self.mkdtemp("sql")
+        for i in xrange(number):
+            rsrc = CalDAVFile(os.path.join(self.collection_name, "file%04s.ics" % (i,)))
+            index = sqlPropertyStore(rsrc)
+            for prop in SQLProps.props:
+                index.set(prop)
+        return index
+
+    def test_db_init_directory(self):
+        self.collection_name, self.collection_uri = self.mkdtemp("sql")
+        rsrc = CalDAVFile(self.collection_name)
+        index = sqlPropertyStore(rsrc)
+        db = index.index._db()
+        self.assertTrue(os.path.exists(os.path.join(os.path.dirname(self.collection_name), SQLPropertiesDatabase.dbFilename)),
+                        msg="Could not initialize index via collection resource.")
+
+    def test_db_init_root(self):
+        self.collection_name, self.collection_uri = self.mkdtemp("sql")
+        rsrc = RootResource(self.collection_name)
+        index = sqlPropertyStore(rsrc)
+        db = index.index._db()
+        self.assertTrue(os.path.exists(os.path.join(self.collection_name, SQLPropertiesDatabase.dbFilename)),
+                        msg="Could not initialize index via collection resource.")
+
+    def test_db_init_file(self):
+        index = self._setUpIndex()
+        db = index.index._db()
+        self.assertTrue(os.path.exists(os.path.join(self.collection_name, SQLPropertiesDatabase.dbFilename)),
+                        msg="Could not initialize index via file resource.")
+
+    def test_setoneproperty(self):
+        for prop in SQLProps.props:
+            self._setOnePropertyAndTest(prop)
+
+    def test_setunknownproperty(self):
+        doc = davxml.WebDAVDocument.fromString("""<?xml version="1.0" encoding="utf-8" ?><guess/>""")
+        self._setOnePropertyAndTest(doc.root_element)
+
+    def test_setmultipleproperties(self):
+        index = self._setUpIndex()
+        for prop in SQLProps.props:
+            self._setProperty(index, prop)
+        for prop in SQLProps.props:
+            self._testProperty(index, prop)
+        proplist = set(index.list())
+        expected_proplist = set([prop.qname() for prop in SQLProps.props])
+        self.assertTrue(proplist == expected_proplist,
+                        msg="Property lists do not match: %s != %s." % (proplist, expected_proplist))
+
+    def test_deleteproperties(self):
+        index = self._setUpIndex()
+        for prop in SQLProps.props:
+            self._setProperty(index, prop)
+        
+        remaining_props = [p for p in SQLProps.props]
+        for prop in SQLProps.props:
+            remaining_props.pop(0)
+            index.delete(prop.qname())
+            proplist = set(index.list())
+            expected_proplist = set([prop.qname() for prop in remaining_props])
+            self.assertTrue(proplist == expected_proplist,
+                            msg="Property lists do not match: %s != %s." % (proplist, expected_proplist))
+
+    def test_deleteallproperties(self):
+        index = self._setUpIndex()
+        for prop in SQLProps.props:
+            self._setProperty(index, prop)
+        
+        index.deleteAll()
+        for prop in SQLProps.props:
+            self.assertFalse(index.contains(prop.qname()),
+                            msg="Could not find property %s." % prop)
+
+    def test_getallproperties(self):
+        index = self._setUpIndex()
+        for prop in SQLProps.props:
+            self._setProperty(index, prop)
+        
+        result = index.getAll([p.qname() for p in SQLProps.props])
+        self._testPropertyList(result)
+
+    def test_getallresourceproperties(self):
+        num_resources = 10
+        index = self._setupMultipleResources(num_resources)
+        result = index.getAllResources([p.qname() for p in SQLProps.props])
+        self._testResourcePropertyList(num_resources, result)
+
+#    def test_timegetallresourceproperties(self):
+#        num_resources = 1000
+#        index = self._setupMultipleResources(num_resources)
+#        t1 = time.time()
+#        result = index.getAllResources([p.qname() for p in SQLProps.props])
+#        t2 = time.time()
+#        self.assertTrue(t1 == t2,
+#                        msg="Time for 1000 prop query = %s" % (t2 - t1,))
+#
+#        self._testResourcePropertyList(num_resources, result)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070217/7c95a4bf/attachment.html


More information about the calendarserver-changes mailing list