[CalendarServer-changes] [12331] twext/trunk/twext/who
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:24:15 PDT 2014
Revision: 12331
http://trac.calendarserver.org//changeset/12331
Author: wsanchez at apple.com
Date: 2014-01-13 16:38:59 -0800 (Mon, 13 Jan 2014)
Log Message:
-----------
Start work on basic queries.
Modified Paths:
--------------
twext/trunk/twext/who/idirectory.py
twext/trunk/twext/who/ldap/_constants.py
twext/trunk/twext/who/ldap/_service.py
twext/trunk/twext/who/ldap/_util.py
twext/trunk/twext/who/ldap/test/test_service.py
twext/trunk/twext/who/ldap/test/test_util.py
twext/trunk/twext/who/test/test_directory.py
Modified: twext/trunk/twext/who/idirectory.py
===================================================================
--- twext/trunk/twext/who/idirectory.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/idirectory.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -220,7 +220,7 @@
@staticmethod
def valueType(name):
"""
- Check for the expected type of values for a field.
+ Look up the expected type for values of a field.
@param name: The name of the field.
@type name: L{NamedConstant}
Modified: twext/trunk/twext/who/ldap/_constants.py
===================================================================
--- twext/trunk/twext/who/ldap/_constants.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/ldap/_constants.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -22,6 +22,9 @@
Names, NamedConstant, Values, ValueConstant
)
+from ..idirectory import (
+ FieldName as BaseFieldName, RecordType as BaseRecordType
+)
from ..expression import MatchType
@@ -153,7 +156,7 @@
teletexTerminalIdentifier = ValueConstant(u"teletexTerminalIdentifier")
telexNumber = ValueConstant(u"telexNumber")
title = ValueConstant(u"title")
- userid = ValueConstant(u"uid")
+ userID = ValueConstant(u"uid")
uniqueMember = ValueConstant(u"uniqueMember")
userPassword = ValueConstant(u"userPassword")
x121Address = ValueConstant(u"x121Address")
@@ -190,3 +193,23 @@
# http://tools.ietf.org/html/rfc2307
# http://tools.ietf.org/html/rfc2798
# http://tools.ietf.org/html/rfc2739 calendar
+
+
+
+# Maps field name -> LDAP attribute name
+DEFAULT_FIELDNAME_MAP = {
+ BaseFieldName.uid: u"uid", # FIXME
+ BaseFieldName.guid: u"entryUUID", # FIXME
+ BaseFieldName.recordType: u"objectClass",
+ BaseFieldName.shortNames: RFC4519Attribute.userID.value,
+ BaseFieldName.fullNames: RFC4519Attribute.commonName.value,
+ BaseFieldName.emailAddresses: u"mail", # FIXME
+ BaseFieldName.password: u"userPassword", # FIXME
+}
+
+
+# Maps record type -> LDAP organizational unit name
+DEFAULT_RECORDTYPE_MAP = {
+ BaseRecordType.user: u"People", # FIXME
+ BaseRecordType.group: u"Group", # FIXME
+}
Modified: twext/trunk/twext/who/ldap/_service.py
===================================================================
--- twext/trunk/twext/who/ldap/_service.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/ldap/_service.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -34,7 +34,8 @@
from ..idirectory import (
DirectoryServiceError, DirectoryAvailabilityError,
- # InvalidDirectoryRecordError, QueryNotSupportedError,
+ # InvalidDirectoryRecordError,
+ # QueryNotSupportedError,
# FieldName as BaseFieldName,
RecordType as BaseRecordType,
# IPlaintextPasswordVerifier, IHTTPDigestVerifier,
@@ -43,17 +44,21 @@
DirectoryService as BaseDirectoryService,
DirectoryRecord as BaseDirectoryRecord,
)
-# from ..expression import (
-# CompoundExpression, Operand,
-# MatchExpression, MatchFlags,
-# )
+from ..expression import (
+ # CompoundExpression, Operand,
+ MatchExpression, # MatchFlags,
+)
from ..util import (
# iterFlags,
ConstantsContainer,
)
-# from ._constants import LDAP_QUOTING_TABLE
+from ._constants import DEFAULT_FIELDNAME_MAP, DEFAULT_RECORDTYPE_MAP
+from ._util import (
+ ldapQueryStringFromMatchExpression,
+ ldapQueryStringFromCompoundExpression,
+ # ldapQueryStringFromExpression,
+)
-DEFAULT_URL = "ldap://localhost/"
#
@@ -121,16 +126,20 @@
def __init__(
self,
- url=DEFAULT_URL,
+ url,
+ baseDN,
credentials=None,
timeout=None,
tlsCACertificateFile=None,
tlsCACertificateDirectory=None,
useTLS=False,
debug=False,
+ fieldNameMap=DEFAULT_FIELDNAME_MAP,
+ recordTypeMap=DEFAULT_RECORDTYPE_MAP,
):
self.url = url
- self.credentials = credentials
+ self._baseDN = baseDN
+ self._credentials = credentials
self._timeout = timeout
if tlsCACertificateFile is None:
@@ -150,7 +159,10 @@
else:
self._debug = None
+ self._fieldNameMap = fieldNameMap
+ self._recordTypeMap = recordTypeMap
+
@property
def realmName(self):
return u"{self.url}".format(self=self)
@@ -186,33 +198,33 @@
self.log.info("Starting TLS for {source.url}")
yield deferToThread(connection.start_tls_s)
- if self.credentials is not None:
- if IUsernamePassword.providedBy(self.credentials):
+ if self._credentials is not None:
+ if IUsernamePassword.providedBy(self._credentials):
try:
yield deferToThread(
connection.simple_bind_s,
- self.credentials.username,
- self.credentials.password,
+ self._credentials.username,
+ self._credentials.password,
)
self.log.info(
"Bound to LDAP as {credentials.username}",
- credentials=self.credentials
+ credentials=self._credentials
)
except (
ldap.INVALID_CREDENTIALS, ldap.INVALID_DN_SYNTAX
) as e:
self.log.error(
"Unable to bind to LDAP as {credentials.username}",
- credentials=self.credentials
+ credentials=self._credentials
)
raise LDAPBindAuthError(
- self.credentials.username, e
+ self._credentials.username, e
)
else:
raise LDAPConnectionError(
"Unknown credentials type: {0}"
- .format(self.credentials)
+ .format(self._credentials)
)
self._connection = connection
@@ -220,7 +232,51 @@
returnValue(self._connection)
+ @inlineCallbacks
+ def _recordsFromQueryString(self, queryString):
+ connection = yield self._connect()
+ # print("+" * 80)
+ # print("Query:", repr(queryString))
+
+ reply = connection.search_s(
+ self._baseDN, ldap.SCOPE_SUBTREE, queryString # attrs
+ )
+
+ # print("Reply:", repr(reply))
+ # print("+" * 80)
+
+ records = []
+
+ for recordData in reply:
+ raise NotImplementedError(reply)
+
+ returnValue(records)
+
+
+ def recordsFromNonCompoundExpression(self, expression, records=None):
+ if isinstance(expression, MatchExpression):
+ queryString = ldapQueryStringFromMatchExpression(
+ expression, self._fieldNameMap, self._recordTypeMap
+ )
+ return self._recordsFromQueryString(queryString)
+
+ return BaseDirectoryService.recordsFromNonCompoundExpression(
+ self, expression, records=records
+ )
+
+
+ def recordsFromCompoundExpression(self, expression, records=None):
+ if not expression.expressions:
+ return ()
+
+ queryString = ldapQueryStringFromCompoundExpression(
+ expression, self._fieldNameMap, self._recordTypeMap
+ )
+ return self._recordsFromQueryString(queryString)
+
+
+
class DirectoryRecord(BaseDirectoryRecord):
"""
LDAP directory record.
Modified: twext/trunk/twext/who/ldap/_util.py
===================================================================
--- twext/trunk/twext/who/ldap/_util.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/ldap/_util.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -15,7 +15,7 @@
# limitations under the License.
##
-from ..idirectory import QueryNotSupportedError
+from ..idirectory import QueryNotSupportedError, FieldName
from ..expression import (
CompoundExpression, Operand,
MatchExpression, MatchFlags,
@@ -25,23 +25,29 @@
-def ldapQueryStringFromMatchExpression(expression, attrMap):
+def ldapQueryStringFromMatchExpression(
+ expression, fieldNameMap, recordTypeMap
+):
"""
Generates an LDAP query string from a match expression.
@param expression: A match expression.
@type expression: L{MatchExpression}
- @param attrMap: A mapping from L{FieldName}s to native LDAP attribute
+ @param fieldNameMap: A mapping from L{FieldName}s to native LDAP attribute
names.
- @type attrMap: L{dict}
+ @type fieldNameMap: L{dict}
+ @param recordTypeMap: A mapping from L{RecordType}s to native LDAP object
+ class names.
+ @type recordTypeMap: L{dict}
+
@return: An LDAP query string.
@rtype: C{unicode}
@raises QueryNotSupportedError: If the expression's match type is unknown,
or if the expresion references an unknown field name (meaning a field
- name not in C{attrMap}).
+ name not in C{fieldNameMap}).
"""
matchType = LDAPMatchType.fromMatchType(expression.matchType)
if matchType is None:
@@ -63,14 +69,24 @@
# if MatchFlags.caseInsensitive not in flags:
# raise NotImplementedError("Need to handle case sensitive")
+ fieldName = expression.fieldName
try:
- attribute = attrMap[expression.fieldName]
+ attribute = fieldNameMap[fieldName]
except KeyError:
raise QueryNotSupportedError(
- "Unknown field name: {0}".format(expression.fieldName)
+ "Unmapped field name: {0}".format(expression.fieldName)
)
- value = unicode(expression.fieldValue) # We want unicode
+ if fieldName is FieldName.recordType:
+ try:
+ value = recordTypeMap[expression.fieldValue]
+ except KeyError:
+ raise QueryNotSupportedError(
+ "Unmapped record type: {0}".format(expression.fieldValue)
+ )
+ else:
+ value = unicode(expression.fieldValue)
+
value = value.translate(LDAP_QUOTING_TABLE) # Escape special chars
return matchType.queryString.format(
@@ -78,16 +94,18 @@
)
-def ldapQueryStringFromCompoundExpression(expression, attrMap):
+def ldapQueryStringFromCompoundExpression(
+ expression, fieldNameMap, recordTypeMap
+):
"""
Generates an LDAP query string from a compound expression.
@param expression: A compound expression.
@type expression: L{MatchExpression}
- @param attrMap: A mapping from L{FieldName}s to native LDAP attribute
+ @param fieldNameMap: A mapping from L{FieldName}s to native LDAP attribute
names.
- @type attrMap: L{dict}
+ @type fieldNameMap: L{dict}
@return: An LDAP query string.
@rtype: C{unicode}
@@ -107,7 +125,9 @@
for subExpression in expression.expressions:
queryTokens.append(
- ldapQueryStringFromExpression(subExpression, attrMap)
+ ldapQueryStringFromExpression(
+ subExpression, fieldNameMap, recordTypeMap
+ )
)
if len(expression.expressions) > 1:
@@ -116,13 +136,15 @@
return u"".join(queryTokens)
-def ldapQueryStringFromExpression(expression, attrMap):
+def ldapQueryStringFromExpression(
+ expression, fieldNameMap, recordTypeMap
+):
"""
Converts an expression into an LDAP query string.
- @param attrMap: A mapping from L{FieldName}s to native LDAP attribute
+ @param fieldNameMap: A mapping from L{FieldName}s to native LDAP attribute
names.
- @type attrMap: L{dict}
+ @type fieldNameMap: L{dict}
@param expression: An expression.
@type expression: L{MatchExpression} or L{CompoundExpression}
@@ -135,10 +157,14 @@
"""
if isinstance(expression, MatchExpression):
- return ldapQueryStringFromMatchExpression(expression, attrMap)
+ return ldapQueryStringFromMatchExpression(
+ expression, fieldNameMap, recordTypeMap
+ )
if isinstance(expression, CompoundExpression):
- return ldapQueryStringFromCompoundExpression(expression, attrMap)
+ return ldapQueryStringFromCompoundExpression(
+ expression, fieldNameMap, recordTypeMap
+ )
raise QueryNotSupportedError(
"Unknown expression type: {0!r}".format(expression)
Modified: twext/trunk/twext/who/ldap/test/test_service.py
===================================================================
--- twext/trunk/twext/who/ldap/test/test_service.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/ldap/test/test_service.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -29,17 +29,22 @@
from twisted.cred.credentials import UsernamePassword
from twisted.trial import unittest
+from ...idirectory import FieldName as BaseFieldName
# from ...expression import (
# CompoundExpression, Operand, MatchExpression, MatchType, MatchFlags
# )
from .._service import (
- DEFAULT_URL,
+ DEFAULT_FIELDNAME_MAP, DEFAULT_RECORDTYPE_MAP,
LDAPBindAuthError,
DirectoryService, DirectoryRecord,
)
from ...test import test_directory
-from ...test.test_xml import xmlService
+from ...test.test_xml import (
+ xmlService,
+ DirectoryServiceConvenienceTestMixIn
+ as BaseDirectoryServiceConvenienceTestMixIn,
+)
class BaseTestCase(object):
@@ -47,12 +52,23 @@
Tests for L{DirectoryService}.
"""
- url = DEFAULT_URL
- realmName = unicode(DEFAULT_URL)
+ url = "ldap://localhost/"
+ baseDN = u"o=org"
+ realmName = unicode(url)
def setUp(self):
- self.mockLDAP = MockLdap(mockDirectoryDataFromXML(self.mktemp()))
+ self.xmlSeedService = xmlService(self.mktemp())
+ self.mockData = mockDirectoryDataFromXMLService(self.xmlSeedService)
+
+ if False:
+ from pprint import pprint
+ print("")
+ print("-" * 80)
+ pprint(self.mockData)
+ print("-" * 80)
+
+ self.mockLDAP = MockLdap(self.mockData)
self.mockLDAP.start()
@@ -61,25 +77,50 @@
def service(self, **kwargs):
- return DirectoryService(**kwargs)
+ return DirectoryService(url=self.url, baseDN=self.baseDN, **kwargs)
-class DirectoryServiceConvenienceTestMixIn(object):
+class DirectoryServiceConvenienceTestMixIn(
+ BaseDirectoryServiceConvenienceTestMixIn
+):
def _unimplemented(self):
raise NotImplementedError()
_unimplemented.todo = "unimplemented"
- test_recordWithUID = _unimplemented
- test_recordWithGUID = _unimplemented
- test_recordsWithRecordType = _unimplemented
- test_recordWithShortName = _unimplemented
- test_recordsWithEmailAddress = _unimplemented
+ def test_recordWithUID(self):
+ return BaseDirectoryServiceConvenienceTestMixIn.test_recordWithUID(self)
+ test_recordWithUID.todo = "needs a seed"
+ def test_recordWithGUID(self):
+ return BaseDirectoryServiceConvenienceTestMixIn.test_recordWithGUID(self)
+
+ test_recordWithGUID.todo = "needs a seed"
+
+
+ def test_recordsWithRecordType(self):
+ return BaseDirectoryServiceConvenienceTestMixIn.test_recordsWithRecordType(self)
+
+ test_recordsWithRecordType.todo = "needs a seed"
+
+
+ def test_recordWithShortName(self):
+ return BaseDirectoryServiceConvenienceTestMixIn.test_recordWithShortName(self)
+
+ test_recordWithShortName.todo = "needs a seed"
+
+
+ def test_recordsWithEmailAddress(self):
+ return BaseDirectoryServiceConvenienceTestMixIn.test_recordsWithEmailAddress(self)
+
+ test_recordsWithEmailAddress.todo = "needs a seed"
+
+
+
class DirectoryServiceConnectionTestMixIn(object):
@inlineCallbacks
def test_connect_defaults(self):
@@ -195,9 +236,7 @@
-def mockDirectoryDataFromXML(tmp):
- service = xmlService(tmp)
-
+def mockDirectoryDataFromXMLService(service):
o = u"org"
ou = u"calendarserver"
@@ -206,17 +245,6 @@
u"ou={ou}".format(ou=ou): dict(ou=ou),
}
- def toAttribute(fieldName):
- return unicode({
- service.fieldName.uid: u"recordid",
- service.fieldName.guid: u"guid",
- service.fieldName.recordType: u"objectclass",
- service.fieldName.shortNames: u"uid",
- service.fieldName.fullNames: u"cn",
- service.fieldName.emailAddresses: u"mail",
- service.fieldName.password: u"userPassword",
- }.get(fieldName, fieldName.name))
-
def toUnicode(obj):
if isinstance(obj, (NamedConstant, ValueConstant)):
return obj.name
@@ -227,8 +255,13 @@
return unicode(obj)
def tuplify(record, fieldName):
- name = toAttribute(fieldName)
- value = toUnicode(record.fields[fieldName])
+ name = DEFAULT_FIELDNAME_MAP.get(fieldName, fieldName.name)
+
+ if fieldName is BaseFieldName.recordType:
+ value = DEFAULT_RECORDTYPE_MAP[record.fields[fieldName]]
+ else:
+ value = toUnicode(record.fields[fieldName])
+
return (name, value)
for records in service.index[service.fieldName.uid].itervalues():
@@ -245,10 +278,4 @@
data[dn] = recordData
- # from pprint import pprint
- # print("")
- # print("-" * 80)
- # pprint(data)
- # print("-" * 80)
-
return data
Modified: twext/trunk/twext/who/ldap/test/test_util.py
===================================================================
--- twext/trunk/twext/who/ldap/test/test_util.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/ldap/test/test_util.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -38,7 +38,13 @@
Tests for LDAP query generation.
"""
- def attrMap(self, service):
+ def service(self):
+ # Use intentionally funky conenction info, since we don't expect
+ # to connect.
+ return DirectoryService(u"ldap://cretin/", u"o=plugh")
+
+
+ def fieldNameMap(self, service):
"""
Create a mapping from field names to LDAP attribute names.
The attribute names returned here are not real LDAP attribute names,
@@ -48,12 +54,22 @@
return dict([(c, c.name) for c in service.fieldName.iterconstants()])
+ def recordTypeMap(self, service):
+ """
+ Create a mapping from record types to LDAP object class names.
+ The object class names returned here are not real LDAP object class
+ names, but we don't care for these tests, since we're not actually
+ connecting to LDAP.
+ """
+ return dict([(c, c.name) for c in service.recordType.iterconstants()])
+
+
def test_queryStringFromMatchExpression_matchTypes(self):
"""
Match expressions with each match type produces the correct
operator=value string.
"""
- service = DirectoryService()
+ service = self.service()
for matchType, expected in (
(MatchType.equals, u"=xyzzy"),
@@ -70,10 +86,11 @@
matchType=matchType
)
queryString = ldapQueryStringFromMatchExpression(
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"({attribute}{expected})".format(
- attribute="shortNames", expected=expected
+ attribute=u"shortNames", expected=expected
)
self.assertEquals(queryString, expected)
@@ -82,17 +99,18 @@
"""
Match expression with the C{NOT} flag adds the C{!} operator.
"""
- service = DirectoryService()
+ service = self.service()
expression = MatchExpression(
service.fieldName.shortNames, u"xyzzy",
flags=MatchFlags.NOT
)
queryString = ldapQueryStringFromMatchExpression(
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"(!{attribute}=xyzzy)".format(
- attribute="shortNames",
+ attribute=u"shortNames",
)
self.assertEquals(queryString, expected)
@@ -102,17 +120,18 @@
Match expression with the C{caseInsensitive} flag adds the C{??????}
operator.
"""
- service = DirectoryService()
+ service = self.service()
expression = MatchExpression(
service.fieldName.shortNames, u"xyzzy",
flags=MatchFlags.caseInsensitive
)
queryString = ldapQueryStringFromMatchExpression(
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"???????({attribute}=xyzzy)".format(
- attribute="shortNames",
+ attribute=u"shortNames",
)
self.assertEquals(queryString, expected)
@@ -126,17 +145,18 @@
"""
Special characters are quoted properly.
"""
- service = DirectoryService()
+ service = self.service()
expression = MatchExpression(
service.fieldName.fullNames,
u"\\xyzzy: a/b/(c)* ~~ >=< ~~ &| \0!!"
)
queryString = ldapQueryStringFromMatchExpression(
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"({attribute}={expected})".format(
- attribute="fullNames",
+ attribute=u"fullNames",
expected=(
u"\\5Cxyzzy: a\\2Fb\\2F\\28c\\29\\2A "
"\\7E\\7E \\3E\\3D\\3C \\7E\\7E \\26\\7C \\00!!"
@@ -149,7 +169,7 @@
"""
Unknown expression.
"""
- service = DirectoryService()
+ service = self.service()
expression = MatchExpression(
object(), u"xyzzy",
@@ -158,7 +178,8 @@
self.assertRaises(
QueryNotSupportedError,
ldapQueryStringFromMatchExpression,
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
@@ -166,7 +187,7 @@
"""
Unknown expression.
"""
- service = DirectoryService()
+ service = self.service()
expression = MatchExpression(
service.fieldName.shortNames, u"xyzzy",
@@ -176,7 +197,8 @@
self.assertRaises(
QueryNotSupportedError,
ldapQueryStringFromMatchExpression,
- expression, self.attrMap(service)
+ expression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
@@ -192,7 +214,7 @@
The Operand shouldn't make any difference here, so we test AND and OR,
expecting the same result.
"""
- service = DirectoryService()
+ service = self.service()
for operand in (Operand.AND, Operand.OR):
matchExpression = MatchExpression(
@@ -203,11 +225,13 @@
operand
)
queryString = queryFunction(
- compoundExpression, self.attrMap(service)
+ compoundExpression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"{match}".format(
match=ldapQueryStringFromMatchExpression(
- matchExpression, self.attrMap(service)
+ matchExpression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
)
self.assertEquals(queryString, expected)
@@ -221,7 +245,7 @@
The sub-expressions should be grouped with the given operand.
"""
- service = DirectoryService()
+ service = self.service()
for (operand, token) in ((Operand.AND, u"&"), (Operand.OR, u"|")):
matchExpression1 = MatchExpression(
@@ -235,15 +259,18 @@
operand
)
queryString = queryFunction(
- compoundExpression, self.attrMap(service)
+ compoundExpression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = u"({op}{match1}{match2})".format(
op=token,
match1=ldapQueryStringFromMatchExpression(
- matchExpression1, self.attrMap(service)
+ matchExpression1,
+ self.fieldNameMap(service), self.recordTypeMap(service),
),
match2=ldapQueryStringFromMatchExpression(
- matchExpression2, self.attrMap(service)
+ matchExpression2,
+ self.fieldNameMap(service), self.recordTypeMap(service),
),
)
self.assertEquals(queryString, expected)
@@ -253,16 +280,18 @@
"""
Match expression.
"""
- service = DirectoryService()
+ service = self.service()
matchExpression = MatchExpression(
service.fieldName.shortNames, u"xyzzy"
)
queryString = ldapQueryStringFromExpression(
- matchExpression, self.attrMap(service)
+ matchExpression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
expected = ldapQueryStringFromMatchExpression(
- matchExpression, self.attrMap(service)
+ matchExpression,
+ self.fieldNameMap(service), self.recordTypeMap(service),
)
self.assertEquals(queryString, expected)
@@ -283,10 +312,10 @@
"""
Unknown expression.
"""
- service = DirectoryService()
+ service = self.service()
self.assertRaises(
QueryNotSupportedError,
ldapQueryStringFromExpression,
- object(), self.attrMap(service)
+ object(), self.fieldNameMap(service), self.recordTypeMap(service)
)
Modified: twext/trunk/twext/who/test/test_directory.py
===================================================================
--- twext/trunk/twext/who/test/test_directory.py 2014-01-14 00:20:20 UTC (rev 12330)
+++ twext/trunk/twext/who/test/test_directory.py 2014-01-14 00:38:59 UTC (rev 12331)
@@ -227,8 +227,8 @@
@inlineCallbacks
def test_recordsFromExpression_emptyExpression(self):
"""
- L{DirectoryService.recordsFromExpression} with an unknown expression
- type and an empty L{CompoundExpression} returns an empty result.
+ L{DirectoryService.recordsFromExpression} with an empty
+ L{CompoundExpression} returns an empty result.
"""
service = self.service()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/f30cd6e0/attachment.html>
More information about the calendarserver-changes
mailing list