[CalendarServer-changes] [13169] twext/trunk/twext/who/opendirectory/_service.py

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 4 15:59:48 PDT 2014


Revision: 13169
          http://trac.calendarserver.org//changeset/13169
Author:   gaya at apple.com
Date:     2014-04-04 15:59:48 -0700 (Fri, 04 Apr 2014)
Log Message:
-----------
in _queryFromCompoundExpression() handle AND recordType match expressions

Modified Paths:
--------------
    twext/trunk/twext/who/opendirectory/_service.py

Modified: twext/trunk/twext/who/opendirectory/_service.py
===================================================================
--- twext/trunk/twext/who/opendirectory/_service.py	2014-04-04 20:43:24 UTC (rev 13168)
+++ twext/trunk/twext/who/opendirectory/_service.py	2014-04-04 22:59:48 UTC (rev 13169)
@@ -210,15 +210,15 @@
             self._node = node
 
 
-    def _queryStringFromMatchExpression(self, expression):
+    def _queryStringAndRecordTypesFromMatchExpression(self, expression):
         """
         Generates an LDAP query string from a match expression.
 
         @param expression: A match expression.
         @type expression: L{MatchExpression}
 
-        @return: An LDAP query string.
-        @rtype: C{unicode}
+        @return: tuple(LDAP query string, recordTypes)
+        @rtype: (C{unicode}, set())
         """
         matchType = ODMatchType.fromMatchType(expression.matchType)
         if matchType is None:
@@ -236,15 +236,13 @@
         # if MatchFlags.caseInsensitive not in flags:
         #     raise NotImplementedError("Need to handle case sensitive")
 
+        if expression.fieldName is self.fieldName.recordType:
+            return (notOp, set([ODRecordType.fromRecordType(expression.fieldValue).value]),)
+
         if expression.fieldName is self.fieldName.uid:
             odAttr = ODAttribute.guid
             value = expression.fieldValue
 
-        elif expression.fieldName is self.fieldName.recordType:
-            raise QueryNotSupportedError(
-                "Can't build a query string for record types."
-            )
-
         else:
             odAttr = ODAttribute.fromFieldName(expression.fieldName)
             if odAttr is None:
@@ -257,43 +255,54 @@
         value = unicode(value)  # We want unicode
         value = value.translate(LDAP_QUOTING_TABLE)  # Escape special chars
 
-        return matchType.queryString.format(
-            notOp=notOp, attribute=odAttr.value, value=value
+        return (
+            matchType.queryString.format(
+                notOp=notOp, attribute=odAttr.value, value=value
+            ),
+            None,
         )
 
 
-    def _queryStringFromCompoundExpression(self, expression):
+    def _queryStringAndRecordTypesFromCompoundExpression(self, expression):
         """
         Generates an LDAP query string from a compound expression.
 
         @param expression: A compound expression.
         @type expression: L{MatchExpression}
 
-        @return: An LDAP query string.
-        @rtype: C{unicode}
+        @return: tuple(LDAP query string, recordTypes)
+        @rtype: (C{unicode}, set())
         """
         queryTokens = []
+        recordTypes = set()
 
-        if len(expression.expressions) > 1:
-            queryTokens.append(u"(")
-
-            if expression.operand is Operand.AND:
-                queryTokens.append(u"&")
+        for subExpression in expression.expressions:
+            queryToken, subExpRecordTypes = self._queryStringAndRecordTypesFromExpression(subExpression)
+            if subExpRecordTypes:
+                if expression.operand is Operand.AND or queryToken == u"!": # AND or NOR
+                    recordTypes |= subExpRecordTypes
+                else:
+                    raise QueryNotSupportedError(
+                        "Record type matches must AND or NOR"
+                    )
             else:
-                queryTokens.append(u"|")
+                queryTokens.append(queryToken)
 
-        for subExpression in expression.expressions:
-            queryTokens.append(
-                self._queryStringFromExpression(subExpression)
-            )
+        if queryTokens:
+            if len(queryTokens) > 1:
+                if expression.operand is Operand.AND:
+                    queryTokens[:0] = (u"&")
+                else:
+                    queryTokens[:0] = (u"|")
 
-        if len(expression.expressions) > 1:
-            queryTokens.append(u")")
+            if len(queryTokens) > 2:
+                queryTokens[:0] = (u"(")
+                queryTokens.append(u")")
 
-        return u"".join(queryTokens)
+        return (u"".join(queryTokens), recordTypes if recordTypes else None,)
 
 
-    def _queryStringFromExpression(self, expression):
+    def _queryStringAndRecordTypesFromExpression(self, expression):
         """
         Converts either a MatchExpression or a CompoundExpression into an LDAP
         query string.
@@ -301,15 +310,15 @@
         @param expression: An expression.
         @type expression: L{MatchExpression} or L{CompoundExpression}
 
-        @return: A native OpenDirectory query string
-        @rtype: C{unicode}
+        @return: tuple(LDAP query string, recordTypes)
+        @rtype: (C{unicode}, set())
         """
 
         if isinstance(expression, MatchExpression):
-            return self._queryStringFromMatchExpression(expression)
+            return self._queryStringAndRecordTypesFromMatchExpression(expression)
 
         if isinstance(expression, CompoundExpression):
-            return self._queryStringFromCompoundExpression(expression)
+            return self._queryStringAndRecordTypesFromCompoundExpression(expression)
 
         raise QueryNotSupportedError(
             "Unknown expression type: {0!r}".format(expression)
@@ -327,9 +336,17 @@
         @rtype: L{ODQuery}
         """
 
-        queryString = self._queryStringFromExpression(expression)
+        queryString, recordTypes = self._queryStringAndRecordTypesFromExpression(expression)
+        supportedRecordTypes = set([t.value for t in ODRecordType.iterconstants()])
+        if recordTypes:
+            recordTypes = supportedRecordTypes & recordTypes
+            if not recordTypes:
+                raise QueryNotSupportedError(
+                    "Query for unsupported record types: {0!r}".format(recordTypes - supportedRecordTypes)
+                )
+        else:
+            recordTypes = supportedRecordTypes
 
-        recordTypes = [t.value for t in ODRecordType.iterconstants()]
         attributes = [a.value for a in ODAttribute.iterconstants()]
         maxResults = 0
 
@@ -337,8 +354,8 @@
             self.node,
             recordTypes,
             None,
-            ODMatchType.compound.value,
-            queryString,
+            ODMatchType.compound.value if queryString else ODMatchType.any.value,
+            queryString if queryString else None,
             attributes,
             maxResults,
             None
@@ -422,7 +439,7 @@
                 expression.fieldName
             ).value
 
-            # TODO: Add support other valuetypes:
+            # TODO: Add support other value types:
             valueType = self.fieldName.valueType(expression.fieldName)
             if valueType == UUID:
                 queryValue = unicode(expression.fieldValue).upper()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140404/2860ae76/attachment.html>


More information about the calendarserver-changes mailing list