[CalendarServer-changes] [11892] CalendarServer/trunk/twext/who
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:18:53 PDT 2014
Revision: 11892
http://trac.calendarserver.org//changeset/11892
Author: wsanchez at apple.com
Date: 2013-11-06 13:20:52 -0800 (Wed, 06 Nov 2013)
Log Message:
-----------
docs
Modified Paths:
--------------
CalendarServer/trunk/twext/who/directory.py
CalendarServer/trunk/twext/who/idirectory.py
Modified: CalendarServer/trunk/twext/who/directory.py
===================================================================
--- CalendarServer/trunk/twext/who/directory.py 2013-11-06 20:11:38 UTC (rev 11891)
+++ CalendarServer/trunk/twext/who/directory.py 2013-11-06 21:20:52 UTC (rev 11892)
@@ -26,7 +26,7 @@
from uuid import UUID
-from zope.interface import implements
+from zope.interface import implementer
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.internet.defer import succeed, fail
@@ -40,19 +40,63 @@
+ at implementer(IDirectoryService)
class DirectoryService(object):
- implements(IDirectoryService)
+ """
+ Generic implementation of L{IDirectoryService}.
+ This is a complete implementation of L{IDirectoryService}, with support for
+ the query operands in L{Operand}.
+
+ The C{recordsWith*} methods are all implemented in terms of
+ L{recordsWithFieldValue}, which is in turn implemented in terms of
+ L{recordsFromExpression}.
+ L{recordsFromQuery} is also implemented in terms of
+ {recordsFromExpression}.
+
+ L{recordsFromExpression} (and therefore most uses of the other methods)
+ will always fail with a L{QueryNotSupportedError}.
+
+ A subclass should therefore override L{recordsFromExpression} with an
+ implementation that handles any queries that it can support and its
+ superclass' implementation with any query it cannot support.
+
+ A subclass may override L{recordsFromQuery} if it is to support additional
+ operands.
+
+ L{updateRecords} and L{removeRecords} will fail with L{NotAllowedError}
+ when asked to modify data.
+ A subclass should override these methods if is to allow editing of
+ directory information.
+
+ @cvar recordType: a L{Names} class or compatible object (eg.
+ L{ConstantsContainer}) which contains the L{NamedConstant}s denoting
+ the record types that are supported by this directory service.
+
+ @cvar fieldName: a L{Names} class or compatible object (eg.
+ L{ConstantsContainer}) which contains the L{NamedConstant}s denoting
+ the record field names that are supported by this directory service.
+
+ @cvar normalizedFields: a L{dict} mapping of (ie. L{NamedConstant}s
+ contained in the C{fieldName} class variable) to callables that take
+ a field value (a L{unicode}) and return a normalized field value (also
+ a L{unicode}).
+ """
+
recordType = RecordType
fieldName = FieldName
normalizedFields = {
FieldName.guid: lambda g: UUID(g).hex,
- FieldName.emailAddresses: lambda e: e.lower(),
+ FieldName.emailAddresses: lambda e: bytes(e).lower(),
}
def __init__(self, realmName):
+ """
+ @param realmName: a realm name
+ @type realmName: unicode
+ """
self.realmName = realmName
@@ -70,11 +114,30 @@
def recordsFromExpression(self, expression, records=None):
"""
Finds records matching a single expression.
- @param expression: an expression
+
+ @note: The implementation in L{DirectoryService} always raises
+ L{QueryNotSupportedError}.
+
+ @note: This L{DirectoryService} adds a C{records} keyword argument to
+ the interface defined by L{IDirectoryService}.
+ This allows the implementation of
+ L{DirectoryService.recordsFromQuery} to narrow the scope of records
+ being searched as it applies expressions.
+ This is therefore relevant to subclasses, which need to support the
+ added parameter, but not to users of L{IDirectoryService}.
+
+ @param expression: an expression to apply
@type expression: L{object}
- @param records: a set of records to search within. C{None} if
+
+ @param records: a set of records to limit the search to. C{None} if
the whole directory should be searched.
@type records: L{set} or L{frozenset}
+
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
+
+ @raises: L{QueryNotSupportedError} if the expression is not
+ supported by this directory service.
"""
return fail(QueryNotSupportedError(
"Unknown expression: {0}".format(expression)
@@ -158,17 +221,32 @@
def updateRecords(self, records, create=False):
for record in records:
return fail(NotAllowedError("Record updates not allowed."))
+ return succeed(None)
def removeRecords(self, uids):
for uid in uids:
return fail(NotAllowedError("Record removal not allowed."))
+ return succeed(None)
+ at implementer(IDirectoryRecord)
class DirectoryRecord(object):
- implements(IDirectoryRecord)
+ """
+ Generic implementation of L{IDirectoryService}.
+ This is an incomplete implementation of L{IDirectoryRecord}.
+
+ L{groups} will always fail with L{NotImplementedError} and L{members} will
+ do so if this is a group record.
+ A subclass should override these methods to support group membership and
+ complete this implementation.
+
+ @cvar requiredFields: an iterable of field names that must be present in
+ all directory records.
+ """
+
requiredFields = (
FieldName.uid,
FieldName.recordType,
Modified: CalendarServer/trunk/twext/who/idirectory.py
===================================================================
--- CalendarServer/trunk/twext/who/idirectory.py 2013-11-06 20:11:38 UTC (rev 11891)
+++ CalendarServer/trunk/twext/who/idirectory.py 2013-11-06 21:20:52 UTC (rev 11892)
@@ -42,9 +42,9 @@
-##
+#
# Exceptions
-##
+#
class DirectoryServiceError(Exception):
"""
@@ -55,7 +55,7 @@
class DirectoryConfigurationError(DirectoryServiceError):
"""
- Directory configurtion error.
+ Directory configuration error.
"""
@@ -93,16 +93,19 @@
class NotAllowedError(DirectoryServiceError):
"""
- Apparently, you can't do that.
+ It seems you aren't permitted to do that.
"""
-##
+#
# Data Types
-##
+#
class RecordType(Names):
+ """
+ Constants for common directory record types.
+ """
user = NamedConstant()
group = NamedConstant()
@@ -113,7 +116,31 @@
class FieldName(Names):
"""
- Constants for common field names.
+ Constants for common directory record field names.
+
+ Fields as assciated with either a single value or an iterable of values.
+
+ @cvar uid: The primary unique identifier for a directory record.
+ The associated value must be a L{unicode}.
+
+ @cvar guid: The globally unique identifier for a directory record.
+ The associated value must be a L{UUID} or C{None}.
+
+ @cvar recordType: The type of a directory record.
+ The associated value must be a L{NamedConstant}.
+
+ @cvar shortNames: The short names for a directory record.
+ The associated values must L{unicode}s and there must be at least
+ one associated value.
+
+ @cvar fullNames: The full names for a directory record.
+ The associated values must be L{unicode}s.
+
+ @cvar emailAddresses: The email addresses for a directory record.
+ The associated values must be L{unicodes}.
+
+ @cvar password: The clear text password for a directory record.
+ The associated value must be a L{unicode} or C{None}.
"""
uid = NamedConstant()
guid = NamedConstant()
@@ -138,11 +165,20 @@
@staticmethod
def isMultiValue(name):
+ """
+ Check for whether a field is multi-value (as opposed to single-value).
+
+ @return: C{True} if the field is multi-value, C{False} otherwise.
+ @rtype: L{BOOL}
+ """
return getattr(name, "multiValue", False)
class Operand(Names):
+ """
+ Contants for common operands.
+ """
OR = NamedConstant()
AND = NamedConstant()
@@ -151,9 +187,9 @@
-##
+#
# Interfaces
-##
+#
class IDirectoryService(Interface):
"""
@@ -169,7 +205,15 @@
A directory service may allow support the editing, removal and
addition of records.
+ Services are read-only should fail with L{NotAllowedError} in editing
+ methods.
+
+ The L{FieldName.uid} field, the L{FieldName.guid} field (if not C{None}),
+ and the combination of the L{FieldName.recordType} and
+ L{FieldName.shortName} fields must be unique to each directory record
+ vended by a directory service.
"""
+
realmName = Attribute(
"The name of the authentication realm this service represents."
)
@@ -177,8 +221,10 @@
def recordTypes():
"""
- @return: an iterable of L{NamedConstant}s denoting the record
- types that are kept in this directory.
+ Get the record types supported by this directory service.
+
+ @return: The record types that are supported by this directory service.
+ @rtype: iterable of L{NamedConstant}s
"""
@@ -189,7 +235,8 @@
@param expression: an expression to apply
@type expression: L{object}
- @return: a deferred iterable of matching L{IDirectoryRecord}s.
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
@raises: L{QueryNotSupportedError} if the expression is not
supported by this directory service.
@@ -207,7 +254,8 @@
@param operand: an operand
@type operand: a L{NamedConstant}
- @return: a deferred iterable of matching L{IDirectoryRecord}s.
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
@raises: L{QueryNotSupportedError} if the query is not
supported by this directory service.
@@ -225,7 +273,8 @@
@param value: a value to match
@type value: L{bytes}
- @return: a deferred iterable of L{IDirectoryRecord}s.
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
"""
@@ -236,8 +285,8 @@
@param uid: a UID
@type uid: L{bytes}
- @return: a deferred iterable of L{IDirectoryRecord}s, or
- C{None} if there is no such record.
+ @return: The matching record or C{None} if there is no match.
+ @rtype: deferred L{IDirectoryRecord}s or C{None}
"""
@@ -248,8 +297,8 @@
@param guid: a GUID
@type guid: L{bytes}
- @return: a deferred iterable of L{IDirectoryRecord}s, or
- C{None} if there is no such record.
+ @return: The matching record or C{None} if there is no match.
+ @rtype: deferred L{IDirectoryRecord}s or C{None}
"""
@@ -260,7 +309,8 @@
@param recordType: a record type
@type recordType: L{NamedConstant}
- @return: a deferred iterable of L{IDirectoryRecord}s.
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
"""
@@ -274,8 +324,8 @@
@param shortName: a short name
@type shortName: L{bytes}
- @return: a deferred iterable of L{IDirectoryRecord}s, or
- C{None} if there is no such record.
+ @return: The matching record or C{None} if there is no match.
+ @rtype: deferred L{IDirectoryRecord}s or C{None}
"""
@@ -286,8 +336,8 @@
@param emailAddress: an email address
@type emailAddress: L{bytes}
- @return: a deferred iterable of L{IDirectoryRecord}s, or
- C{None} if there is no such record.
+ @return: The matching records.
+ @rtype: deferred iterable of L{IDirectoryRecord}s
"""
@@ -300,6 +350,12 @@
@param create: if true, create records if necessary
@type create: boolean
+
+ @return: unspecifiied
+ @rtype: deferred object
+
+ @raises L{NotAllowedError}: if the update is not allowed by the
+ directory service.
"""
@@ -309,6 +365,12 @@
@param uids: the UIDs of the records to remove
@type uids: iterable of L{bytes}
+
+ @return: unspecifiied
+ @rtype: deferred object
+
+ @raises L{NotAllowedError}: if the removal is not allowed by the
+ directory service.
"""
@@ -349,6 +411,7 @@
"""
Find the records that are members of this group. Only direct
members are included; members of members are not expanded.
+
@return: a deferred iterable of L{IDirectoryRecord}s which are
direct members of this group.
"""
@@ -359,6 +422,7 @@
Find the group records that this record is a member of. Only
groups for which this record is a direct member is are
included; membership is not expanded.
+
@return: a deferred iterable of L{IDirectoryRecord}s which are
groups that this record is a member of.
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/609fe797/attachment.html>
More information about the calendarserver-changes
mailing list