[CalendarServer-changes] [6201] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun Aug 29 19:28:25 PDT 2010


Revision: 6201
          http://trac.macosforge.org/projects/calendarserver/changeset/6201
Author:   glyph at apple.com
Date:     2010-08-29 19:28:22 -0700 (Sun, 29 Aug 2010)
Log Message:
-----------
store-to-store migration API and tests

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
    CalendarServer/trunk/twistedcaldav/test/test_sharing.py
    CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
    CalendarServer/trunk/txdav/base/propertystore/test/test_sql.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_scheduling.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/trunk/txdav/caldav/datastore/util.py
    CalendarServer/trunk/txdav/caldav/icalendarstore.py
    CalendarServer/trunk/txdav/carddav/datastore/test/test_sql.py
    CalendarServer/trunk/txdav/common/datastore/file.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/test/util.py

Modified: CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/twistedcaldav/test/test_calendarquery.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -34,7 +34,7 @@
 from twistedcaldav.config import config
 from twistedcaldav.test.util import HomeTestCase
 from twisted.internet.defer import inlineCallbacks, returnValue
-from txdav.caldav.datastore.test.test_sql import buildStore
+from txdav.common.datastore.test.util import buildStore
 from txdav.caldav.datastore.test.common import StubNotifierFactory
 
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_sharing.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/twistedcaldav/test/test_sharing.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -25,9 +25,11 @@
 from twistedcaldav.config import config
 from twistedcaldav.test.util import HomeTestCase, norequest
 from twistedcaldav.resource import CalDAVResource
-from txdav.caldav.datastore.test.test_sql import buildStore
+from txdav.common.datastore.test.util import buildStore
 from txdav.caldav.datastore.test.common import StubNotifierFactory
 
+sharedOwnerType = davxml.ResourceType.sharedownercalendar #@UndefinedVariable
+regularCalendarType = davxml.ResourceType.calendar #@UndefinedVariable
 
 class SharingTests(HomeTestCase):
 
@@ -119,14 +121,14 @@
         request = SimpleRequest(self.site, "MKCOL", "/calendar/")
 
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.calendar)
+        self.assertEquals(rtype, regularCalendarType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, request))
         self.assertEquals(propInvite, None)
 
         self.resource.upgradeToShare()
 
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.sharedownercalendar)
+        self.assertEquals(rtype, sharedOwnerType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, request))
         self.assertEquals(propInvite, customxml.Invite())
         
@@ -140,14 +142,14 @@
         request = SimpleRequest(self.site, "PROPPATCH", "/calendar/")
 
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.calendar)
+        self.assertEquals(rtype, regularCalendarType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, request))
         self.assertEquals(propInvite, None)
 
         self.resource.upgradeToShare()
 
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.sharedownercalendar)
+        self.assertEquals(rtype, sharedOwnerType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, request))
         self.assertEquals(propInvite, customxml.Invite())
         
@@ -158,19 +160,17 @@
 
     @inlineCallbacks
     def test_downgradeFromShare(self):
-        request = SimpleRequest(self.site, "PROPPATCH", "/calendar/")
-
-        self.resource.writeDeadProperty(davxml.ResourceType.sharedownercalendar)
+        self.resource.writeDeadProperty(sharedOwnerType)
         self.resource.writeDeadProperty(customxml.Invite())
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.sharedownercalendar)
+        self.assertEquals(rtype, sharedOwnerType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, None))
         self.assertEquals(propInvite, customxml.Invite())
 
         yield self.resource.downgradeFromShare(None)
 
         rtype = self.resource.resourceType()
-        self.assertEquals(rtype, davxml.ResourceType.calendar)
+        self.assertEquals(rtype, regularCalendarType)
         propInvite = (yield self.resource.readProperty(customxml.Invite, None))
         self.assertEquals(propInvite, None)
         

Modified: CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_wrapping.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/twistedcaldav/test/test_wrapping.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -41,7 +41,7 @@
 
 from txdav.carddav.datastore.test.test_file import vcard4_text
 
-from txdav.caldav.datastore.test.test_sql import buildStore
+from txdav.common.datastore.test.util import buildStore
 from txdav.caldav.datastore.test.common import StubNotifierFactory, \
     assertProvides
 from txdav.caldav.icalendarstore import ICalendarHome
@@ -258,8 +258,9 @@
         )
         self.commit()
         self.assertIsInstance(dropBoxResource, DropboxCollection)
+        dropboxHomeType = davxml.ResourceType.dropboxhome #@UndefinedVariable
         self.assertEquals(dropBoxResource.resourceType(),
-                          davxml.ResourceType.dropboxhome)
+                          dropboxHomeType)
 
 
     @inlineCallbacks
@@ -271,8 +272,9 @@
         C{CalendarHome.calendarWithName}.
         """
         calDavFile = yield self.getResource("calendars/users/wsanchez/calendar")
+        regularCalendarType = davxml.ResourceType.calendar #@UndefinedVariable
         self.assertEquals(calDavFile.resourceType(),
-                          davxml.ResourceType.calendar)
+                          regularCalendarType)
         self.commit()
 
 

Modified: CalendarServer/trunk/txdav/base/propertystore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/base/propertystore/test/test_sql.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/base/propertystore/test/test_sql.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -23,7 +23,7 @@
 
 from txdav.caldav.datastore.test.common import StubNotifierFactory
 
-from txdav.common.datastore.test.util import SQLStoreBuilder
+from txdav.common.datastore.test.util import buildStore
 
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.test import base
@@ -36,10 +36,6 @@
 
 
 
-theStoreBuilder = SQLStoreBuilder()
-buildStore = theStoreBuilder.buildStore
-
-
 class PropertyStoreTest(base.PropertyStoreTest):
 
     def _preTest(self):

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -16,8 +16,8 @@
 ##
 from zope.interface.declarations import implements
 from txdav.caldav.icalendarstore import ICalendarHome, ICalendar, ICalendarObject,\
-    ICalendarTransaction
-from txdav.idav import IDataStore
+    ICalendarTransaction, ICalendarStore
+
 from twisted.python.util import FancyEqMixin
 from twisted.python.components import proxyForInterface
 
@@ -137,14 +137,12 @@
 #        return self._subCalendar.calendarObjectWithName(name)
 
 
-class ImplicitStore(object):
+class ImplicitStore(proxyForInterface(ICalendarStore, "_calendarStore")):
     """
     This is a wrapper around an L{ICalendarStore} that implements implicit
     scheduling.
     """
 
-    implements(IDataStore)
-
     def __init__(self, calendarStore):
         """
         Create an L{ImplicitStore} wrapped around another

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -1184,7 +1184,33 @@
                 calendar2.calendarObjectWithUID(obj.uid()), None)
 
 
+    def test_eachCalendarHome(self):
+        """
+        L{ICalendarTransaction.eachCalendarHome} returns an iterator that
+        yields 2-tuples of (transaction, home).
+        """
+        # create some additional calendar homes
+        additionalUIDs = set('alpha-uid home2 home3 beta-uid'.split())
+        txn = self.transactionUnderTest()
+        for name in additionalUIDs:
+            txn.calendarHomeWithUID(name, create=True)
+        self.commit()
+        foundUIDs = set([])
+        lastTxn = None
+        for txn, home in self.storeUnderTest().eachCalendarHome():
+            self.addCleanup(txn.commit)
+            foundUIDs.add(home.uid())
+            self.assertNotIdentical(lastTxn, txn)
+            lastTxn = txn
+        requiredUIDs = set([
+            uid for uid in self.requirements
+            if self.requirements[uid] is not None
+        ])
+        expectedUIDs = additionalUIDs.union(requiredUIDs)
+        self.assertEquals(foundUIDs, expectedUIDs)
 
+
+
 class StubNotifierFactory(object):
 
     """ For testing push notifications without an XMPP server """

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -444,11 +444,14 @@
     File storage tests.
     """
 
+    calendarStore = None
+
     def storeUnderTest(self):
         """
         Create and return a L{CalendarStore} for testing.
         """
-        setUpCalendarStore(self)
+        if self.calendarStore is None:
+            setUpCalendarStore(self)
         return self.calendarStore
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_scheduling.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_scheduling.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_scheduling.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -16,6 +16,14 @@
 
 """
 Tests for L{txdav.caldav.datastore.scheduling}.
+
+The aforementioned module is intended to eventually support implicit
+scheduling; however, it does not currently.  The interim purpose of this module
+and accompanying tests is to effectively test the interface specifications to
+make sure that the common tests don't require anything I{not} specified in the
+interface, so that dynamic proxies specified with a tool like
+C{proxyForInterface} can be used to implement features such as implicit
+scheduling or data caching as middleware in the data-store layer.
 """
 
 from twisted.trial.unittest import TestCase
@@ -42,7 +50,10 @@
     Tests for L{ImplicitSchedulingStore}.
     """
 
+    implicitStore = None
+
     def storeUnderTest(self):
-        setUpCalendarStore(self)
-        self.implicitStore = ImplicitStore(self.calendarStore)
+        if self.implicitStore is None:
+            setUpCalendarStore(self)
+            self.implicitStore = ImplicitStore(self.calendarStore)
         return self.implicitStore

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -24,18 +24,21 @@
 from txdav.caldav.datastore.test.common import CommonTests as CalendarCommonTests
 
 from txdav.common.datastore.sql import ECALENDARTYPE
-from txdav.common.datastore.test.util import SQLStoreBuilder
+from txdav.common.datastore.test.util import buildStore
 from txdav.common.icommondatastore import NoSuchHomeChildError
 
 from twisted.trial import unittest
 from twisted.internet.defer import inlineCallbacks
 from twisted.internet.threads import deferToThread
 from twext.python.vcomponent import VComponent
+from twext.web2.dav.element.rfc2518 import GETContentLanguage, ResourceType
 
+from txdav.caldav.datastore.test.test_file import setUpCalendarStore
+from txdav.caldav.datastore.util import _migrateCalendar, migrateHome
+from txdav.base.propertystore.base import PropertyName
 
-theStoreBuilder = SQLStoreBuilder()
-buildStore = theStoreBuilder.buildStore
 
+
 class CalendarSQLStorageTests(CalendarCommonTests, unittest.TestCase):
     """
     Calendar SQL storage tests.
@@ -44,12 +47,12 @@
     @inlineCallbacks
     def setUp(self):
         super(CalendarSQLStorageTests, self).setUp()
-        self.calendarStore = yield buildStore(self, self.notifierFactory)
+        self._sqlCalendarStore = yield buildStore(self, self.notifierFactory)
         self.populate()
 
 
     def populate(self):
-        populateTxn = self.calendarStore.newTransaction()
+        populateTxn = self.storeUnderTest().newTransaction()
         for homeUID in self.requirements:
             calendars = self.requirements[homeUID]
             if calendars is not None:
@@ -79,8 +82,112 @@
         """
         Create and return a L{CalendarStore} for testing.
         """
-        return self.calendarStore
+        return self._sqlCalendarStore
 
+
+    def assertCalendarsSimilar(self, a, b, bCalendarFilter=None):
+        """
+        Assert that two calendars have a similar structure (contain the same
+        events).
+        """
+        def namesAndComponents(x, filter=lambda x:x.component()):
+            return dict([(fromObj.name(), filter)
+                         for fromObj in x.calendarObjects()])
+        if bCalendarFilter is not None:
+            extra = [bCalendarFilter]
+        else:
+            extra = []
+        self.assertEquals(namesAndComponents(a), namesAndComponents(b, *extra))
+
+
+    def assertPropertiesSimilar(self, a, b, disregard=[]):
+        """
+        Assert that two objects with C{properties} methods have similar
+        properties.
+        
+        @param disregard: a list of L{PropertyName} keys to discard from both
+            input and output.
+        """
+        def sanitize(x):
+            result = dict(x.properties().items())
+            for key in disregard:
+                result.pop(key, None)
+            return result
+        self.assertEquals(sanitize(a), sanitize(b))
+
+
+    def fileTransaction(self):
+        """
+        Create a file-backed calendar transaction, for migration testing.
+        """
+        setUpCalendarStore(self)
+        fileStore = self.calendarStore
+        txn = fileStore.newTransaction()
+        self.addCleanup(txn.commit)
+        return txn
+
+
+    def test_migrateCalendarFromFile(self):
+        """
+        C{_migrateCalendar()} can migrate a file-backed calendar to a database-
+        backed calendar.
+        """
+        fromCalendar = self.fileTransaction().calendarHomeWithUID(
+            "home1").calendarWithName("calendar_1")
+        toHome = self.transactionUnderTest().calendarHomeWithUID(
+            "new-home", create=True)
+        toCalendar = toHome.calendarWithName("calendar")
+        _migrateCalendar(fromCalendar, toCalendar, lambda x: x.component())
+        self.assertCalendarsSimilar(fromCalendar, toCalendar)
+
+
+    def test_migrateHomeFromFile(self):
+        """
+        L{migrateHome} will migrate an L{ICalendarHome} provider from one
+        backend to another; in this specific case, from the file-based backend
+        to the SQL-based backend.
+        """
+        fromHome = self.fileTransaction().calendarHomeWithUID("home1")
+
+        builtinProperties = [PropertyName.fromElement(ResourceType)]
+
+        # Populate an arbitrary / unused dead properties so there's something
+        # to verify against.
+
+        key = PropertyName.fromElement(GETContentLanguage)
+        fromHome.properties()[key] = GETContentLanguage("C")
+        fromHome.calendarWithName("calendar_1").properties()[key] = (
+            GETContentLanguage("pig-latin")
+        )
+        toHome = self.transactionUnderTest().calendarHomeWithUID(
+            "new-home", create=True
+        )
+        migrateHome(fromHome, toHome, lambda x: x.component())
+        self.assertEquals(set([c.name() for c in toHome.calendars()]),
+                          set([k for k in self.requirements['home1'].keys()
+                               if self.requirements['home1'][k] is not None]))
+        for c in fromHome.calendars():
+            self.assertPropertiesSimilar(
+                c, toHome.calendarWithName(c.name()),
+                builtinProperties
+            )
+        self.assertPropertiesSimilar(fromHome, toHome, builtinProperties)
+
+
+    def test_eachCalendarHome(self):
+        """
+        L{ICalendarStore.eachCalendarHome} is currently stubbed out by
+        L{txdav.common.datastore.sql.CommonDataStore}.
+        """
+        return super(CalendarSQLStorageTests, self).test_eachCalendarHome()
+
+
+    test_eachCalendarHome.todo = (
+        "stubbed out, as migration only needs to go from file->sql currently")
+
+
+
+
     @inlineCallbacks
     def test_homeProvisioningConcurrency(self):
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/util.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/datastore/util.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -20,7 +20,7 @@
 from twext.python.vcomponent import InvalidICalendarDataError
 from twext.python.vcomponent import VComponent
 
-from txdav.common.icommondatastore import InvalidObjectResourceError,\
+from txdav.common.icommondatastore import InvalidObjectResourceError, \
     NoSuchObjectResourceError
 
 
@@ -28,7 +28,8 @@
     """
     Validate a calendar component for a particular calendar.
 
-    @param calendarObject: The calendar object whose component will be replaced.
+    @param calendarObject: The calendar object whose component will be
+        replaced.
     @type calendarObject: L{ICalendarObject}
 
     @param calendar: The calendar which the L{ICalendarObject} is present in.
@@ -74,15 +75,61 @@
     if dropboxProperty is not None:
         componentDropboxID = dropboxProperty.value().split("/")[-1]
         return componentDropboxID
-    attachProperty = calendarObject.component().getFirstPropertyInAnyComponent("ATTACH")
+    attachProperty = calendarObject.component().getFirstPropertyInAnyComponent(
+        "ATTACH"
+    )
     if attachProperty is not None:
         # Make sure the value type is URI
         valueType = attachProperty.params().get("VALUE", ("TEXT",))
-        if valueType[0] == "URI": 
+        if valueType[0] == "URI":
             # FIXME: more aggressive checking to see if this URI is really the
             # 'right' URI.  Maybe needs to happen in the front end.
             attachPath = attachProperty.value().split("/")[-2]
             return attachPath
-    
+
     return calendarObject.uid() + ".dropbox"
-        
\ No newline at end of file
+
+
+def _migrateCalendar(inCalendar, outCalendar, getComponent):
+    """
+    Copy all calendar objects and properties in the given input calendar to the
+    given output calendar.
+
+    @param inCalendar: the L{ICalendar} to retrieve calendar objects from.
+    @param outCalendar: the L{ICalendar} to store calendar objects to.
+    @param getComponent: a 1-argument callable; see L{migrateHome}.
+    """
+    outCalendar.properties().update(inCalendar.properties())
+    for calendarObject in inCalendar.calendarObjects():
+        outCalendar.createCalendarObjectWithName(
+            calendarObject.name(),
+            calendarObject.component()) # XXX WRONG SHOULD CALL getComponent
+        outCalendar.calendarObjectWithName(
+            calendarObject.name()).properties().update(
+                calendarObject.properties())
+        # XXX attachments
+
+
+def migrateHome(inHome, outHome, getComponent):
+    """
+    Copy all calendars and properties in the given input calendar to the given
+    output calendar.
+
+    @param inHome: the L{ICalendarHome} to retrieve calendars and properties
+        from.
+
+    @param outHome: the L{ICalendarHome} to store calendars and properties
+        into.
+
+    @param getComponent: a 1-argument callable that takes an L{ICalendarObject}
+        (from a calendar in C{inHome}) and returns a L{VComponent} (to store in
+        a calendar in outHome).
+    """
+    outHome.removeCalendarWithName("calendar")
+    outHome.removeCalendarWithName("inbox")
+    outHome.properties().update(inHome.properties())
+    for calendar in inHome.calendars():
+        name = calendar.name()
+        outHome.createCalendarWithName(name)
+        outCalendar = outHome.calendarWithName(name)
+        _migrateCalendar(calendar, outCalendar, getComponent)

Modified: CalendarServer/trunk/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/icalendarstore.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/caldav/icalendarstore.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -19,9 +19,9 @@
 Calendar store interfaces
 """
 
-from txdav.common.icommondatastore import ICommonTransaction,\
+from txdav.common.icommondatastore import ICommonTransaction, \
     IShareableCollection
-from txdav.idav import IDataStoreResource
+from txdav.idav import IDataStoreResource, IDataStore
 
 from txdav.idav import INotifier
 
@@ -62,6 +62,23 @@
         """
 
 
+
+class ICalendarStore(IDataStore):
+    """
+    API root for calendar data storage.
+    """
+
+    def eachCalendarHome(self):
+        """
+        Enumerate all calendar homes in this store, with each one in an
+        accompanying transaction.
+
+        @return: an iterator of 2-tuples of C{(transaction, calendar home)}
+            where C{transaction} is an L{ITransaction} provider and C{calendar
+            home} is an L{ICalendarHome} provider.
+        """
+
+
 #
 # Interfaces
 #

Modified: CalendarServer/trunk/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/test/test_sql.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/carddav/datastore/test/test_sql.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -24,15 +24,13 @@
 from txdav.carddav.datastore.test.common import CommonTests as AddressBookCommonTests
 
 from txdav.common.datastore.sql import EADDRESSBOOKTYPE
-from txdav.common.datastore.test.util import SQLStoreBuilder
+from txdav.common.datastore.test.util import buildStore
 
 from twisted.trial import unittest
 from twisted.internet.defer import inlineCallbacks
 from twisted.internet.threads import deferToThread
 from twistedcaldav.vcard import Component as VCard
 
-theStoreBuilder = SQLStoreBuilder()
-buildStore = theStoreBuilder.buildStore
 
 class AddressBookSQLStorageTests(AddressBookCommonTests, unittest.TestCase):
     """

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -31,6 +31,7 @@
 from twistedcaldav.notifications import NotificationRecord
 from twistedcaldav.notifications import NotificationsDatabase as OldNotificationIndex
 from twistedcaldav.sharing import SharedCollectionsDatabase
+from txdav.caldav.icalendarstore import ICalendarStore
 
 from txdav.common.icommondatastore import HomeChildNameNotAllowedError, \
     HomeChildNameAlreadyExistsError, NoSuchHomeChildError, \
@@ -41,7 +42,7 @@
 from txdav.base.datastore.file import DataStoreTransaction, DataStore, writeOperation, \
     hidden, isValidName, FileMetaDataMixin
 from txdav.base.datastore.util import cached
-from txdav.idav import IDataStore
+
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.xattr import PropertyStore
 
@@ -65,7 +66,7 @@
     @ivar _path: A L{CachingFilePath} referencing a directory on disk that
         stores all calendar and addressbook data for a group of UIDs.
     """
-    implements(IDataStore)
+    implements(ICalendarStore)
 
     def __init__(self, path, notifierFactory, enableCalendars=True,
         enableAddressBooks=True):
@@ -82,14 +83,48 @@
         self._notifierFactory = notifierFactory
         self._transactionClass = CommonStoreTransaction
 
+
     def newTransaction(self, name='no name'):
         """
         Create a new transaction.
 
         @see Transaction
         """
-        return self._transactionClass(self, name, self.enableCalendars, self.enableAddressBooks, self._notifierFactory)
+        return self._transactionClass(
+            self, name, self.enableCalendars,
+            self.enableAddressBooks, self._notifierFactory
+        )
 
+
+    def _homesOfType(self, storeType):
+        """
+        Common implementation of L{ICalendarStore.eachCalendarHome} and
+        L{IAddressBookStore.eachAddressbookHome}; see those for a description
+        of the return type.
+
+        @param storeType: one of L{EADDRESSBOOKTYPE} or L{ECALENDARTYPE}.
+        """
+        top = self._path.child(TOPPATHS[storeType]).child(UIDPATH)
+        for firstPrefix in top.children():
+            if not isValidName(firstPrefix.basename()):
+                continue
+            for secondPrefix in firstPrefix.children():
+                if not isValidName(secondPrefix.basename()):
+                    continue
+                for actualHome in secondPrefix.children():
+                    uid = actualHome.basename()
+                    if not isValidName(uid):
+                        continue
+                    txn = self.newTransaction("enumerate home %r" % (uid,))
+                    home = txn.homeWithUID(storeType, uid, False)
+                    yield (txn, home)
+
+
+    def eachCalendarHome(self):
+        return self._homesOfType(ECALENDARTYPE)
+
+
+
 class CommonStoreTransaction(DataStoreTransaction):
     """
     In-memory implementation of
@@ -672,7 +707,7 @@
 
 
     def syncToken(self):
-        
+
         try:
             urnuuid = str(self.properties()[PropertyName.fromElement(ResourceID)].children[0])
         except KeyError:

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -1,3 +1,4 @@
+# -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
 ##
 # Copyright (c) 2010 Apple Inc. All rights reserved.
 #
@@ -36,7 +37,7 @@
 from twistedcaldav.customxml import NotificationType
 
 from txdav.common.datastore.sql_legacy import PostgresLegacyNotificationsEmulator
-from txdav.caldav.icalendarstore import ICalendarTransaction
+from txdav.caldav.icalendarstore import ICalendarTransaction, ICalendarStore
 
 from txdav.carddav.iaddressbookstore import IAddressBookTransaction
 
@@ -51,7 +52,7 @@
     INotificationObject
 from txdav.base.datastore.sql import memoized
 from txdav.base.datastore.util import cached
-from txdav.idav import IDataStore, AlreadyFinishedError
+from txdav.idav import AlreadyFinishedError
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.sql import PropertyStore
 
@@ -67,7 +68,7 @@
 
 class CommonDataStore(Service, object):
 
-    implements(IDataStore)
+    implements(ICalendarStore)
 
     def __init__(self, connectionFactory, notifierFactory, attachmentsPath,
                  enableCalendars=True, enableAddressBooks=True):
@@ -78,6 +79,13 @@
         self.attachmentsPath = attachmentsPath
         self.enableCalendars = enableCalendars
         self.enableAddressBooks = enableAddressBooks
+        
+        
+    def eachCalendarHome(self):
+        """
+        @see L{ICalendarStore.eachCalendarHome}
+        """
+        return []
 
 
     def newTransaction(self, label="unlabeled"):

Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/util.py	2010-08-28 02:53:27 UTC (rev 6200)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py	2010-08-30 02:28:22 UTC (rev 6201)
@@ -137,3 +137,6 @@
                 log.err()
         cleanupConn.commit()
         cleanupConn.close()
+
+theStoreBuilder = SQLStoreBuilder()
+buildStore = theStoreBuilder.buildStore
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100829/e26f3099/attachment-0001.html>


More information about the calendarserver-changes mailing list