[CalendarServer-changes] [9903] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Fri Oct 5 21:05:58 PDT 2012


Revision: 9903
          http://trac.calendarserver.org//changeset/9903
Author:   gaya at apple.com
Date:     2012-10-05 21:05:58 -0700 (Fri, 05 Oct 2012)
Log Message:
-----------
Add ADDRESS_BOOK_OBJECT KIND row

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/vcard.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/vcard.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/vcard.py	2012-10-06 00:21:26 UTC (rev 9902)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/vcard.py	2012-10-06 04:05:58 UTC (rev 9903)
@@ -104,7 +104,7 @@
         @return: the duplicated vcard.
         """
         return Property(None, None, params=None, pycard=self._pycard.duplicate())
-        
+
     def name  (self): return self._pycard.getName()
 
     def value (self): return self._pycard.getValue().getValue()
@@ -144,7 +144,7 @@
             attrs = self._pycard.getAttributes()[name.upper()]
         except KeyError:
             return []
-        
+
         for attr in attrs:
             results.extend(attr.getValues())
         return results
@@ -162,7 +162,7 @@
         self._pycard.setAttributes({})
 
     def removeParameterValue(self, paramname, paramvalue):
-        
+
         paramname = paramname.upper()
         for attrName in self.parameterNames():
             if attrName.upper() == paramname:
@@ -188,7 +188,7 @@
         else:
             # Valid utf-8 please
             string.decode("utf-8")
-        
+
         # No BOMs please
         if string[:3] == codecs.BOM_UTF8:
             string = string[3:]
@@ -222,7 +222,7 @@
         else:
             # Valid utf-8 please
             string.decode("utf-8")
-        
+
         # No BOMs please
         if string[:3] == codecs.BOM_UTF8:
             string = string[3:]
@@ -288,11 +288,11 @@
             # even though it's names as a private variable.
             if "parent" in kwargs:
                 parent = kwargs["parent"]
-                
+
                 if parent is not None:
                     if not isinstance(parent, Component):
                         raise TypeError("Not a Component: %r" % (parent,))
-                    
+
                 self._parent = parent
             else:
                 self._parent = None
@@ -317,7 +317,7 @@
     # FIXME: Should this not be in __eq__?
     def same(self, other):
         return self._pycard == other._pycard
-    
+
     def name(self):
         """
         @return: the name of the iCalendar type of this component.
@@ -330,7 +330,7 @@
         @return: the duplicated vcard.
         """
         return Component(None, pycard=self._pycard.duplicate())
-        
+
     def hasProperty(self, name):
         """
         @param name: the name of the property whose existence is being tested.
@@ -349,7 +349,7 @@
         if len(properties) == 1: return properties[0]
         if len(properties) > 1: raise InvalidVCardDataError("More than one %s property in component %r" % (name, self))
         return None
-        
+
     def properties(self, name=None):
         """
         @param name: if given and not C{None}, restricts the returned properties
@@ -398,7 +398,7 @@
         Add or replace a property in this component.
         @param property: the L{Property} to add or replace in this component.
         """
-        
+
         # Remove all existing ones first
         self._pycard.removeProperties(property.name())
         self.addProperty(property)
@@ -414,6 +414,28 @@
 
         return self._resource_uid
 
+    def resourceKind(self):
+        """
+        @return: the kind of the subcomponents in this component.
+        """
+        assert self.name() == "VCARD", "Not a vcard: %r" % (self,)
+
+        if not hasattr(self, "_resource_kind"):
+            self._resource_kind = self.propertyValue("X-ADDRESSBOOKSERVER-KIND")
+
+        return self._resource_kind
+
+    def resourceMembers(self):
+        """
+        @return: an iterable of L{Property} objects, one for each member of this
+        """
+        assert self.name() == "VCARD", "Not a vcard: %r" % (self,)
+
+        if not hasattr(self, "_resource_members"):
+            self._resource_members = self.properties("X-ADDRESSBOOKSERVER-MEMBERS")
+
+        return self._resource_members
+
     def validVCardData(self, doFix=True, doRaise=True):
         """
         @return: tuple of fixed, unfixed issues
@@ -431,7 +453,7 @@
                 raise InvalidVCardDataError("Calendar data had unfixable problems:\n  %s" % ("\n  ".join(unfixed),))
         if fixed:
             log.debug("vCard data had fixable problems:\n  %s" % ("\n  ".join(fixed),))
-        
+
         return fixed, unfixed
 
     def validForCardDAV(self):
@@ -447,7 +469,7 @@
         uid = self.propertyValue("UID")
         if uid is None:
             raise InvalidVCardDataError("All vCards must have UIDs")
-        
+
         # Control character check - only HTAB, CR, LF allowed for characters in the range 0x00-0x1F
         s = str(self)
         if len(s.translate(None, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F")) != len(s):

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-06 00:21:26 UTC (rev 9902)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-06 04:05:58 UTC (rev 9903)
@@ -41,22 +41,23 @@
 from txdav.common.datastore.sql_legacy import PostgresLegacyABIndexEmulator
 
 from txdav.carddav.datastore.util import validateAddressBookComponent
-from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook,\
+from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook, \
     IAddressBookObject
 
-from txdav.common.datastore.sql import CommonHome, CommonHomeChild,\
+from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
     CommonObjectResource, EADDRESSBOOKTYPE
 from twext.enterprise.dal.syntax import Delete
 from twext.enterprise.dal.syntax import Insert
 
 from twext.enterprise.dal.syntax import Update
 from twext.enterprise.dal.syntax import utcNowSQL
-from txdav.common.datastore.sql_tables import ADDRESSBOOK_TABLE,\
-    ADDRESSBOOK_BIND_TABLE, ADDRESSBOOK_OBJECT_REVISIONS_TABLE,\
-    ADDRESSBOOK_OBJECT_TABLE, ADDRESSBOOK_HOME_TABLE,\
-    ADDRESSBOOK_HOME_METADATA_TABLE, ADDRESSBOOK_AND_ADDRESSBOOK_BIND,\
+from txdav.common.datastore.sql_tables import ADDRESSBOOK_TABLE, \
+    ADDRESSBOOK_BIND_TABLE, ADDRESSBOOK_OBJECT_REVISIONS_TABLE, \
+    ADDRESSBOOK_OBJECT_TABLE, ADDRESSBOOK_HOME_TABLE, \
+    ADDRESSBOOK_HOME_METADATA_TABLE, ADDRESSBOOK_AND_ADDRESSBOOK_BIND, \
     ADDRESSBOOK_OBJECT_AND_BIND_TABLE, \
-    ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE, schema
+    ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE, \
+    _ABO_KIND_PERSON, _ABO_KIND_GROUP, _ABO_KIND_RESOURCE, _ABO_KIND_LOCATION, schema
 from txdav.base.propertystore.base import PropertyName
 
 
@@ -163,8 +164,8 @@
     def __init__(self, *args, **kw):
         super(AddressBook, self).__init__(*args, **kw)
         self._index = PostgresLegacyABIndexEmulator(self)
-        
 
+
     @property
     def _addressbookHome(self):
         return self._home
@@ -256,7 +257,7 @@
         @type component: L{Component}
         """
 
-        ao = schema.ADDRESSBOOK_OBJECT
+        abo = schema.ADDRESSBOOK_OBJECT
 
         componentText = str(component)
         self._objectText = componentText
@@ -269,26 +270,33 @@
         if self._txn._migrating and hasattr(component, "md5"):
             self._md5 = component.md5
 
+        # map vCard kind to AddressBook object kind; default is _ABO_KIND_PERSON
+        aoKind = {"group": _ABO_KIND_GROUP,
+                  "resource": _ABO_KIND_RESOURCE,
+                  "location": _ABO_KIND_LOCATION, }.get(component.resourceKind(), _ABO_KIND_PERSON)
+
         if inserting:
             self._resourceID, self._created, self._modified = (
                 yield Insert(
-                    {ao.ADDRESSBOOK_RESOURCE_ID: self._addressbook._resourceID,
-                     ao.RESOURCE_NAME: self._name,
-                     ao.VCARD_TEXT: componentText,
-                     ao.VCARD_UID: component.resourceUID(),
-                     ao.MD5: self._md5},
-                    Return=(ao.RESOURCE_ID,
-                            ao.CREATED,
-                            ao.MODIFIED)
+                    {abo.ADDRESSBOOK_RESOURCE_ID: self._addressbook._resourceID,
+                     abo.RESOURCE_NAME: self._name,
+                     abo.VCARD_TEXT: componentText,
+                     abo.VCARD_UID: component.resourceUID(),
+                     abo.KIND: aoKind,
+                     abo.MD5: self._md5},
+                    Return=(abo.RESOURCE_ID,
+                            abo.CREATED,
+                            abo.MODIFIED)
                 ).on(self._txn))[0]
         else:
             self._modified = (yield Update(
-                {ao.VCARD_TEXT: componentText,
-                 ao.VCARD_UID: component.resourceUID(),
-                 ao.MD5: self._md5,
-                 ao.MODIFIED: utcNowSQL},
-                Where=ao.RESOURCE_ID == self._resourceID,
-                Return=ao.MODIFIED).on(self._txn))[0][0]
+                {abo.VCARD_TEXT: componentText,
+                 abo.VCARD_UID: component.resourceUID(),
+                 abo.KIND: aoKind,
+                 abo.MD5: self._md5,
+                 abo.MODIFIED: utcNowSQL},
+                Where=abo.RESOURCE_ID == self._resourceID,
+                Return=abo.MODIFIED).on(self._txn))[0][0]
 
 
     @inlineCallbacks
@@ -315,7 +323,7 @@
 
         if unfixed:
             self.log_error("Address data id=%s had unfixable problems:\n  %s" % (self._resourceID, "\n  ".join(unfixed),))
-        
+
         if fixed:
             self.log_error("Address data id=%s had fixable problems:\n  %s" % (self._resourceID, "\n  ".join(fixed),))
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py	2012-10-06 00:21:26 UTC (rev 9902)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py	2012-10-06 04:05:58 UTC (rev 9903)
@@ -31,7 +31,7 @@
 from twistedcaldav.vcard import Component as VComponent
 
 from txdav.base.propertystore.base import PropertyName
-from txdav.carddav.datastore.test.common import CommonTests as AddressBookCommonTests,\
+from txdav.carddav.datastore.test.common import CommonTests as AddressBookCommonTests, \
     vcard4_text
 from txdav.carddav.datastore.test.test_file import setUpAddressBookStore
 from txdav.carddav.datastore.util import _migrateAddressbook, migrateHome
@@ -39,7 +39,12 @@
 from txdav.common.datastore.sql_tables import schema
 from txdav.common.datastore.test.util import buildStore
 
+def _todo(f, why):
+    f.todo = why
+    return f
 
+testUnimplemented = lambda f: _todo(f, "Test unimplemented")
+
 class AddressBookSQLStorageTests(AddressBookCommonTests, unittest.TestCase):
     """
     AddressBook SQL storage tests.
@@ -206,23 +211,23 @@
         The DATAVERSION column for new calendar homes must match the
         ADDRESSBOOK-DATAVERSION value.
         """
-        
+
         home = yield self.transactionUnderTest().addressbookHomeWithUID("home_version")
         self.assertTrue(home is not None)
         yield self.transactionUnderTest().commit
-        
+
         txn = yield self.transactionUnderTest()
         version = yield txn.calendarserverValue("ADDRESSBOOK-DATAVERSION")[0][0]
         ch = schema.ADDRESSBOOK_HOME
         homeVersion = yield Select(
-            [ch.DATAVERSION,],
+            [ch.DATAVERSION, ],
             From=ch,
             Where=ch.OWNER_UID == "home_version",
         ).on(txn)[0][0]
         self.assertEqual(int(homeVersion, version))
-        
-        
 
+
+
     def test_eachAddressbookHome(self):
         """
         L{IAddressbookStore.eachAddressbookHome} is currently stubbed out by
@@ -301,6 +306,13 @@
         yield d1
         yield d2
 
+    @testUnimplemented
+    def test_addressbookObjectKind(self):
+        """
+        Test that kind property vCard is stored correctly in database
+        """
+        raise NotImplementedError()
+
     @inlineCallbacks
     def test_removeAddressBookPropertiesOnDelete(self):
         """
@@ -314,7 +326,7 @@
         addressbook = yield home.createAddressBookWithName(name)
         resourceID = addressbook._resourceID
         addressbookProperties = addressbook.properties()
-        
+
         prop = carddavxml.AddressBookDescription.fromString("Address Book to be removed")
         addressbookProperties[PropertyName.fromElement(prop)] = prop
         yield self.commit()

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2012-10-06 00:21:26 UTC (rev 9902)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2012-10-06 04:05:58 UTC (rev 9903)
@@ -369,8 +369,7 @@
   MD5                     char(32)     not null,
   CREATED                 timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   MODIFIED                timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
-  -- ### TODO: ADD ROW ###
-  --KIND 			  		  integer      not null, -- enum OBJECT_KIND
+  KIND 			  		  integer      not null, -- enum OBJECT_KIND
 
   unique(ADDRESSBOOK_RESOURCE_ID, RESOURCE_NAME), -- implicit index
   unique(ADDRESSBOOK_RESOURCE_ID, VCARD_UID)      -- implicit index
@@ -380,15 +379,15 @@
 -- AddressBook Object kind --
 -----------------------------
 
-create table OBJECT_KIND (
+create table ADDRESS_BOOK_OBJECT_KIND (
   ID          integer     primary key,
   DESCRIPTION varchar(16) not null unique
 );
 
-insert into OBJECT_KIND values (0, 'person');
-insert into OBJECT_KIND values (1, 'group' );
-insert into OBJECT_KIND values (2, 'resource');
-insert into OBJECT_KIND values (3, 'location');
+insert into ADDRESS_BOOK_OBJECT_KIND values (0, 'person');
+insert into ADDRESS_BOOK_OBJECT_KIND values (1, 'group' );
+insert into ADDRESS_BOOK_OBJECT_KIND values (2, 'resource');
+insert into ADDRESS_BOOK_OBJECT_KIND values (3, 'location');
 
 -------------
 -- Members --

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py	2012-10-06 00:21:26 UTC (rev 9902)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_tables.py	2012-10-06 04:05:58 UTC (rev 9903)
@@ -36,7 +36,7 @@
     """
     Generate the global L{SchemaSyntax}.
     """
-    
+
     if version is None:
         pathObj = getModule(__name__).filePath.sibling("sql_schema").child("current.sql")
     else:
@@ -102,7 +102,7 @@
     result = {}
     for tableRole, tableDictionary in kw.items():
         result.update([("%s:%s" % (tableRole, k), v)
-                       for k,v in tableDictionary.items()])
+                       for k, v in tableDictionary.items()])
     return result
 
 
@@ -147,18 +147,18 @@
     schema.CALENDAR_BIND_STATUS.ID
 )
 
-_BIND_STATUS_INVITED  = _bindStatus('invited')
+_BIND_STATUS_INVITED = _bindStatus('invited')
 _BIND_STATUS_ACCEPTED = _bindStatus('accepted')
 _BIND_STATUS_DECLINED = _bindStatus('declined')
-_BIND_STATUS_INVALID  = _bindStatus('invalid')
+_BIND_STATUS_INVALID = _bindStatus('invalid')
 
 _attachmentsMode = _schemaConstants(
     schema.CALENDAR_OBJECT_ATTACHMENTS_MODE.DESCRIPTION,
     schema.CALENDAR_OBJECT_ATTACHMENTS_MODE.ID
 )
 
-_ATTACHMENTS_MODE_NONE  = _attachmentsMode('none')
-_ATTACHMENTS_MODE_READ  = _attachmentsMode('read')
+_ATTACHMENTS_MODE_NONE = _attachmentsMode('none')
+_ATTACHMENTS_MODE_READ = _attachmentsMode('read')
 _ATTACHMENTS_MODE_WRITE = _attachmentsMode('write')
 
 
@@ -174,21 +174,33 @@
 _BIND_MODE_DIRECT = _bindMode('direct')
 
 
+_addressBookObjectKind = _schemaConstants(
+    schema.ADDRESS_BOOK_OBJECT_KIND.DESCRIPTION,
+    schema.ADDRESS_BOOK_OBJECT_KIND.ID
+)
+
+_ABO_KIND_PERSON = _addressBookObjectKind('person')
+_ABO_KIND_GROUP = _addressBookObjectKind('group')
+_ABO_KIND_RESOURCE = _addressBookObjectKind('resource')
+_ABO_KIND_LOCATION = _addressBookObjectKind('location')
+
+
+
 # Compatibility tables for string formatting:
-CALENDAR_HOME_TABLE                 = _S(schema.CALENDAR_HOME)
-CALENDAR_HOME_METADATA_TABLE        = _S(schema.CALENDAR_HOME_METADATA)
-ADDRESSBOOK_HOME_TABLE              = _S(schema.ADDRESSBOOK_HOME)
-ADDRESSBOOK_HOME_METADATA_TABLE     = _S(schema.ADDRESSBOOK_HOME_METADATA)
-NOTIFICATION_HOME_TABLE             = _S(schema.NOTIFICATION_HOME)
-CALENDAR_TABLE                      = _S(schema.CALENDAR)
-ADDRESSBOOK_TABLE                   = _S(schema.ADDRESSBOOK)
-CALENDAR_BIND_TABLE                 = _S(schema.CALENDAR_BIND)
-ADDRESSBOOK_BIND_TABLE              = _S(schema.ADDRESSBOOK_BIND)
-CALENDAR_OBJECT_REVISIONS_TABLE     = _S(schema.CALENDAR_OBJECT_REVISIONS)
-ADDRESSBOOK_OBJECT_REVISIONS_TABLE  = _S(schema.ADDRESSBOOK_OBJECT_REVISIONS)
+CALENDAR_HOME_TABLE = _S(schema.CALENDAR_HOME)
+CALENDAR_HOME_METADATA_TABLE = _S(schema.CALENDAR_HOME_METADATA)
+ADDRESSBOOK_HOME_TABLE = _S(schema.ADDRESSBOOK_HOME)
+ADDRESSBOOK_HOME_METADATA_TABLE = _S(schema.ADDRESSBOOK_HOME_METADATA)
+NOTIFICATION_HOME_TABLE = _S(schema.NOTIFICATION_HOME)
+CALENDAR_TABLE = _S(schema.CALENDAR)
+ADDRESSBOOK_TABLE = _S(schema.ADDRESSBOOK)
+CALENDAR_BIND_TABLE = _S(schema.CALENDAR_BIND)
+ADDRESSBOOK_BIND_TABLE = _S(schema.ADDRESSBOOK_BIND)
+CALENDAR_OBJECT_REVISIONS_TABLE = _S(schema.CALENDAR_OBJECT_REVISIONS)
+ADDRESSBOOK_OBJECT_REVISIONS_TABLE = _S(schema.ADDRESSBOOK_OBJECT_REVISIONS)
 NOTIFICATION_OBJECT_REVISIONS_TABLE = _S(schema.NOTIFICATION_OBJECT_REVISIONS)
-CALENDAR_OBJECT_TABLE               = _S(schema.CALENDAR_OBJECT)
-ADDRESSBOOK_OBJECT_TABLE            = _S(schema.ADDRESSBOOK_OBJECT)
+CALENDAR_OBJECT_TABLE = _S(schema.CALENDAR_OBJECT)
+ADDRESSBOOK_OBJECT_TABLE = _S(schema.ADDRESSBOOK_OBJECT)
 
 # Some combined tables used in join-string-formatting.
 CALENDAR_AND_CALENDAR_BIND = _combine(CHILD=CALENDAR_TABLE,
@@ -322,12 +334,12 @@
                         elif default is False:
                             default = 0
                         out.write(" " + repr(default))
-            if ( (not column.model.canBeNull())
+            if ((not column.model.canBeNull())
                  # Oracle treats empty strings as NULLs, so we have to accept
                  # NULL values in columns of a string type.  Other types should
                  # be okay though.
                  and typeName not in ('varchar', 'nclob', 'char', 'nchar',
-                                      'nvarchar', 'nvarchar2') ):
+                                      'nvarchar', 'nvarchar2')):
                 out.write(' not null')
             if [column.model] in list(table.model.uniques()):
                 out.write(' unique')
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121005/0008fe8f/attachment-0001.html>


More information about the calendarserver-changes mailing list