[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