[CalendarServer-changes] [12122] twext/trunk/twext/who/opendirectory

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:19:44 PDT 2014


Revision: 12122
          http://trac.calendarserver.org//changeset/12122
Author:   sagen at apple.com
Date:     2013-12-17 14:15:26 -0800 (Tue, 17 Dec 2013)
Log Message:
-----------
Adds support for compound expressions in OD

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

Added Paths:
-----------
    twext/trunk/twext/who/opendirectory/test/test_service.py

Modified: twext/trunk/twext/who/opendirectory/service.py
===================================================================
--- twext/trunk/twext/who/opendirectory/service.py	2013-12-17 19:25:31 UTC (rev 12121)
+++ twext/trunk/twext/who/opendirectory/service.py	2013-12-17 22:15:26 UTC (rev 12122)
@@ -1,4 +1,4 @@
-# -*- test-case-name: twext.who.test.test_util -*-
+# -*- test-case-name: twext.who.opendirectory.test.test_service -*-
 ##
 # Copyright (c) 2013 Apple Inc. All rights reserved.
 #
@@ -328,6 +328,87 @@
             self._node = node
 
 
+    def _queryStringFromExpression(self, expression):
+        """
+        Converts either a MatchExpression or a CompoundExpression into a native
+        OpenDirectory query string.
+
+        @param expression: The expression
+        @type expression: Either L{MatchExpression} or L{CompoundExpression}
+
+        @return: A native OpenDirectory query string
+        @rtype: C{unicode}
+        """
+
+        if isinstance(expression, MatchExpression):
+            matchType = ODMatchType.fromMatchType(expression.matchType)
+            if matchType is None:
+                raise QueryNotSupportedError(
+                    "Unknown match type: {0}".format(matchType)
+                )
+            odAttr = ODAttribute.fromFieldName(expression.fieldName).value
+            queryString = {
+                ODMatchType.equals.value      : u"(%s=%s)",
+                ODMatchType.startsWith.value  : u"(%s=%s*)",
+                ODMatchType.endsWith.value    : u"(%s=*%s)",
+                ODMatchType.contains.value    : u"(%s=*%s*)",
+                ODMatchType.lessThan.value    : u"(%s<%s)",
+                ODMatchType.greaterThan.value : u"(%s>%s)",
+            }.get(matchType.value, u"(%s=*%s*)") % (odAttr, expression.fieldValue,)
+
+        elif isinstance(expression, CompoundExpression):
+            queryString = u""
+            operand = u"&" if expression.operand is Operand.AND else u"|"
+            if len(expression.expressions) > 1:
+                queryString += u"("
+                queryString += operand
+            for subExpression in expression.expressions:
+                queryString += self._queryStringFromExpression(subExpression)
+            if len(expression.expressions) > 1:
+                queryString += u")"
+
+        return queryString
+
+
+    def _queryFromCompoundExpression(self, expression):
+        """
+        Form an OpenDirectory query from a compound expression.
+
+        @param expression: The compound expression.
+        @type expression: L{CompoundExpression}
+
+        @return: A native OpenDirectory query.
+        @rtype: L{ODQuery}
+        """
+
+        queryString = self._queryStringFromExpression(expression)
+
+        recordTypes = [t.value for t in ODRecordType.iterconstants()]
+        attributes = [a.value for a in ODAttribute.iterconstants()]
+        maxResults = 0
+
+        query, error = ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
+            self.node,
+            recordTypes,
+            None,
+            0x210B, # kODMatchCompoundExpression
+            queryString,
+            attributes,
+            maxResults,
+            None
+        )
+
+        if error:
+            self.log.error(
+                "Error while forming OpenDirectory query: {error}",
+                error=error
+            )
+            raise OpenDirectoryQueryError(error)
+
+        return query
+
+
+
     def _queryFromMatchExpression(self, expression):
         """
         Form an OpenDirectory query from a match expression.
@@ -447,6 +528,7 @@
         @return: The records produced by executing the query.
         @rtype: iterable of L{DirectoryRecord}
         """
+
         odRecords, error = query.resultsAllowingPartial_error_(False, None)
 
         if error:
@@ -460,12 +542,11 @@
             yield self._adaptODRecord(odRecord)
 
 
-    def recordsFromMatchExpression(self, expression):
+
+    def recordsFromExpression(self, expression):
         """
-        Find records matching a match expression.
-
         @param expression: an expression to apply
-        @type expression: L{MatchExpression}
+        @type expression: L{MatchExpression} or L{CompoundExpression}
 
         @return: The matching records.
         @rtype: deferred iterable of L{IDirectoryRecord}s
@@ -473,16 +554,15 @@
         @raises: L{QueryNotSupportedError} if the expression is not
             supported by this directory service.
         """
-        query = self._queryFromMatchExpression(expression)
-        return self._recordsFromQuery(query)
 
-
-    def recordsFromExpression(self, expression):
         try:
             if isinstance(expression, CompoundExpression):
-                raise NotImplementedError(Operand)
+                query = self._queryFromCompoundExpression(expression)
+                return self._recordsFromQuery(query)
+
             elif isinstance(expression, MatchExpression):
-                return self.recordsFromMatchExpression(expression)
+                query = self._queryFromMatchExpression(expression)
+                return self._recordsFromQuery(query)
 
         except QueryNotSupportedError:
             pass

Added: twext/trunk/twext/who/opendirectory/test/test_service.py
===================================================================
--- twext/trunk/twext/who/opendirectory/test/test_service.py	                        (rev 0)
+++ twext/trunk/twext/who/opendirectory/test/test_service.py	2013-12-17 22:15:26 UTC (rev 12122)
@@ -0,0 +1,67 @@
+##
+# Copyright (c) 2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+OpenDirectory service tests.
+"""
+
+from twisted.trial import unittest
+from twext.who.opendirectory import DirectoryService
+from twext.who.expression import (
+    CompoundExpression, MatchExpression, MatchType, Operand
+)
+
+
+
+
+
+class OpenDirectoryServiceTestCase(unittest.TestCase):
+    """
+    Tests for L{DirectoryService}.
+    """
+
+    def test_queryFromExpression(self):
+        service = DirectoryService()
+        expression = MatchExpression(
+            service.fieldName.shortNames, u"xyzzy",
+            matchType=MatchType.equals
+        )
+        query = service._queryStringFromExpression(expression)
+        self.assertEquals(query, u"(dsAttrTypeStandard:RecordName=xyzzy)")
+
+        expression = CompoundExpression(
+            [
+                MatchExpression(
+                    service.fieldName.shortNames, u"xyzzy",
+                    matchType=MatchType.contains
+                ),
+                MatchExpression(
+                    service.fieldName.emailAddresses, u"plugh",
+                    matchType=MatchType.startsWith
+                ),
+                MatchExpression(
+                    service.fieldName.fullNames, u"foo",
+                    matchType=MatchType.equals
+                ),
+            ],
+            Operand.AND
+        ) 
+        query = service._queryStringFromExpression(expression)
+        self.assertEquals(query,
+            u"(&(dsAttrTypeStandard:RecordName=*xyzzy*)"
+             "(dsAttrTypeStandard:EMailAddress=plugh*)"
+             "(dsAttrTypeStandard:RealName=foo))"
+        )
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/a257c5c2/attachment.html>


More information about the calendarserver-changes mailing list