[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