[CalendarServer-changes] [11900] CalendarServer/branches/users/cdaboo/reverse-proxy-pods
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:23:22 PDT 2014
Revision: 11900
http://trac.calendarserver.org//changeset/11900
Author: cdaboo at apple.com
Date: 2013-11-06 18:00:24 -0800 (Wed, 06 Nov 2013)
Log Message:
-----------
Merge from trunk.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/HACKING
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/directory.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/idirectory.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_aggregate.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_directory.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_util.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_xml.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
Property Changed:
----------------
CalendarServer/branches/users/cdaboo/reverse-proxy-pods/
Property changes on: CalendarServer/branches/users/cdaboo/reverse-proxy-pods
___________________________________________________________________
Modified: svn:mergeinfo
- /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
+ /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11875-11895
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/HACKING
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/HACKING 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/HACKING 2013-11-07 02:00:24 UTC (rev 11900)
@@ -144,10 +144,6 @@
PEP-8 items we do not follow:
- * Lines need not be limited to 79 spaces, but longer lines are
- undesirable. If you can easily do so, try to keep lines under 80
- columns.
-
* PEP-8 recommends using a backslash to break long lines up:
::
@@ -181,14 +177,6 @@
Because that's just silly.
- * Lining up assignments is OK, within reason:
-
- ::
-
- cars = 4
- motorbikes = 8
- bicycles = 18
-
Additions:
* Close parentheses and brackets such as ``()``, ``[]`` and ``{}`` at the
@@ -248,9 +236,8 @@
process = subprocess.Popen(...)
- This makes code shorter and removes the runtime indirection (which
- can be relevant in tight loops). It also makes it easier to replace
- one implementation with another.
+ This makes code shorter and makes it easier to replace one implementation
+ with another.
* All files should have an ``__all__`` specification. Put them at the
top of the file, before imports (PEP-8 puts them at the top, but
@@ -259,8 +246,8 @@
* It is more important that symbol names are meaningful than it is
that they be concise. ``x`` is rarely an appropriate name for a
- variable. ``transmogrifierStatus`` is more useful to the reader
- than ``trmgStat``; avoid contractions.
+ variable. Avoid contractions: ``transmogrifierStatus`` is more useful
+ to the reader than ``trmgStat``.
* A deferred that will be immediately returned may be called ``d``:
@@ -271,9 +258,7 @@
d.addErrback(onError)
return d
- * We prefer ``inlineCallbacks`` over ``deferredGenerator``.
- ``inlineCallbacks`` are more readable, and we do not support Python
- versions old enough that ``deferredGenerator`` would be necessary.
+ * Do not use ``deferredGenerator``. Use ``inlineCallbacks`` instead.
* That said, avoid using ``inlineCallbacks`` when chaining deferreds
is straightforward, as they are more expensive. Use
@@ -306,17 +291,29 @@
Use of underscores is reserved for implied dispatching and the like
(eg. ``http_FOO()``). See the Twisted Coding Standard for details.
- * Always use a tuple when using ``%``-formatting, even when only one
- value is being provided:
+ * Do not use ``%``-formatting:
::
error = "Unexpected value: %s" % (value,)
- Do not use the non-tuple form:
+ Use PEP-3101 formatting instead:
::
+ error = "Unexpected value: {value}".format(value=value)
+
+ * If you must use ``%``-formatting for some reason, always use a tuple as
+ the format argument, even when only one value is being provided:
+
+ ::
+
+ error = "Unexpected value: %s" % (value,)
+
+ Never use the non-tuple form:
+
+ ::
+
error = "Unexpected value: %s" % value
Which is allowed in Python, but results in a programming error if
@@ -329,8 +326,9 @@
numbers = (1,2,3,) # No
numbers = (1,2,3) # Yes
- It's desirable on multiple lines, though, as that makes re-ordering
- items easy, and avoids a diff on the last line when adding another:
+ The trailing comma is desirable on multiple lines, though, as that makes
+ re-ordering items easy, and avoids a diff on the last line when adding
+ another:
::
@@ -368,11 +366,11 @@
==============
* If a callable is going to return a Deferred some of the time, it
- should probably return a deferred all of the time. Return
- ``succeed(value)`` instead of ``value`` if necessary. This avoids
- forcing the caller to check as to whether the value is a deferred
- or not (eg. by using ``maybeDeferred()``), which is both annoying
- to code and potentially expensive at runtime.
+ should return a deferred all of the time. Return ``succeed(value)``
+ instead of ``value`` if necessary. This avoids forcing the caller
+ to check as to whether the value is a deferred or not (eg. by using
+ ``maybeDeferred()``), which is both annoying to code and potentially
+ expensive at runtime.
* Be proactive about closing files and file-like objects.
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/directory.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/directory.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -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,
@@ -285,9 +363,11 @@
def members(self):
if self.recordType == RecordType.group:
- raise NotImplementedError("Subclasses must implement members()")
+ return fail(
+ NotImplementedError("Subclasses must implement members()")
+ )
return succeed(())
def groups(self):
- raise NotImplementedError("Subclasses must implement groups()")
+ return fail(NotImplementedError("Subclasses must implement groups()"))
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/idirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/idirectory.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/idirectory.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -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.
"""
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_aggregate.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_aggregate.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_aggregate.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -26,7 +26,8 @@
from twext.who.util import ConstantsContainer
from twext.who.test import test_directory, test_xml
-from twext.who.test.test_xml import QueryMixIn, xmlService, TestService as XMLTestService
+from twext.who.test.test_xml import QueryMixIn, xmlService
+from twext.who.test.test_xml import TestService as XMLTestService
@@ -68,7 +69,10 @@
-class DirectoryServiceImmutableTest(BaseTest, test_directory.DirectoryServiceImmutableTest):
+class DirectoryServiceImmutableTest(
+ BaseTest,
+ test_directory.BaseDirectoryServiceImmutableTest,
+):
pass
@@ -81,24 +85,39 @@
class GroupsDirectoryService(XMLTestService):
recordType = ConstantsContainer((XMLTestService.recordType.group,))
- usersService = self.xmlService(testXMLConfigUsers, UsersDirectoryService)
- groupsService = self.xmlService(testXMLConfigGroups, GroupsDirectoryService)
+ usersService = self.xmlService(
+ testXMLConfigUsers,
+ UsersDirectoryService
+ )
+ groupsService = self.xmlService(
+ testXMLConfigGroups,
+ GroupsDirectoryService
+ )
return BaseTest.service(self, (usersService, groupsService))
-class DirectoryServiceAggregatedBaseTest(AggregatedBaseTest, DirectoryServiceBaseTest):
+class DirectoryServiceAggregatedBaseTest(
+ AggregatedBaseTest,
+ DirectoryServiceBaseTest,
+):
pass
-class DirectoryServiceAggregatedQueryTest(AggregatedBaseTest, test_xml.DirectoryServiceQueryTest):
+class DirectoryServiceAggregatedQueryTest(
+ AggregatedBaseTest,
+ test_xml.DirectoryServiceQueryTest,
+):
pass
-class DirectoryServiceAggregatedImmutableTest(AggregatedBaseTest, test_directory.DirectoryServiceImmutableTest):
+class DirectoryServiceAggregatedImmutableTest(
+ AggregatedBaseTest,
+ test_directory.BaseDirectoryServiceImmutableTest,
+):
pass
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_directory.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_directory.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -31,7 +31,7 @@
-class BaseTest(unittest.TestCase):
+class ServiceMixIn(object):
realmName = "xyzzy"
@@ -42,7 +42,7 @@
-class DirectoryServiceTest(BaseTest):
+class BaseDirectoryServiceTest(ServiceMixIn):
def test_interface(self):
service = self.service()
try:
@@ -69,13 +69,6 @@
)
- # @inlineCallbacks
- # def test_recordsFromExpression(self):
- # service = self.service()
- # result = yield(service.recordsFromExpression(None))
- # self.assertIsInstance(result, QueryNotSupportedError)
-
-
@inlineCallbacks
def test_recordsFromQueryNone(self):
service = self.service()
@@ -113,7 +106,55 @@
-class DirectoryServiceImmutableTest(BaseTest):
+class DirectoryServiceTest(unittest.TestCase, BaseDirectoryServiceTest):
+ def test_recordsFromExpression(self):
+ service = self.service()
+ result = yield(service.recordsFromExpression(None))
+ self.assertFailure(result, QueryNotSupportedError)
+
+
+ def test_recordWithUID(self):
+ service = self.service()
+ self.assertFailure(
+ service.recordWithUID(None),
+ QueryNotSupportedError
+ )
+
+
+ def test_recordWithGUID(self):
+ service = self.service()
+ self.assertFailure(
+ service.recordWithGUID(None),
+ QueryNotSupportedError
+ )
+
+
+ def test_recordsWithRecordType(self):
+ service = self.service()
+ self.assertFailure(
+ service.recordsWithRecordType(None),
+ QueryNotSupportedError
+ )
+
+
+ def test_recordWithShortName(self):
+ service = self.service()
+ self.assertFailure(
+ service.recordWithShortName(None, None),
+ QueryNotSupportedError
+ )
+
+
+ def test_recordsWithEmailAddress(self):
+ service = self.service()
+ self.assertFailure(
+ service.recordsWithEmailAddress(None),
+ QueryNotSupportedError
+ )
+
+
+
+class BaseDirectoryServiceImmutableTest(ServiceMixIn):
def test_updateRecordsNotAllowed(self):
service = self.service()
@@ -148,7 +189,15 @@
-class DirectoryRecordTest(BaseTest):
+class DirectoryServiceImmutableTest(
+ unittest.TestCase,
+ BaseDirectoryServiceImmutableTest,
+):
+ pass
+
+
+
+class BaseDirectoryRecordTest(ServiceMixIn):
fields_wsanchez = {
FieldName.uid: "UID:wsanchez",
FieldName.recordType: RecordType.user,
@@ -179,8 +228,16 @@
FieldName.emailAddresses: ("sagen at CalendarServer.org",)
}
+ fields_staff = {
+ FieldName.uid: "UID:staff",
+ FieldName.recordType: RecordType.group,
+ FieldName.shortNames: ("staff",),
+ FieldName.fullNames: ("Staff",),
+ FieldName.emailAddresses: ("staff at CalendarServer.org",)
+ }
- def _testRecord(self, fields=None, service=None):
+
+ def makeRecord(self, fields=None, service=None):
if fields is None:
fields = self.fields_wsanchez
if service is None:
@@ -189,7 +246,7 @@
def test_interface(self):
- record = self._testRecord()
+ record = self.makeRecord()
try:
verifyObject(IDirectoryRecord, record)
except BrokenMethodImplementation as e:
@@ -198,7 +255,7 @@
def test_init(self):
service = self.service()
- wsanchez = self._testRecord(self.fields_wsanchez, service=service)
+ wsanchez = self.makeRecord(self.fields_wsanchez, service=service)
self.assertEquals(wsanchez.service, service)
self.assertEquals(wsanchez.fields, self.fields_wsanchez)
@@ -207,49 +264,49 @@
def test_initWithNoUID(self):
fields = self.fields_wsanchez.copy()
del fields[FieldName.uid]
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
fields = self.fields_wsanchez.copy()
fields[FieldName.uid] = ""
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
def test_initWithNoRecordType(self):
fields = self.fields_wsanchez.copy()
del fields[FieldName.recordType]
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
fields = self.fields_wsanchez.copy()
fields[FieldName.recordType] = ""
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
def test_initWithNoShortNames(self):
fields = self.fields_wsanchez.copy()
del fields[FieldName.shortNames]
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
fields = self.fields_wsanchez.copy()
fields[FieldName.shortNames] = ()
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
fields = self.fields_wsanchez.copy()
fields[FieldName.shortNames] = ("",)
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
fields = self.fields_wsanchez.copy()
fields[FieldName.shortNames] = ("wsanchez", "")
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
def test_initWithBogusRecordType(self):
fields = self.fields_wsanchez.copy()
fields[FieldName.recordType] = object()
- self.assertRaises(ValueError, self._testRecord, fields)
+ self.assertRaises(ValueError, self.makeRecord, fields)
def test_initNormalize(self):
- sagen = self._testRecord(self.fields_sagen)
+ sagen = self.makeRecord(self.fields_sagen)
self.assertEquals(
sagen.fields[FieldName.emailAddresses],
@@ -263,10 +320,10 @@
plugh = DirectoryService("plugh")
- wsanchez = self._testRecord(self.fields_wsanchez)
- wsanchezmod = self._testRecord(self.fields_wsanchez, plugh)
- glyph = self._testRecord(self.fields_glyph)
- glyphmod = self._testRecord(fields_glyphmod)
+ wsanchez = self.makeRecord(self.fields_wsanchez)
+ wsanchezmod = self.makeRecord(self.fields_wsanchez, plugh)
+ glyph = self.makeRecord(self.fields_glyph)
+ glyphmod = self.makeRecord(fields_glyphmod)
self.assertEquals(wsanchez, wsanchez)
self.assertNotEqual(wsanchez, glyph)
@@ -276,7 +333,7 @@
def test_attributeAccess(self):
- wsanchez = self._testRecord(self.fields_wsanchez)
+ wsanchez = self.makeRecord(self.fields_wsanchez)
self.assertEquals(
wsanchez.recordType,
@@ -295,10 +352,10 @@
wsanchez.fields[FieldName.emailAddresses]
)
+
@inlineCallbacks
def test_members(self):
- wsanchez = self._testRecord(self.fields_wsanchez)
-
+ wsanchez = self.makeRecord(self.fields_wsanchez)
self.assertEquals(
set((yield wsanchez.members())),
set()
@@ -306,5 +363,24 @@
raise SkipTest("Subclasses should implement this test.")
+
def test_groups(self):
raise SkipTest("Subclasses should implement this test.")
+
+
+
+class DirectoryRecordTest(unittest.TestCase, BaseDirectoryRecordTest):
+ def test_members(self):
+ wsanchez = self.makeRecord(self.fields_wsanchez)
+ self.assertEquals(
+ set((yield wsanchez.members())),
+ set()
+ )
+
+ staff = self.makeRecord(self.fields_staff)
+ self.assertFailure(staff.members(), NotImplementedError)
+
+
+ def test_groups(self):
+ wsanchez = self.makeRecord(self.fields_wsanchez)
+ self.assertFailure(wsanchez.groups(), NotImplementedError)
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_util.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_util.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -82,7 +82,11 @@
)
def test_lookupByName(self):
- constants = set((Instruments.hammer, Tools.screwdriver, Instruments.chisel))
+ constants = set((
+ Instruments.hammer,
+ Tools.screwdriver,
+ Instruments.chisel,
+ ))
container = ConstantsContainer(constants)
self.assertEquals(
@@ -108,7 +112,7 @@
class UtilTest(unittest.TestCase):
def test_uniqueResult(self):
self.assertEquals(1, uniqueResult((1,)))
- self.assertRaises(DirectoryServiceError, uniqueResult, (1,2,3))
+ self.assertRaises(DirectoryServiceError, uniqueResult, (1, 2, 3))
def test_describe(self):
self.assertEquals("nail pounder", describe(Tools.hammer))
@@ -116,5 +120,5 @@
def test_describeFlags(self):
self.assertEquals("blue", describe(Switches.b))
- self.assertEquals("red|green", describe(Switches.r|Switches.g))
- self.assertEquals("blue|black", describe(Switches.b|Switches.black))
+ self.assertEquals("red|green", describe(Switches.r | Switches.g))
+ self.assertEquals("blue|black", describe(Switches.b | Switches.black))
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_xml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_xml.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/twext/who/test/test_xml.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -47,7 +47,10 @@
-class DirectoryServiceBaseTest(BaseTest, test_directory.DirectoryServiceTest):
+class DirectoryServiceBaseTest(
+ BaseTest,
+ test_directory.BaseDirectoryServiceTest,
+):
def test_repr(self):
service = self.service()
@@ -70,7 +73,11 @@
@inlineCallbacks
def test_recordWithGUID(self):
service = self.service()
- record = (yield service.recordWithGUID("6C495FCD-7E78-4D5C-AA66-BC890AD04C9D"))
+ record = (
+ yield service.recordWithGUID(
+ "6C495FCD-7E78-4D5C-AA66-BC890AD04C9D"
+ )
+ )
self.assertEquals(record, None)
@inlineCallbacks
@@ -80,8 +87,11 @@
records = (yield service.recordsWithRecordType(object()))
self.assertEquals(set(records), set())
- records = (yield service.recordsWithRecordType(service.recordType.user))
- self.assertRecords(records,
+ records = (
+ yield service.recordsWithRecordType(service.recordType.user)
+ )
+ self.assertRecords(
+ records,
(
"__wsanchez__",
"__glyph__",
@@ -95,8 +105,11 @@
),
)
- records = (yield service.recordsWithRecordType(service.recordType.group))
- self.assertRecords(records,
+ records = (
+ yield service.recordsWithRecordType(service.recordType.group)
+ )
+ self.assertRecords(
+ records,
(
"__calendar-dev__",
"__twisted__",
@@ -109,13 +122,28 @@
def test_recordWithShortName(self):
service = self.service()
- record = (yield service.recordWithShortName(service.recordType.user, "null"))
+ record = (
+ yield service.recordWithShortName(
+ service.recordType.user,
+ "null",
+ )
+ )
self.assertEquals(record, None)
- record = (yield service.recordWithShortName(service.recordType.user, "wsanchez"))
+ record = (
+ yield service.recordWithShortName(
+ service.recordType.user,
+ "wsanchez",
+ )
+ )
self.assertEquals(record.uid, "__wsanchez__")
- record = (yield service.recordWithShortName(service.recordType.user, "wilfredo_sanchez"))
+ record = (
+ yield service.recordWithShortName(
+ service.recordType.user,
+ "wilfredo_sanchez",
+ )
+ )
self.assertEquals(record.uid, "__wsanchez__")
@@ -123,13 +151,25 @@
def test_recordsWithEmailAddress(self):
service = self.service()
- records = (yield service.recordsWithEmailAddress("wsanchez at bitbucket.calendarserver.org"))
+ records = (
+ yield service.recordsWithEmailAddress(
+ "wsanchez at bitbucket.calendarserver.org"
+ )
+ )
self.assertRecords(records, ("__wsanchez__",))
- records = (yield service.recordsWithEmailAddress("wsanchez at devnull.twistedmatrix.com"))
+ records = (
+ yield service.recordsWithEmailAddress(
+ "wsanchez at devnull.twistedmatrix.com"
+ )
+ )
self.assertRecords(records, ("__wsanchez__",))
- records = (yield service.recordsWithEmailAddress("shared at example.com"))
+ records = (
+ yield service.recordsWithEmailAddress(
+ "shared at example.com"
+ )
+ )
self.assertRecords(records, ("__sagen__", "__dre__"))
@@ -176,12 +216,12 @@
def test_badRootElement(self):
- service = self.service(xmlData=
+ service = self.service(xmlData=(
"""<?xml version="1.0" encoding="utf-8"?>
<frobnitz />
"""
- )
+ ))
self.assertRaises(ParseError, service.loadRecords)
try:
@@ -193,12 +233,12 @@
def test_noRealmName(self):
- service = self.service(xmlData=
+ service = self.service(xmlData=(
"""<?xml version="1.0" encoding="utf-8"?>
<directory />
"""
- )
+ ))
self.assertRaises(ParseError, service.loadRecords)
try:
@@ -215,7 +255,7 @@
def test_unknownFieldElementsDirty(self):
- service = self.service(xmlData=
+ service = self.service(xmlData=(
"""<?xml version="1.0" encoding="utf-8"?>
<directory realm="Unknown Record Types">
@@ -226,8 +266,11 @@
</record>
</directory>
"""
+ ))
+ self.assertEquals(
+ set(service.unknownFieldElements),
+ set(("political-affiliation",))
)
- self.assertEquals(set(service.unknownFieldElements), set(("political-affiliation",)))
def test_unknownRecordTypesClean(self):
@@ -236,7 +279,7 @@
def test_unknownRecordTypesDirty(self):
- service = self.service(xmlData=
+ service = self.service(xmlData=(
"""<?xml version="1.0" encoding="utf-8"?>
<directory realm="Unknown Record Types">
@@ -247,7 +290,7 @@
</record>
</directory>
"""
- )
+ ))
self.assertEquals(set(service.unknownRecordTypes), set(("camera",)))
@@ -314,7 +357,10 @@
records = yield service.recordsFromQuery(
(
service.query("emailAddresses", "shared at example.com"),
- service.query("fullNames", "Andre LaBranche", flags=MatchFlags.NOT),
+ service.query(
+ "fullNames", "Andre LaBranche",
+ flags=MatchFlags.NOT
+ ),
),
operand=Operand.AND
)
@@ -325,7 +371,10 @@
def test_queryCaseInsensitive(self):
service = self.service()
records = yield service.recordsFromQuery((
- service.query("shortNames", "SagEn", flags=MatchFlags.caseInsensitive),
+ service.query(
+ "shortNames", "SagEn",
+ flags=MatchFlags.caseInsensitive
+ ),
))
self.assertRecords(records, ("__sagen__",))
@@ -334,7 +383,10 @@
def test_queryCaseInsensitiveNoIndex(self):
service = self.service()
records = yield service.recordsFromQuery((
- service.query("fullNames", "moRGen SAGen", flags=MatchFlags.caseInsensitive),
+ service.query(
+ "fullNames", "moRGen SAGen",
+ flags=MatchFlags.caseInsensitive
+ ),
))
self.assertRecords(records, ("__sagen__",))
@@ -352,7 +404,10 @@
def test_queryStartsWithNoIndex(self):
service = self.service()
records = yield service.recordsFromQuery((
- service.query("fullNames", "Wilfredo", matchType=MatchType.startsWith),
+ service.query(
+ "fullNames", "Wilfredo",
+ matchType=MatchType.startsWith
+ ),
))
self.assertRecords(records, ("__wsanchez__",))
@@ -363,8 +418,8 @@
records = yield service.recordsFromQuery((
service.query(
"shortNames", "w",
- matchType = MatchType.startsWith,
- flags = MatchFlags.NOT,
+ matchType=MatchType.startsWith,
+ flags=MatchFlags.NOT,
),
))
self.assertRecords(
@@ -397,8 +452,8 @@
records = yield service.recordsFromQuery((
service.query(
"shortNames", "wil",
- matchType = MatchType.startsWith,
- flags = MatchFlags.NOT,
+ matchType=MatchType.startsWith,
+ flags=MatchFlags.NOT,
),
))
self.assertRecords(
@@ -426,8 +481,8 @@
records = yield service.recordsFromQuery((
service.query(
"fullNames", "Wilfredo",
- matchType = MatchType.startsWith,
- flags = MatchFlags.NOT,
+ matchType=MatchType.startsWith,
+ flags=MatchFlags.NOT,
),
))
self.assertRecords(
@@ -454,8 +509,8 @@
records = yield service.recordsFromQuery((
service.query(
"shortNames", "WIL",
- matchType = MatchType.startsWith,
- flags = MatchFlags.caseInsensitive,
+ matchType=MatchType.startsWith,
+ flags=MatchFlags.caseInsensitive,
),
))
self.assertRecords(records, ("__wsanchez__",))
@@ -467,8 +522,8 @@
records = yield service.recordsFromQuery((
service.query(
"fullNames", "wilfrEdo",
- matchType = MatchType.startsWith,
- flags = MatchFlags.caseInsensitive,
+ matchType=MatchType.startsWith,
+ flags=MatchFlags.caseInsensitive,
),
))
self.assertRecords(records, ("__wsanchez__",))
@@ -478,7 +533,10 @@
def test_queryContains(self):
service = self.service()
records = yield service.recordsFromQuery((
- service.query("shortNames", "sanchez", matchType=MatchType.contains),
+ service.query(
+ "shortNames", "sanchez",
+ matchType=MatchType.contains
+ ),
))
self.assertRecords(records, ("__wsanchez__",))
@@ -498,8 +556,8 @@
records = yield service.recordsFromQuery((
service.query(
"shortNames", "sanchez",
- matchType = MatchType.contains,
- flags = MatchFlags.NOT,
+ matchType=MatchType.contains,
+ flags=MatchFlags.NOT,
),
))
self.assertRecords(
@@ -526,8 +584,8 @@
records = yield service.recordsFromQuery((
service.query(
"fullNames", "fred",
- matchType = MatchType.contains,
- flags = MatchFlags.NOT,
+ matchType=MatchType.contains,
+ flags=MatchFlags.NOT,
),
))
self.assertRecords(
@@ -590,12 +648,18 @@
# Verify change is present immediately
record = (yield service.recordWithUID("__wsanchez__"))
- self.assertEquals(set(record.fullNames), set(("Wilfredo Sanchez Vega",)))
+ self.assertEquals(
+ set(record.fullNames),
+ set(("Wilfredo Sanchez Vega",))
+ )
# Verify change is persisted
service.flush()
record = (yield service.recordWithUID("__wsanchez__"))
- self.assertEquals(set(record.fullNames), set(("Wilfredo Sanchez Vega",)))
+ self.assertEquals(
+ set(record.fullNames),
+ set(("Wilfredo Sanchez Vega",))
+ )
@inlineCallbacks
@@ -604,7 +668,7 @@
newRecord = DirectoryRecord(
service,
- fields = {
+ fields={
service.fieldName.uid: "__plugh__",
service.fieldName.recordType: service.recordType.user,
service.fieldName.shortNames: ("plugh",),
@@ -628,14 +692,17 @@
newRecord = DirectoryRecord(
service,
- fields = {
+ fields={
service.fieldName.uid: "__plugh__",
service.fieldName.recordType: service.recordType.user,
service.fieldName.shortNames: ("plugh",),
}
)
- self.assertFailure(service.updateRecords((newRecord,)), NoSuchRecordError)
+ self.assertFailure(
+ service.updateRecords((newRecord,)),
+ NoSuchRecordError
+ )
@inlineCallbacks
@@ -659,7 +726,7 @@
-class DirectoryRecordTest(BaseTest, test_directory.DirectoryRecordTest):
+class DirectoryRecordTest(BaseTest, test_directory.BaseDirectoryRecordTest):
@inlineCallbacks
def test_members(self):
service = self.service()
@@ -714,8 +781,8 @@
assert name is not None
return MatchExpression(
name, value,
- matchType = matchType,
- flags = flags,
+ matchType=matchType,
+ flags=flags,
)
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -94,27 +94,28 @@
"""
inbox = (yield home.calendarWithName("inbox"))
- prop = inbox.properties().get(PropertyName.fromElement(propname))
- if prop is not None:
- defaultCalendar = str(prop.children[0])
- parts = defaultCalendar.split("/")
- if len(parts) == 5:
+ if inbox is not None:
+ prop = inbox.properties().get(PropertyName.fromElement(propname))
+ if prop is not None:
+ defaultCalendar = str(prop.children[0])
+ parts = defaultCalendar.split("/")
+ if len(parts) == 5:
- calendarName = parts[-1]
- calendarHomeUID = parts[-2]
- if calendarHomeUID == home.uid():
+ calendarName = parts[-1]
+ calendarHomeUID = parts[-2]
+ if calendarHomeUID == home.uid():
- calendar = (yield home.calendarWithName(calendarName))
- if calendar is not None:
- try:
- yield home.setDefaultCalendar(
- calendar, tasks=(propname == customxml.ScheduleDefaultTasksURL)
- )
- except InvalidDefaultCalendar:
- # Ignore these - the server will recover
- pass
+ calendar = (yield home.calendarWithName(calendarName))
+ if calendar is not None:
+ try:
+ yield home.setDefaultCalendar(
+ calendar, tasks=(propname == customxml.ScheduleDefaultTasksURL)
+ )
+ except InvalidDefaultCalendar:
+ # Ignore these - the server will recover
+ pass
- del inbox.properties()[PropertyName.fromElement(propname)]
+ del inbox.properties()[PropertyName.fromElement(propname)]
@@ -130,15 +131,13 @@
calendars = (yield home.loadChildren())
for calendar in calendars:
if calendar.isInbox():
- continue
+ prop = calendar.properties().get(PropertyName.fromElement(caldavxml.CalendarFreeBusySet))
+ if prop is not None:
+ del calendar.properties()[PropertyName.fromElement(caldavxml.CalendarFreeBusySet)]
prop = calendar.properties().get(PropertyName.fromElement(caldavxml.ScheduleCalendarTransp))
if prop is not None:
yield calendar.setUsedForFreeBusy(prop == caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
del calendar.properties()[PropertyName.fromElement(caldavxml.ScheduleCalendarTransp)]
- inbox = (yield home.calendarWithName("inbox"))
- prop = inbox.properties().get(PropertyName.fromElement(caldavxml.CalendarFreeBusySet))
- if prop is not None:
- del inbox.properties()[PropertyName.fromElement(caldavxml.CalendarFreeBusySet)]
Modified: CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
===================================================================
--- CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py 2013-11-06 23:41:28 UTC (rev 11899)
+++ CalendarServer/branches/users/cdaboo/reverse-proxy-pods/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py 2013-11-07 02:00:24 UTC (rev 11900)
@@ -102,10 +102,11 @@
the new value from the XML property.
"""
inbox = (yield home.calendarWithName("inbox"))
- prop = inbox.properties().get(PropertyName.fromElement(customxml.CalendarAvailability))
- if prop is not None:
- yield home.setAvailability(prop.calendar())
- del inbox.properties()[PropertyName.fromElement(customxml.CalendarAvailability)]
+ if inbox is not None:
+ prop = inbox.properties().get(PropertyName.fromElement(customxml.CalendarAvailability))
+ if prop is not None:
+ yield home.setAvailability(prop.calendar())
+ del inbox.properties()[PropertyName.fromElement(customxml.CalendarAvailability)]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/7087e7f7/attachment.html>
More information about the calendarserver-changes
mailing list