[CalendarServer-changes] [13053] CalendarServer/branches/users/sagen/move2who-4
source_changes at macosforge.org
source_changes at macosforge.org
Sun Mar 30 16:06:13 PDT 2014
Revision: 13053
http://trac.calendarserver.org//changeset/13053
Author: gaya at apple.com
Date: 2014-03-30 16:06:13 -0700 (Sun, 30 Mar 2014)
Log Message:
-----------
all CDT tests work but one
Modified Paths:
--------------
CalendarServer/branches/users/sagen/move2who-4/conf/auth/accounts-test.xml
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directorybackedaddressbook.py
CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/method/report_addressbook_query.py
CalendarServer/branches/users/sagen/move2who-4/txdav/carddav/datastore/query/filter.py
CalendarServer/branches/users/sagen/move2who-4/txdav/who/vcard.py
Modified: CalendarServer/branches/users/sagen/move2who-4/conf/auth/accounts-test.xml
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/conf/auth/accounts-test.xml 2014-03-30 15:10:20 UTC (rev 13052)
+++ CalendarServer/branches/users/sagen/move2who-4/conf/auth/accounts-test.xml 2014-03-30 23:06:13 UTC (rev 13053)
@@ -295,6 +295,7 @@
<uid>public01</uid>
<password>public01</password>
<full-name>Public 01</full-name>
+ <email>public01 at example.com</email>
</record>
<record type="user">
@@ -302,6 +303,7 @@
<uid>public02</uid>
<password>public02</password>
<full-name>Public 02</full-name>
+ <email>public02 at example.com</email>
</record>
<record type="user">
@@ -309,6 +311,7 @@
<uid>public03</uid>
<password>public03</password>
<full-name>Public 03</full-name>
+ <email>public03 at example.com</email>
</record>
<record type="user">
@@ -316,6 +319,7 @@
<uid>public04</uid>
<password>public04</password>
<full-name>Public 04</full-name>
+ <email>public04 at example.com</email>
</record>
<record type="user">
@@ -323,6 +327,7 @@
<uid>public05</uid>
<password>public05</password>
<full-name>Public 05</full-name>
+ <email>public05 at example.com</email>
</record>
<record type="user">
@@ -330,6 +335,7 @@
<uid>public06</uid>
<password>public06</password>
<full-name>Public 06</full-name>
+ <email>public06 at example.com</email>
</record>
<record type="user">
@@ -337,6 +343,7 @@
<uid>public07</uid>
<password>public07</password>
<full-name>Public 07</full-name>
+ <email>public07 at example.com</email>
</record>
<record type="user">
@@ -344,6 +351,7 @@
<uid>public08</uid>
<password>public08</password>
<full-name>Public 08</full-name>
+ <email>public08 at example.com</email>
</record>
<record type="user">
@@ -351,6 +359,7 @@
<uid>public09</uid>
<password>public09</password>
<full-name>Public 09</full-name>
+ <email>public09 at example.com</email>
</record>
<record type="user">
@@ -358,6 +367,7 @@
<uid>public10</uid>
<password>public10</password>
<full-name>Public 10</full-name>
+ <email>public10 at example.com</email>
</record>
<record type="group">
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directorybackedaddressbook.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directorybackedaddressbook.py 2014-03-30 15:10:20 UTC (rev 13052)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directorybackedaddressbook.py 2014-03-30 23:06:13 UTC (rev 13053)
@@ -26,7 +26,7 @@
from twext.python.log import Logger
from twext.who.expression import Operand, MatchType, MatchFlags, \
MatchExpression, CompoundExpression
-from twext.who.idirectory import FieldName, RecordType
+from twext.who.idirectory import FieldName
from twisted.internet.defer import deferredGenerator
from twisted.internet.defer import succeed, inlineCallbacks, maybeDeferred, \
returnValue
@@ -37,8 +37,8 @@
from txdav.carddav.datastore.query.filter import IsNotDefined, TextMatch, \
ParameterFilter
from txdav.who.idirectory import FieldName as CalFieldName
-from txdav.who.vcard import recordTypeToVCardKindMap, vCardPropToParamMap, \
- vCardConstantProperties, vCardFromRecord
+from txdav.who.vcard import recordTypeToVCardKindMap, vCardKindToRecordTypeMap, \
+ vCardPropToParamMap, vCardConstantProperties, vCardFromRecord
from txdav.xml import element as davxml
from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, \
twisted_private_namespace
@@ -70,6 +70,8 @@
def makeChild(self, name):
+ from twistedcaldav.simpleresource import SimpleCalDAVResource
+ return SimpleCalDAVResource(principalCollections=self.principalCollections())
return self.directory
@@ -154,7 +156,7 @@
@inlineCallbacks
- def doAddressBookDirectoryQuery(self, addressBookFilter, addressBookQuery, maxResults):
+ def doAddressBookDirectoryQuery(self, addressBookFilter, addressBookQuery, maxResults, defaultKind=None):
"""
Get vCards for a given addressBookFilter and addressBookQuery
"""
@@ -165,46 +167,42 @@
limited = False
maxQueryRecords = 0
- searchableFields = {
- RecordType.user: {
- "FN": FieldName.fullNames,
- "N": FieldName.fullNames,
- "EMAIL": FieldName.emailAddresses,
- "UID": FieldName.uid,
- "ADR": (
- CalFieldName.streetAddress,
- CalFieldName.floor,
- )
- },
- RecordType.group: {
- "FN": FieldName.fullNames,
- "N": FieldName.fullNames,
- "EMAIL": FieldName.emailAddresses,
- "UID": FieldName.uid,
- "ADR": (
- CalFieldName.streetAddress,
- CalFieldName.floor,
- )
- # LATER "X-ADDRESSBOOKSERVER-MEMBER": FieldName.membersUIDs,
- },
+ vcardPropToRecordFieldMap = {
+ "FN": FieldName.fullNames,
+ "N": FieldName.fullNames,
+ "EMAIL": FieldName.emailAddresses,
+ "UID": FieldName.uid,
+ "ADR": (
+ CalFieldName.streetAddress,
+ CalFieldName.floor,
+ ),
+ "KIND": FieldName.recordType,
+ # LATER "X-ADDRESSBOOKSERVER-MEMBER": FieldName.membersUIDs,
}
- allowedRecordTypes = set(self.directory.recordTypes()) & set(recordTypeToVCardKindMap.keys()) & set(searchableFields.keys())
+ allowedRecordTypes = set(self.directory.recordTypes()) & set(recordTypeToVCardKindMap.keys())
log.debug("doAddressBookDirectoryQuery: allowedRecordTypes={allowedRecordTypes}", allowedRecordTypes=allowedRecordTypes,)
+ '''
expressions = []
for recordType in allowedRecordTypes:
#log.debug("doAddressBookDirectoryQuery: recordType={recordType}", recordType=recordType,)
- vcardPropToRecordFieldMap = searchableFields[recordType]
kind = recordTypeToVCardKindMap[recordType]
constantProperties = vCardConstantProperties.copy()
constantProperties["KIND"] = kind
# add KIND as constant so that query can be skipped if addressBookFilter needs a different kind
- propNames, expression = expressionFromABFilter(addressBookFilter, vcardPropToRecordFieldMap, recordType=recordType, constantProperties=constantProperties)
+ propNames, expression = expressionFromABFilter(addressBookFilter, vcardPropToRecordFieldMap, constantProperties=constantProperties)
#log.debug("doAddressBookDirectoryQuery: recordType={recordType}, expression={expression!r}, propNames={propNames}", recordType=recordType, expression=expression, propNames=propNames)
+ if expression:
+ recordTypeExpression = MatchExpression(FieldName.recordType, recordType, MatchType.equals)
+ if expression is True:
+ expression = recordTypeExpression
+ else:
+ expression = CompoundExpression((expression, recordTypeExpression,), Operand.AND)
+
if expression:
expressions.append(expression)
@@ -213,7 +211,35 @@
expression = CompoundExpression(expressions, Operand.OR)
else:
expression = expressions[0]
+ '''
+ propNames, expression = expressionFromABFilter(
+ addressBookFilter, vcardPropToRecordFieldMap, vCardConstantProperties
+ )
+
+ if expression:
+ if defaultKind and "KIND" not in propNames:
+ defaultRecordExpression = MatchExpression(
+ FieldName.recordType,
+ vCardKindToRecordTypeMap[defaultKind],
+ MatchType.equals
+ )
+ if expression is True:
+ expression = defaultRecordExpression
+ else:
+ expression = CompoundExpression(
+ (expression, defaultRecordExpression,),
+ Operand.AND
+ )
+ elif expression is True: # True means all records
+ expression = CompoundExpression(
+ [
+ MatchExpression(FieldName.recordType, recordType, MatchType.equals)
+ for recordType in self.directory.recordTypes()
+ ], Operand.OR
+ )
+
+ log.debug("doAddressBookDirectoryQuery: expression={expression!r}, propNames={propNames}", expression=expression, propNames=propNames)
maxRecords = int(maxResults * 1.2)
# keep trying query till we get results based on filter. Especially when doing "all results" query
@@ -225,7 +251,7 @@
log.debug("doAddressBookDirectoryQuery: #records={n}, records={records!r}", n=len(records), records=records)
queryLimited = False
- vCardsResults = [ABDirectoryQueryResult(self, record) for record in records]
+ vCardsResults = [(yield ABDirectoryQueryResult(self).generate(record)) for record in records]
filteredResults = []
for vCardResult in vCardsResults:
@@ -286,7 +312,7 @@
-def expressionFromABFilter(addressBookFilter, vcardPropToSearchableFieldMap, recordType, constantProperties={}):
+def expressionFromABFilter(addressBookFilter, vcardPropToSearchableFieldMap, constantProperties={}):
"""
Convert the supplied addressbook-query into a ds expression tree.
@@ -347,17 +373,34 @@
@return: (filterProperyNames, expressions) tuple. expression==True means list all results, expression==False means no results
"""
+ def matchExpression(fieldName, matchString, matchType, matchFlags):
+ # special case recordType field
+ if fieldName == FieldName.recordType:
+ # change kind to record type
+ uMatchString = vCardKindToRecordTypeMap.get(matchString)
+ if uMatchString is None:
+ uMatchString = NamedConstant()
+ uMatchString.description = u""
+
+ # change types and flags
+ matchFlags &= ~MatchFlags.caseInsensitive
+ matchType = MatchType.equals
+ else:
+ uMatchString = matchString.decode("utf-8")
+
+ return MatchExpression(fieldName, uMatchString, matchType, matchFlags)
+
+
def definedExpression(defined, allOf):
- if constant or propFilter.filter_name in ("N" , "FN", "UID", "SOURCE",):
+ if constant or propFilter.filter_name in ("N" , "FN", "UID", "SOURCE", "KIND",):
return defined # all records have this property so no records do not have it
else:
- if defined:
- matchList = [MatchExpression(fieldName, u"", MatchType.startsWith) for fieldName in searchableFields]
- else:
- # this may generate inefficient LDAP query stirng
- matchList = [MatchExpression(fieldName, u"", MatchType.startsWith, MatchFlags.NOT) for fieldName in searchableFields]
+ # this may generate inefficient LDAP query string
+ matchFlags = MatchFlags.NOT & MatchFlags.caseInsensitive if defined else MatchFlags.NOT
+ matchList = [matchExpression(fieldName, "", MatchType.startsWith, matchFlags) for fieldName in searchableFields]
return andOrExpression(allOf, matchList)
+
def andOrExpression(propFilterAllOf, matchList):
matchList = list(set(matchList))
if propFilterAllOf and len(matchList) > 1:
@@ -448,10 +491,17 @@
matchList = []
for matchString in matchStrings:
- if textMatchElement.negate:
- matchList = [MatchExpression(fieldName, matchString.decode("utf-8"), matchType, MatchFlags.NOT) for fieldName in searchableFields]
+ matchFlags = None
+ if textMatchElement.collation == "i;unicode-casemap" and textMatchElement.negate:
+ matchFlags = MatchFlags.caseInsensitive | MatchFlags.NOT
+ elif textMatchElement.collation == "i;unicode-casemap":
+ matchFlags = MatchFlags.caseInsensitive
+ elif textMatchElement.negate:
+ matchFlags = MatchFlags.NOT
else:
- matchList = [MatchExpression(fieldName, matchString.decode("utf-8"), matchType) for fieldName in searchableFields]
+ matchFlags = MatchFlags.NOT & MatchFlags.caseInsensitive # MatchFlags.none
+
+ matchList = [matchExpression(fieldName, matchString.decode("utf-8"), matchType, matchFlags) for fieldName in searchableFields]
matchList.extend(matchList)
return andOrExpression(propFilterAllOf, matchList)
@@ -541,14 +591,6 @@
else:
expression = not filterAllOf
- #log.debug("expressionFromABFilter: recordType={rdn!r}, expression={q!r}, properties={pn}", rdn=recordType, q=expression, pn=properties)
- if expression:
- recordTypeExpression = MatchExpression(FieldName.recordType, recordType, MatchType.equals)
- if expression is True:
- expression = recordTypeExpression
- else:
- expression = CompoundExpression((expression, recordTypeExpression,), Operand.AND)
-
#log.debug("expressionFromABFilter: expression={q!r}, properties={pn}", q=expression, pn=properties)
return((properties, expression))
@@ -559,14 +601,10 @@
Result from ab query report or multiget on directory
"""
- def __init__(self, directoryBackedAddressBook, record,
- kind=None,
- addProps=None,
- ):
+ def __init__(self, directoryBackedAddressBook,):
self._directoryBackedAddressBook = directoryBackedAddressBook
- #generate a vCard here. May throw an exception
- self._vCard = vCardFromRecord(record, kind, addProps, directoryBackedAddressBook.uri)
+ #self._vCard = None
def __repr__(self):
@@ -585,12 +623,18 @@
return hash(s)
'''
+ @inlineCallbacks
+ def generate(self, record, kind=None, addProps=None,):
+ self._vCard = yield vCardFromRecord(record, kind, addProps, None)
+ returnValue(self)
+
+
def vCard(self):
return self._vCard
def vCardText(self):
- return str(self.vCard())
+ return str(self._vCard)
def uri(self):
Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/method/report_addressbook_query.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/method/report_addressbook_query.py 2014-03-30 15:10:20 UTC (rev 13052)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/method/report_addressbook_query.py 2014-03-30 23:06:13 UTC (rev 13053)
@@ -157,7 +157,7 @@
def queryDirectoryBackedAddressBook(directoryBackedAddressBook, addressBookFilter):
"""
"""
- results, limited[0] = (yield directoryBackedAddressBook.doAddressBookDirectoryQuery(addressBookFilter, query, max_number_of_results[0]))
+ results, limited[0] = yield directoryBackedAddressBook.doAddressBookDirectoryQuery(addressBookFilter, query, max_number_of_results[0], defaultKind="individual")
for vCardResult in results:
# match against original filter if different from addressBookFilter
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/carddav/datastore/query/filter.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/carddav/datastore/query/filter.py 2014-03-30 15:10:20 UTC (rev 13052)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/carddav/datastore/query/filter.py 2014-03-30 23:06:13 UTC (rev 13053)
@@ -136,7 +136,7 @@
return not allof
return allof
else:
- return True
+ return False
def valid(self):
@@ -190,9 +190,6 @@
else:
raise ValueError("Unknown child element: %s" % (qname,))
- if qualifier and isinstance(qualifier, IsNotDefined) and (len(filters) != 0):
- raise ValueError("No other tests allowed when CardDAV:is-not-defined is present")
-
if xml_element.qname() == (carddav_namespace, "prop-filter"):
propfilter_test = xml_element.attributes.get("test", "anyof")
if propfilter_test not in ("anyof", "allof"):
@@ -200,13 +197,16 @@
else:
propfilter_test = "anyof"
+ if qualifier and isinstance(qualifier, IsNotDefined) and (len(filters) != 0) and propfilter_test == "allof":
+ raise ValueError("When test is allof, no other tests allowed when CardDAV:is-not-defined is present")
+
self.propfilter_test = propfilter_test
self.qualifier = qualifier
self.filters = filters
self.filter_name = xml_element.attributes["name"]
if isinstance(self.filter_name, unicode):
self.filter_name = self.filter_name.encode("utf-8")
- self.defined = not self.qualifier or not isinstance(qualifier, IsNotDefined)
+ self.defined = not self.qualifier or not isinstance(qualifier, IsNotDefined) or len(filters)
def _deserialize(self, data):
@@ -241,25 +241,18 @@
matches this filter, False otherwise.
"""
- # Always return True for the is-not-defined case as the result of this will
- # be negated by the caller
- if not self.defined:
- return True
+ allof = self.propfilter_test == "allof"
+ if self.qualifier and allof != self.qualifier.match(item):
+ return not allof
- if self.qualifier and not self.qualifier.match(item):
- return False
-
if len(self.filters) > 0:
- allof = self.propfilter_test == "allof"
for filter in self.filters:
if allof != filter._match(item):
return not allof
return allof
else:
- return True
+ return not allof
-
-
class PropertyFilter (FilterChildBase):
"""
Limits a search to specific properties.
Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/vcard.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/vcard.py 2014-03-30 15:10:20 UTC (rev 13052)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/vcard.py 2014-03-30 23:06:13 UTC (rev 13053)
@@ -26,6 +26,7 @@
from pycalendar.vcard.n import N
from twext.python.log import Logger
from twext.who.idirectory import FieldName, RecordType
+from twisted.internet.defer import inlineCallbacks, returnValue
from twistedcaldav.config import config
from twistedcaldav.vcard import Component, Property, vCardProductID
from txdav.who.idirectory import FieldName as CalFieldName, \
@@ -42,7 +43,15 @@
CalRecordType.resource: "device",
}
+vCardKindToRecordTypeMap = {
+ "individual" : RecordType.user,
+ "group": RecordType.group,
+ "org": RecordType.group,
+ "location": CalRecordType.location,
+ "device": CalRecordType.resource,
+}
+
# all possible generated parameters.
vCardPropToParamMap = {
#"PHOTO": {"ENCODING": ("B",), "TYPE": ("JPEG",), },
@@ -72,6 +81,7 @@
}
+ at inlineCallbacks
def vCardFromRecord(record, kind=None, addProps=None, parentURI=None):
def isUniqueProperty(newProperty, ignoredParameters={}):
@@ -296,13 +306,9 @@
vcard.addProperty(Property("X-ADDRESSBOOKSERVER-KIND", kind))
# add members
- # FIXME: members() is a deferred. I really want non-deferred FieldName.memberUIDs
- if record.members():
- pass
- '''
- for memberRecord in (yield record.members()):
- vcard.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:" + memberRecord.fields[FieldName.uid].encode("utf-8")))
- '''
+ # FIXME: members() is a deferred, so all of vCardFromRecord is deferred.
+ for memberRecord in (yield record.members()):
+ vcard.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:" + memberRecord.fields[FieldName.uid].encode("utf-8")))
#===================================================================
# vCard 4.0 http://tools.ietf.org/html/rfc6350
@@ -321,4 +327,4 @@
vcard.addProperty(Property("X-ABShowAs", "COMPANY"))
log.debug("vCardFromRecord: vcard=\n{vcard}", vcard=vcard)
- return vcard
+ returnValue(vcard)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140330/214d80f8/attachment-0001.html>
More information about the calendarserver-changes
mailing list