[CalendarServer-changes] [9906] CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/ datastore

source_changes at macosforge.org source_changes at macosforge.org
Mon Oct 8 15:52:43 PDT 2012


Revision: 9906
          http://trac.calendarserver.org//changeset/9906
Author:   gaya at apple.com
Date:     2012-10-08 15:52:43 -0700 (Mon, 08 Oct 2012)
Log Message:
-----------
implement test_addressbookObjectKind

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-08 21:17:08 UTC (rev 9905)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2012-10-08 22:52:43 UTC (rev 9906)
@@ -26,31 +26,25 @@
     "AddressBookObject",
 ]
 
-from zope.interface.declarations import implements
+from twext.enterprise.dal.syntax import \
+    Delete, Insert, Len, Update, utcNowSQL
 
+from twext.python.clsprop import classproperty
+from twext.web2.http_headers import MimeType
+
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python import hashlib
-
-from txdav.xml.rfc2518 import ResourceType
-from twext.web2.http_headers import MimeType
-
 from twistedcaldav import carddavxml, customxml
 from twistedcaldav.memcacher import Memcacher
 from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError
 
-from txdav.common.datastore.sql_legacy import PostgresLegacyABIndexEmulator
-
+from txdav.base.propertystore.base import PropertyName
 from txdav.carddav.datastore.util import validateAddressBookComponent
 from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook, \
     IAddressBookObject
-
 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_legacy import PostgresLegacyABIndexEmulator
 from txdav.common.datastore.sql_tables import ADDRESSBOOK_TABLE, \
     ADDRESSBOOK_BIND_TABLE, ADDRESSBOOK_OBJECT_REVISIONS_TABLE, \
     ADDRESSBOOK_OBJECT_TABLE, ADDRESSBOOK_HOME_TABLE, \
@@ -58,10 +52,12 @@
     ADDRESSBOOK_OBJECT_AND_BIND_TABLE, \
     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
+from txdav.xml.rfc2518 import ResourceType
 
+from zope.interface.declarations import implements
 
 
+
 class AddressBookHome(CommonHome):
 
     implements(IAddressBookHome)
@@ -212,6 +208,8 @@
         return super(AddressBook, self).unshare(EADDRESSBOOKTYPE)
 
 
+
+
 class AddressBookObject(CommonObjectResource):
 
     implements(IAddressBookObject)
@@ -221,6 +219,7 @@
 
     def __init__(self, addressbook, name, uid, resourceID=None, metadata=None):
 
+        self._kind = None
         super(AddressBookObject, self).__init__(addressbook, name, uid, resourceID)
 
 
@@ -232,7 +231,42 @@
     def addressbook(self):
         return self._addressbook
 
+    def kind(self):
+        return self._kind
 
+    @classproperty
+    def _allColumns(cls): #@NoSelf
+        """
+        Full set of columns in the object table that need to be loaded to
+        initialize the object resource state.
+        """
+        obj = cls._objectSchema
+        return [
+            obj.RESOURCE_ID,
+            obj.RESOURCE_NAME,
+            obj.UID,
+            obj.KIND,
+            obj.MD5,
+            Len(obj.TEXT),
+            obj.CREATED,
+            obj.MODIFIED
+        ]
+
+
+    def _initFromRow(self, row):
+        """
+        Given a select result using the columns from L{_allColumns}, initialize
+        the object resource state.
+        """
+        (self._resourceID,
+         self._name,
+         self._uid,
+         self._kind,
+         self._md5,
+         self._size,
+         self._created,
+         self._modified,) = tuple(row)
+
     @inlineCallbacks
     def setComponent(self, component, inserting=False):
 
@@ -270,10 +304,14 @@
         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)
+        componentResourceKindToAddressBookObjectKindMap = {
+            None: _ABO_KIND_PERSON,
+            "person": _ABO_KIND_PERSON,
+            "group": _ABO_KIND_GROUP,
+            "resource": _ABO_KIND_RESOURCE,
+            "location": _ABO_KIND_LOCATION,
+        }
+        self._kind = componentResourceKindToAddressBookObjectKindMap[component.resourceKind()]
 
         if inserting:
             self._resourceID, self._created, self._modified = (
@@ -282,7 +320,7 @@
                      abo.RESOURCE_NAME: self._name,
                      abo.VCARD_TEXT: componentText,
                      abo.VCARD_UID: component.resourceUID(),
-                     abo.KIND: aoKind,
+                     abo.KIND: self._kind,
                      abo.MD5: self._md5},
                     Return=(abo.RESOURCE_ID,
                             abo.CREATED,
@@ -292,7 +330,7 @@
             self._modified = (yield Update(
                 {abo.VCARD_TEXT: componentText,
                  abo.VCARD_UID: component.resourceUID(),
-                 abo.KIND: aoKind,
+                 abo.KIND: self._kind,
                  abo.MD5: self._md5,
                  abo.MODIFIED: utcNowSQL},
                 Where=abo.RESOURCE_ID == self._resourceID,

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-08 21:17:08 UTC (rev 9905)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/test/test_sql.py	2012-10-08 22:52:43 UTC (rev 9906)
@@ -20,31 +20,28 @@
 """
 
 from twext.enterprise.dal.syntax import Select, Parameter
-from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
 
 from twisted.internet.defer import inlineCallbacks, returnValue
+
 from twisted.trial import unittest
 
 from twistedcaldav import carddavxml
-
 from twistedcaldav.vcard import Component as VCard
 from twistedcaldav.vcard import Component as VComponent
 
 from txdav.base.propertystore.base import PropertyName
+from txdav.carddav.datastore.sql import AddressBookObject
 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
 from txdav.common.datastore.sql import EADDRESSBOOKTYPE
-from txdav.common.datastore.sql_tables import schema
+from txdav.common.datastore.sql_tables import  \
+    _ABO_KIND_PERSON, _ABO_KIND_GROUP, schema
 from txdav.common.datastore.test.util import buildStore
+from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
 
-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.
@@ -306,13 +303,77 @@
         yield d1
         yield d2
 
-    @testUnimplemented
+    @inlineCallbacks
     def test_addressbookObjectKind(self):
         """
         Test that kind property vCard is stored correctly in database
         """
-        raise NotImplementedError()
+        """
+        Test that two concurrent attempts to PUT different address book object resources to the
+        same address book home does not cause a deadlock.
+        """
+        addressbookStore = yield buildStore(self, self.notifierFactory)
 
+        # Provision the home and addressbook, one user and one group
+        txn = addressbookStore.newTransaction()
+        home = yield txn.homeWithUID(EADDRESSBOOKTYPE, "uid1", create=True)
+        self.assertNotEqual(home, None)
+        adbk = yield home.addressbookWithName("addressbook")
+        self.assertNotEqual(adbk, None)
+
+        person = VCard.fromString(
+            """BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:uid1
+END:VCARD
+""".replace("\n", "\r\n")
+            )
+        self.assertEqual(person.resourceKind(), None)
+        abObject = yield adbk.createObjectResourceWithName("p.vcf", person)
+        self.assertEqual(abObject.kind(), _ABO_KIND_PERSON)
+
+        group = VCard.fromString(
+            """BEGIN:VCARD
+VERSION:3.0
+PRODID:-//Apple Inc.//AddressBook 6.1//EN
+UID:uid2
+FN:Top Group
+N:Top Group;;;;
+REV:20120503T194243Z
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:uid1
+END:VCARD
+""".replace("\n", "\r\n")
+            )
+        abObject = self.assertEqual(group.resourceKind(), "group")
+        abObject = yield adbk.createObjectResourceWithName("g.vcf", group)
+        self.assertEqual(abObject.kind(), _ABO_KIND_GROUP)
+        yield txn.commit()
+
+        txn = addressbookStore.newTransaction()
+        home = yield txn.homeWithUID(EADDRESSBOOKTYPE, "uid1", create=True)
+        adbk = yield home.addressbookWithName("addressbook")
+
+        abObject = yield AddressBookObject.objectWithName(adbk, "p.vcf", "uid1")
+        person = yield abObject.component()
+        self.assertEqual(person.resourceKind(), None)
+        self.assertEqual(abObject.kind(), _ABO_KIND_PERSON)
+
+        abObject = yield AddressBookObject.objectWithName(adbk, "g.vcf", "uid1")
+        group = yield abObject.component()
+        self.assertEqual(group.resourceKind(), "group")
+        self.assertEqual(abObject.kind(), _ABO_KIND_GROUP)
+        yield txn.commit()
+
+
+
     @inlineCallbacks
     def test_removeAddressBookPropertiesOnDelete(self):
         """
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121008/bface441/attachment-0001.html>


More information about the calendarserver-changes mailing list