[CalendarServer-changes] [6741] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun Jan 16 19:24:11 PST 2011


Revision: 6741
          http://trac.macosforge.org/projects/calendarserver/changeset/6741
Author:   cdaboo at apple.com
Date:     2011-01-16 19:24:05 -0800 (Sun, 16 Jan 2011)
Log Message:
-----------
Make sure dropbox attachment mode is properly set. Minimise queries when doing dropbox operations.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/txdav/caldav/datastore/file.py
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/carddav/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql
    CalendarServer/trunk/txdav/common/datastore/sql_tables.py

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -748,13 +748,8 @@
         return davxml.ResourceType.dropboxhome #@UndefinedVariable
 
 
-    @inlineCallbacks
     def listChildren(self):
-        l = []
-        for everyCalendar in (yield self._newStoreHome.calendars()):
-            for everyObject in (yield everyCalendar.calendarObjects()):
-                l.append((yield everyObject.dropboxID()))
-        returnValue(l)
+        return self._newStoreHome.getAllDropboxIDs()
 
 
 
@@ -894,9 +889,7 @@
                 ),
             )
 
-        othersCanWrite = (
-            yield self._newStoreCalendarObject.attendeesCanManageAttachments()
-        )
+        othersCanWrite = self._newStoreCalendarObject.attendeesCanManageAttachments()
         cuas = (yield self._newStoreCalendarObject.component()).getAttendees()
         newACEs = []
         for calendarUserAddress in cuas:

Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -138,6 +138,17 @@
                     returnValue(calendarObject)
 
 
+    @inlineCallbacks
+    def getAllDropboxIDs(self):
+
+        dropboxIDs = []
+        for calendar in self.calendars():
+            for calendarObject in calendar.calendarObjects():
+                dropboxID = (yield calendarObject.dropboxID())
+                dropboxIDs.append(dropboxID)
+        
+        returnValue(dropboxIDs)
+
     @property
     def _calendarStore(self):
         return self._dataStore
@@ -483,7 +494,7 @@
 
     @inlineCallbacks
     def attendeesCanManageAttachments(self):
-        returnValue((yield self.component()).hasPropertyInAnyComponent("X-APPLE-DROPBOX"))
+        return self.component().hasPropertyInAnyComponent("X-APPLE-DROPBOX")
 
 
     def dropboxID(self):

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -53,8 +53,10 @@
     SQLLegacyCalendarShares, PostgresLegacyInboxIndexEmulator
 from txdav.common.datastore.sql_tables import CALENDAR_TABLE,\
     CALENDAR_BIND_TABLE, CALENDAR_OBJECT_REVISIONS_TABLE, CALENDAR_OBJECT_TABLE,\
-    _ATTACHMENTS_MODE_WRITE, CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE,\
-    CALENDAR_AND_CALENDAR_BIND, CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE
+    _ATTACHMENTS_MODE_NONE, _ATTACHMENTS_MODE_READ, _ATTACHMENTS_MODE_WRITE,\
+    CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE,\
+    CALENDAR_AND_CALENDAR_BIND, CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE,\
+    CALENDAR_OBJECT_AND_BIND_TABLE
 from txdav.common.icommondatastore import IndexedSearchException
 
 from vobject.icalendar import utc
@@ -91,16 +93,50 @@
     @inlineCallbacks
     def calendarObjectWithDropboxID(self, dropboxID):
         """
-        Implement lookup with brute-force scanning.
+        Implement lookup via queries.
         """
-        for calendar in (yield self.calendars()):
-            for calendarObject in (yield calendar.calendarObjects()):
-                dbid = yield calendarObject.dropboxID()
-                if dropboxID == dbid:
-                    returnValue(calendarObject)
+        rows = (yield self._txn.execSQL("""
+            select %(OBJECT:name)s.%(OBJECT:column_PARENT_RESOURCE_ID)s, %(OBJECT:column_RESOURCE_ID)s
+            from %(OBJECT:name)s
+            left outer join %(BIND:name)s on (
+              %(OBJECT:name)s.%(OBJECT:column_PARENT_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s
+            )
+            where
+             %(OBJECT:column_DROPBOX_ID)s = %%s and
+             %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s
+            """ % CALENDAR_OBJECT_AND_BIND_TABLE,
+            [dropboxID, self._resourceID,]
+        ))
 
+        if rows:
+            calendarID, objectID = rows[0]
+            calendar = (yield self.childWithID(calendarID))
+            if calendar:
+                calendarObject = (yield calendar.objectResourceWithID(objectID))
+                returnValue(calendarObject)
+        
+        returnValue(None)
 
     @inlineCallbacks
+    def getAllDropboxIDs(self):
+
+        rows = (yield self._txn.execSQL("""
+            select %(OBJECT:column_DROPBOX_ID)s
+            from %(OBJECT:name)s
+            left outer join %(BIND:name)s on (
+              %(OBJECT:name)s.%(OBJECT:column_PARENT_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s
+            )
+            where
+             %(OBJECT:column_DROPBOX_ID)s is not null and
+             %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s
+            order by %(OBJECT:column_DROPBOX_ID)s
+            """ % CALENDAR_OBJECT_AND_BIND_TABLE,
+            [self._resourceID]
+        ))
+        
+        returnValue([row[0] for row in rows])
+
+    @inlineCallbacks
     def createdHome(self):
         defaultCal = yield self.createCalendarWithName("calendar")
         props = defaultCal.properties()
@@ -108,8 +144,6 @@
             Opaque())
         yield self.createCalendarWithName("inbox")
 
-
-
 class Calendar(CommonHomeChild):
     """
     File-based implementation of L{ICalendar}.
@@ -245,9 +279,9 @@
 
     _objectTable = CALENDAR_OBJECT_TABLE
 
-    def __init__(self, calendar, name, uid, metadata=None):
+    def __init__(self, calendar, name, uid, resourceID=None, metadata=None):
 
-        super(CalendarObject, self).__init__(calendar, name, uid)
+        super(CalendarObject, self).__init__(calendar, name, uid, resourceID)
         
         if metadata is None:
             metadata = {}
@@ -271,6 +305,8 @@
               %(column_UID)s,
               %(column_MD5)s,
               character_length(%(column_TEXT)s),
+              %(column_ATTACHMENTS_MODE)s,
+              %(column_DROPBOX_ID)s,
               %(column_ACCESS)s,
               %(column_SCHEDULE_OBJECT)s,
               %(column_SCHEDULE_TAG)s,
@@ -290,6 +326,8 @@
          self._uid,
          self._md5,
          self._size,
+         self._attachment,
+         self._dropboxID,
          self._access,
          self._schedule_object,
          self._schedule_tag,
@@ -369,32 +407,48 @@
             organizer = ""
 
         # CALENDAR_OBJECT table update
+        self._uid = component.resourceUID()
         self._md5 = hashlib.md5(componentText).hexdigest()
         self._size = len(componentText)
+
+        # Determine attachment mode (ignore inbox's) - NB we have to do this
+        # after setting up other properties as UID at least is needed
+        self._attachment = _ATTACHMENTS_MODE_NONE
+        self._dropboxID = None
+        if self._parentCollection.name() != "inbox":
+            if component.hasPropertyInAnyComponent("X-APPLE-DROPBOX"):
+                self._attachment = _ATTACHMENTS_MODE_WRITE
+                self._dropboxID = (yield self.dropboxID())
+            elif component.hasPropertyInAnyComponent("ATTACH"):
+                # FIXME: really we ought to check to see if the ATTACH properties have URI values
+                # and if those are pointing to our server dropbox collections and only then set
+                # the read mode
+                self._attachment = _ATTACHMENTS_MODE_READ
+                self._dropboxID = (yield self.dropboxID())
+
         if inserting:
             self._resourceID, self._created, self._modified  = (
                 yield self._txn.execSQL(
                 """
                 insert into CALENDAR_OBJECT
                 (CALENDAR_RESOURCE_ID, RESOURCE_NAME, ICALENDAR_TEXT, ICALENDAR_UID, ICALENDAR_TYPE,
-                 ATTACHMENTS_MODE, ORGANIZER, RECURRANCE_MAX, ACCESS, SCHEDULE_OBJECT, SCHEDULE_TAG,
+                 ATTACHMENTS_MODE, DROPBOX_ID, ORGANIZER, RECURRANCE_MAX, ACCESS, SCHEDULE_OBJECT, SCHEDULE_TAG,
                  SCHEDULE_ETAGS, PRIVATE_COMMENTS, MD5)
                  values
-                (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
+                (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                 returning
                  RESOURCE_ID,
                  CREATED,
                  MODIFIED
                 """,
-                # FIXME: correct ATTACHMENTS_MODE based on X-APPLE-
-                # DROPBOX
                 [
                     self._calendar._resourceID,
                     self._name,
                     componentText,
-                    component.resourceUID(),
+                    self._uid,
                     component.resourceType(),
-                    _ATTACHMENTS_MODE_WRITE,
+                    self._attachment,
+                    self._dropboxID,
                     organizer,
                     normalizeForIndex(instances.limit) if instances.limit else None,
                     self._access,
@@ -410,21 +464,19 @@
                 """
                 update CALENDAR_OBJECT set
                 (ICALENDAR_TEXT, ICALENDAR_UID, ICALENDAR_TYPE, ATTACHMENTS_MODE,
-                 ORGANIZER, RECURRANCE_MAX, ACCESS, SCHEDULE_OBJECT, SCHEDULE_TAG,
+                 DROPBOX_ID, ORGANIZER, RECURRANCE_MAX, ACCESS, SCHEDULE_OBJECT, SCHEDULE_TAG,
                  SCHEDULE_ETAGS, PRIVATE_COMMENTS, MD5, MODIFIED)
                  =
-                (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, timezone('UTC', CURRENT_TIMESTAMP))
+                (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, timezone('UTC', CURRENT_TIMESTAMP))
                 where RESOURCE_ID = %s
                 returning MODIFIED
                 """,
-                # should really be filling out more fields: ORGANIZER,
-                # ORGANIZER_OBJECT, a correct ATTACHMENTS_MODE based on X-APPLE-
-                # DROPBOX
                 [
                     componentText,
-                    component.resourceUID(),
+                    self._uid,
                     component.resourceType(),
-                    _ATTACHMENTS_MODE_WRITE,
+                    self._attachment,
+                    self._dropboxID,
                     organizer,
                     normalizeForIndex(instances.limit) if instances.limit else None,
                     self._access,
@@ -446,7 +498,6 @@
                     self._resourceID,
                 ],
             )
-        self._uid = component.resourceUID()
 
 
         # CALENDAR_OBJECT table update
@@ -630,11 +681,8 @@
         attachment = (yield attachment.initFromStore())
         returnValue(attachment)
 
-    @inlineCallbacks
     def attendeesCanManageAttachments(self):
-        returnValue((yield self.component()).hasPropertyInAnyComponent(
-            "X-APPLE-DROPBOX"
-        ))
+        return self._attachment == _ATTACHMENTS_MODE_WRITE
 
 
     dropboxID = dropboxIDFromCalendarObject

Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -172,9 +172,9 @@
 
     _objectTable = ADDRESSBOOK_OBJECT_TABLE
 
-    def __init__(self, addressbook, name, uid, metadata=None):
+    def __init__(self, addressbook, name, uid, resourceID=None, metadata=None):
 
-        super(AddressBookObject, self).__init__(addressbook, name, uid)
+        super(AddressBookObject, self).__init__(addressbook, name, uid, resourceID)
 
 
     @property

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -417,7 +417,17 @@
         """
         return self._childClass.objectWithName(self, name, owned=True)
 
+    @memoizedKey("resourceID", "_children")
+    def childWithID(self, resourceID):
+        """
+        Retrieve the child with the given C{resourceID} contained in this
+        home.
 
+        @param name: a string.
+        @return: an L{ICalendar} or C{None} if no such child exists.
+        """
+        return self._childClass.objectWithID(self, resourceID)
+
     @memoizedKey("name", "_sharedChildren")
     def sharedChildWithName(self, name):
         """
@@ -822,7 +832,6 @@
         @param home: a L{CommonHome}.
         @param name: a string.
         @param owned: a boolean - whether or not to get a shared child
-        @param mustExist: a boolean - if False return and empty object
         @return: an L{CommonHomChild} or C{None} if no such child
             exists.
         """
@@ -865,6 +874,38 @@
 
     @classmethod
     @inlineCallbacks
+    def objectWithID(cls, home, resourceID):
+        """
+        Retrieve the child with the given C{resourceID} contained in this
+        C{home}.
+
+        @param home: a L{CommonHome}.
+        @param resourceID: a string.
+        @return: an L{CommonHomChild} or C{None} if no such child
+            exists.
+        """
+
+        data = yield home._txn.execSQL("""
+            select %(column_RESOURCE_NAME)s from %(name)s
+            where
+              %(column_RESOURCE_ID)s = %%s and
+              %(column_HOME_RESOURCE_ID)s = %%s
+            """ % cls._bindTable,
+            [
+                resourceID,
+                home._resourceID,
+            ]
+        )
+
+        if not data:
+            returnValue(None)
+        name = data[0][0]
+        child = cls(home, name, resourceID)
+        yield child.initFromStore()
+        returnValue(child)
+
+    @classmethod
+    @inlineCallbacks
     def create(cls, home, name):
         
         child = (yield cls.objectWithName(home, name, owned=True))
@@ -1033,27 +1074,41 @@
         if name in self._objects:
             return succeed(self._objects[name])
         else:
-            return self._makeObjectResource(name, None)
+            return self._makeObjectResource(name=name)
 
 
     def objectResourceWithUID(self, uid):
         if uid in self._objects:
             return succeed(self._objects[uid])
         else:
-            return self._makeObjectResource(None, uid)
+            return self._makeObjectResource(uid=uid)
 
 
+    def objectResourceWithID(self, resourceID):
+        if resourceID in self._objects:
+            return succeed(self._objects[resourceID])
+        else:
+            return self._makeObjectResource(resourceID=resourceID)
+
     @inlineCallbacks
-    def _makeObjectResource(self, name, uid):
+    def _makeObjectResource(self, name=None, uid=None, resourceID=None):
         """
         We create the empty object first then have it initialize itself from the store
         """
-        objectResource = (yield self._objectResourceClass.objectWithName(self, name, uid))
+        
+        if resourceID:
+            objectResource = (yield self._objectResourceClass.objectWithID(self, resourceID))
+        else:
+            objectResource = (yield self._objectResourceClass.objectWithName(self, name, uid))
         if objectResource:
             self._objects[objectResource.name()] = objectResource
             self._objects[objectResource.uid()] = objectResource
+            self._objects[objectResource._resourceID] = objectResource
         else:
-            self._objects[name if name else uid] = None
+            if resourceID:
+                self._objects[resourceID] = None
+            else:
+                self._objects[name if name else uid] = None
         returnValue(objectResource)
 
 
@@ -1430,9 +1485,9 @@
 
     _objectTable = None
 
-    def __init__(self, parent, name, uid, metadata=None):
+    def __init__(self, parent, name, uid, resourceID=None, metadata=None):
         self._parentCollection = parent
-        self._resourceID = None
+        self._resourceID = resourceID
         self._name = name
         self._uid = uid
         self._md5 = None
@@ -1483,10 +1538,15 @@
 
     @classmethod
     def objectWithName(cls, parent, name, uid):
-        objectResource = cls(parent, name, uid)
+        objectResource = cls(parent, name, uid, None)
         return objectResource.initFromStore()
 
     @classmethod
+    def objectWithID(cls, parent, resourceID):
+        objectResource = cls(parent, None, None, resourceID)
+        return objectResource.initFromStore()
+
+    @classmethod
     @inlineCallbacks
     def create(cls, parent, name, component, metadata):
 
@@ -1497,7 +1557,7 @@
         if name.startswith("."):
             raise ObjectResourceNameNotAllowedError(name)
         
-        objectResource = cls(parent, name, None, metadata)
+        objectResource = cls(parent, name, None, None, metadata=metadata)
         yield objectResource.setComponent(component, inserting=True)
         yield objectResource._loadPropertyStore(created=True)
 
@@ -1523,13 +1583,20 @@
                 """ % self._objectTable,
                 [self._name, self._parentCollection._resourceID]
             )
-        else:
+        elif self._uid:
             rows = yield self._txn.execSQL(self._selectAllColumns() + """
                 from %(name)s
                 where %(column_UID)s = %%s and %(column_PARENT_RESOURCE_ID)s = %%s
                 """ % self._objectTable,
                 [self._uid, self._parentCollection._resourceID]
             )
+        elif self._resourceID:
+            rows = yield self._txn.execSQL(self._selectAllColumns() + """
+                from %(name)s
+                where %(column_RESOURCE_ID)s = %%s and %(column_PARENT_RESOURCE_ID)s = %%s
+                """ % self._objectTable,
+                [self._resourceID, self._parentCollection._resourceID]
+            )
         if rows:
             self._initFromRow(tuple(rows[0]))
             yield self._loadPropertyStore()

Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema_v1.sql	2011-01-17 03:24:05 UTC (rev 6741)
@@ -168,7 +168,8 @@
   ICALENDAR_TEXT       text         not null,
   ICALENDAR_UID        varchar(255) not null,
   ICALENDAR_TYPE       varchar(255) not null,
-  ATTACHMENTS_MODE     integer      not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  DROPBOX_ID           varchar(255),
   ORGANIZER            varchar(255),
   ORGANIZER_OBJECT     integer      references CALENDAR_OBJECT,
   RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
@@ -193,9 +194,15 @@
 create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID on
   CALENDAR_OBJECT(CALENDAR_RESOURCE_ID);
 
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
 create index CALENDAR_OBJECT_ORGANIZER_OBJECT on
   CALENDAR_OBJECT(ORGANIZER_OBJECT);
 
+create index CALENDAR_OBJECT_DROPBOX_ID on
+  CALENDAR_OBJECT(DROPBOX_ID);
+
 -- Enumeration of attachment modes
 
 create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
@@ -203,8 +210,9 @@
   DESCRIPTION varchar(16) not null unique
 );
 
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'read' );
-insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'write');
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
 
 
 -- Enumeration of calendar access types

Modified: CalendarServer/trunk/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_tables.py	2011-01-15 21:01:57 UTC (rev 6740)
+++ CalendarServer/trunk/txdav/common/datastore/sql_tables.py	2011-01-17 03:24:05 UTC (rev 6741)
@@ -125,6 +125,8 @@
     "column_RESOURCE_NAME"      : "RESOURCE_NAME",
     "column_TEXT"               : "ICALENDAR_TEXT",
     "column_UID"                : "ICALENDAR_UID",
+    "column_ATTACHMENTS_MODE"   : "ATTACHMENTS_MODE",
+    "column_DROPBOX_ID"         : "DROPBOX_ID",
     "column_ACCESS"             : "ACCESS",
     "column_SCHEDULE_OBJECT"    : "SCHEDULE_OBJECT",
     "column_SCHEDULE_TAG"       : "SCHEDULE_TAG",
@@ -150,12 +152,14 @@
 
 # Various constants
 
-_BIND_STATUS_INVITED = 0
+_BIND_STATUS_INVITED  = 0
 _BIND_STATUS_ACCEPTED = 1
 _BIND_STATUS_DECLINED = 2
-_BIND_STATUS_INVALID = 3
+_BIND_STATUS_INVALID  = 3
 
-_ATTACHMENTS_MODE_WRITE = 1
+_ATTACHMENTS_MODE_NONE  = 0
+_ATTACHMENTS_MODE_READ  = 1
+_ATTACHMENTS_MODE_WRITE = 2
 
 _BIND_MODE_OWN = 0
 _BIND_MODE_READ = 1
@@ -167,6 +171,10 @@
 CALENDAR_AND_CALENDAR_BIND.update([("CHILD:%s" % (k,), v) for k,v in CALENDAR_TABLE.items()])
 CALENDAR_AND_CALENDAR_BIND.update([("BIND:%s" % (k,), v) for k,v in CALENDAR_BIND_TABLE.items()])
 
+CALENDAR_OBJECT_AND_BIND_TABLE = {}
+CALENDAR_OBJECT_AND_BIND_TABLE.update([("OBJECT:%s" % (k,), v) for k,v in CALENDAR_OBJECT_TABLE.items()])
+CALENDAR_OBJECT_AND_BIND_TABLE.update([("BIND:%s" % (k,), v) for k,v in CALENDAR_BIND_TABLE.items()])
+
 CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE = {}
 CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE.update([("REV:%s" % (k,), v) for k,v in CALENDAR_OBJECT_REVISIONS_TABLE.items()])
 CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE.update([("BIND:%s" % (k,), v) for k,v in CALENDAR_BIND_TABLE.items()])
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110116/df3238f1/attachment-0001.html>


More information about the calendarserver-changes mailing list