[CalendarServer-changes] [3475] CalendarServer/branches/users/cdaboo/limits-3472

source_changes at macosforge.org source_changes at macosforge.org
Mon Dec 8 10:54:31 PST 2008


Revision: 3475
          http://trac.macosforge.org/projects/calendarserver/changeset/3475
Author:   cdaboo at apple.com
Date:     2008-12-08 10:54:31 -0800 (Mon, 08 Dec 2008)
Log Message:
-----------
Add an option to allow a client to set limits for the principal-property-search report. Also return all
the responses up to that limit (or the server's internal limit) and an additional 507 response.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.element.rfc3744.patch
    CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report.patch
    CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/customxml.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/directory/xmlfile.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/extensions.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_calquery.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_common.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_freebusy.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_multiget.py
    CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/scheduling/processing.py

Added Paths:
-----------
    CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_acl_principal_prop_set.patch
    CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch

Modified: CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.element.rfc3744.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.element.rfc3744.patch	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.element.rfc3744.patch	2008-12-08 18:54:31 UTC (rev 3475)
@@ -89,3 +89,14 @@
  
  class PropertySearch (WebDAVElement):
      """
+@@ -745,4 +755,10 @@
+         (dav_namespace, "description"): (1, 1),
+     }
+ 
++class NumberOfMatchesWithinLimits (WebDAVEmptyElement):
++    """
++    Error which indicates too many results
++    """
++    name = "number-of-matches-within-limits"
++
+ # For DAV:description element (RFC 3744, section 9.5) see Description class above.

Modified: CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report.patch	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report.patch	2008-12-08 18:54:31 UTC (rev 3475)
@@ -15,3 +15,19 @@
  
  import string
  
+@@ -43,7 +47,14 @@
+ max_number_of_matches = 500
+ 
+ class NumberOfMatchesWithinLimits(Exception):
+-    pass
++    
++    def __init__(self, limit):
++        
++        super(NumberOfMatchesWithinLimits, self).__init__()
++        self.limit = limit
++        
++    def maxLimit(self):
++        return self.limit
+ 
+ def http_REPORT(self, request):
+     """

Added: CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_acl_principal_prop_set.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_acl_principal_prop_set.patch	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_acl_principal_prop_set.patch	2008-12-08 18:54:31 UTC (rev 3475)
@@ -0,0 +1,22 @@
+Index: twisted/web2/dav/method/report_acl_principal_prop_set.py
+===================================================================
+--- twisted/web2/dav/method/report_acl_principal_prop_set.py	(revision 19773)
++++ twisted/web2/dav/method/report_acl_principal_prop_set.py	(working copy)
+@@ -103,7 +103,7 @@
+             # Check size of results is within limit
+             matchcount += 1
+             if matchcount > max_number_of_matches:
+-                raise NumberOfMatchesWithinLimits
++                raise NumberOfMatchesWithinLimits(max_number_of_matches)
+ 
+             resource = waitForDeferred(request.locateResource(str(principal)))
+             yield resource
+@@ -144,7 +144,7 @@
+         log.err("Too many matching components")
+         raise HTTPError(ErrorResponse(
+             responsecode.FORBIDDEN,
+-            (dav_namespace, "number-of-matches-within-limits")
++            davxml.NumberOfMatchesWithinLimits()
+         ))
+ 
+     yield MultiStatusResponse(responses)

Modified: CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	2008-12-08 18:54:31 UTC (rev 3475)
@@ -57,7 +57,7 @@
 +                        # Check size of results is within limit
 +                        matchcount += 1
 +                        if matchcount > max_number_of_matches:
-+                            raise NumberOfMatchesWithinLimits
++                            raise NumberOfMatchesWithinLimits(max_number_of_matches)
 +        
 +                        d = waitForDeferred(prop_common.responseForHref(
 +                            request,
@@ -124,7 +124,7 @@
 +                                # Check size of results is within limit
 +                                matchcount += 1
 +                                if matchcount > max_number_of_matches:
-+                                    raise NumberOfMatchesWithinLimits
++                                    raise NumberOfMatchesWithinLimits(max_number_of_matches)
 +    
 +                                d = waitForDeferred(prop_common.responseForHref(
 +                                    request,
@@ -139,3 +139,12 @@
                  except HTTPError:
                      # Just ignore a failure to access the property. We treat this like a property that does not exist
                      # or does not match the principal.
+@@ -162,7 +190,7 @@
+         log.err("Too many matching components in principal-match report")
+         raise HTTPError(ErrorResponse(
+             responsecode.FORBIDDEN,
+-            (dav_namespace, "number-of-matches-within-limits")
++            davxml.NumberOfMatchesWithinLimits()
+         ))
+ 
+     yield MultiStatusResponse(responses)

Added: CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/limits-3472/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	2008-12-08 18:54:31 UTC (rev 3475)
@@ -0,0 +1,22 @@
+Index: twisted/web2/dav/method/report_principal_property_search.py
+===================================================================
+--- twisted/web2/dav/method/report_principal_property_search.py	(revision 19773)
++++ twisted/web2/dav/method/report_principal_property_search.py	(working copy)
+@@ -166,7 +166,7 @@
+                         # Check size of results is within limit
+                         matchcount += 1
+                         if matchcount > max_number_of_matches:
+-                            raise NumberOfMatchesWithinLimits
++                            raise NumberOfMatchesWithinLimits(max_number_of_matches)
+     
+                         d = waitForDeferred(prop_common.responseForHref(
+                             request,
+@@ -183,7 +183,7 @@
+         log.err("Too many matching components in prinicpal-property-search report")
+         raise HTTPError(ErrorResponse(
+             responsecode.FORBIDDEN,
+-            (dav_namespace, "number-of-matches-within-limits")
++            davxml.NumberOfMatchesWithinLimits()
+         ))
+ 
+     yield MultiStatusResponse(responses)

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/customxml.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/customxml.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -316,6 +316,30 @@
     protected = True
     hidden = True
 
+davxml.PrincipalPropertySearch.allowed_children[(calendarserver_namespace, "limit")] = (0, 1)
+davxml.PrincipalPropertySearch.allowed_attributes["type"] = False
+davxml.Match.allowed_attributes = {
+    "caseless": False,
+    "match-type": False,
+}
+
+class Limit (davxml.WebDAVElement):
+    """
+    Client supplied limit for reports.
+    """
+    namespace = calendarserver_namespace
+    name = "limit"
+    allowed_children = {
+        (calendarserver_namespace, "nresults" )  : (1, 1),
+    }
+
+class NResults (davxml.WebDAVTextElement):
+    """
+    Number of results limit.
+    """
+    namespace = calendarserver_namespace
+    name = "nresults"
+
 class FirstNameProperty (davxml.WebDAVTextElement):
     """
     A property representing first name of a principal

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/directory/xmlfile.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/directory/xmlfile.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -86,7 +86,7 @@
 
     def _entriesForRecordType(self, recordType):
         try:
-            for entry in self._accounts()[recordType].itervalues():
+            for entry in sorted(self._accounts()[recordType].itervalues(), key=lambda x: x.shortName):
                 yield entry.shortName, entry
         except KeyError:
             return

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/extensions.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/extensions.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2008 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.
@@ -35,7 +35,7 @@
 import time
 
 from twisted.internet.defer import succeed, DeferredList, inlineCallbacks, returnValue
-from twisted.internet.defer import maybeDeferred, deferredGenerator, waitForDeferred
+from twisted.internet.defer import maybeDeferred
 from twisted.web2 import responsecode
 from twisted.web2.http import HTTPError, Response, RedirectResponse
 from twisted.web2.http import StatusResponse
@@ -44,16 +44,16 @@
 from twisted.web2.static import MetaDataMixin
 from twisted.web2.dav import davxml
 from twisted.web2.dav.davxml import dav_namespace
-from twisted.web2.dav.http import ErrorResponse, MultiStatusResponse
+from twisted.web2.dav.http import MultiStatusResponse
 from twisted.web2.dav.static import DAVFile as SuperDAVFile
 from twisted.web2.dav.resource import DAVResource as SuperDAVResource
 from twisted.web2.dav.resource import DAVPrincipalResource as SuperDAVPrincipalResource
 from twisted.web2.dav.util import joinURL
 from twisted.web2.dav.xattrprops import xattrPropertyStore
 from twisted.web2.dav.method import prop_common
-from twisted.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twisted.web2.dav.method.report import max_number_of_matches
 
+from twistedcaldav.customxml import calendarserver_namespace, NResults
 from twistedcaldav.log import Logger, LoggingMixIn
 from twistedcaldav.util import submodule, Alternator, printTracebacks
 from twistedcaldav.directory.sudo import SudoDirectoryService
@@ -206,39 +206,44 @@
 
 class DirectoryPrincipalPropertySearchMixIn(object):
 
-    @deferredGenerator
+    @inlineCallbacks
     def report_DAV__principal_property_search(self, request,
         principal_property_search):
         """
         Generate a principal-property-search REPORT. (RFC 3744, section 9.4)
-        Overrides twisted implementation, targetting only directory-enabled
+        Overrides twisted implementation, targeting only directory-enabled
         searching.
         """
         # Verify root element
-        if not isinstance(principal_property_search,
-            davxml.PrincipalPropertySearch):
-            raise ValueError("%s expected as root element, not %s." %
-                (davxml.PrincipalPropertySearch.sname(),
-                principal_property_search.sname()))
+        if not isinstance(principal_property_search, davxml.PrincipalPropertySearch):
+            msg = "%s expected as root element, not %s." % (davxml.PrincipalPropertySearch.sname(), principal_property_search.sname())
+            log.warn(msg)
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
 
         # Should we AND (the default) or OR (if test="anyof")?
         testMode = principal_property_search.attributes.get("test", "allof")
         if testMode not in ("allof", "anyof"):
-            raise ValueError("Unknown value for test attribute: %s" %
-                (testMode,))
+            msg = "Bad XML: unknown value for test attribute: %s" % (testMode,)
+            log.warn(msg)
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
         operand = "and" if testMode == "allof" else "or"
 
         # Are we narrowing results down to a single CUTYPE?
         cuType = principal_property_search.attributes.get("type", None)
         if cuType not in ("INDIVIDUAL", "GROUP", "RESOURCE", "ROOM", None):
-            raise ValueError("Unknown value for type attribute: %s" % (cuType,))
+            msg = "Bad XML: unknown value for type attribute: %s" % (cuType,)
+            log.warn(msg)
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
 
         # Only handle Depth: 0
         depth = request.headers.getHeader("depth", "0")
         if depth != "0":
-            log.err("Error in prinicpal-property-search REPORT, Depth set to %s" % (depth,))
+            log.err("Error in principal-property-search REPORT, Depth set to %s" % (depth,))
             raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
 
+        # Get any limit value from xml
+        clientLimit = None
+
         # Get a single DAV:prop element from the REPORT request body
         propertiesForResource = None
         propElement = None
@@ -248,9 +253,11 @@
             if child.qname() == (dav_namespace, "prop"):
                 propertiesForResource = prop_common.propertyListForResource
                 propElement = child
+
             elif child.qname() == (dav_namespace,
                 "apply-to-principal-collection-set"):
                 applyTo = True
+
             elif child.qname() == (dav_namespace, "property-search"):
                 props = child.childOfType(davxml.PropertyContainer)
                 props.removeWhitespaceNodes()
@@ -258,106 +265,111 @@
                 match = child.childOfType(davxml.Match)
                 caseless = match.attributes.get("caseless", "yes")
                 if caseless not in ("yes", "no"):
-                    raise ValueError("Unknown value for caseless attribute: %s"
-                        % (caseless,))
-                caseless = True if caseless == "yes" else False
+                    msg = "Bad XML: unknown value for caseless attribute: %s" % (caseless,)
+                    log.warn(msg)
+                    raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
+                caseless = (caseless == "yes")
                 matchType = match.attributes.get("match-type", "contains")
                 if matchType not in ("starts-with", "contains"):
-                    raise ValueError("Unknown value for match-type attribute: %s" %
-                        (matchType,))
+                    msg = "Bad XML: unknown value for match-type attribute: %s" % (matchType,)
+                    log.warn(msg)
+                    raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
 
-                propertySearches.append((props.children, str(match),
-                    caseless, matchType))
+                propertySearches.append((props.children, str(match), caseless, matchType))
 
+            elif child.qname() == (calendarserver_namespace, "limit"):
+                try:
+                    nresults = child.childOfType(NResults)
+                    clientLimit = int(str(nresults))
+                except (TypeError, ValueError,):
+                    msg = "Bad XML: unknown value for <limit> element"
+                    log.warn(msg)
+                    raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
+
         # Run report
-        try:
+        resultsWereLimited = None
+        resources = []
+        if applyTo or not hasattr(self, "directory"):
+            for principalCollection in self.principalCollections():
+                uri = principalCollection.principalCollectionURL()
+                resource = (yield request.locateResource(uri))
+                if resource:
+                    resources.append((resource, uri))
+        else:
+            resources.append((self, request.uri))
 
-            resources = []
-            if applyTo or not hasattr(self, "directory"):
-                for principalCollection in self.principalCollections():
-                    uri = principalCollection.principalCollectionURL()
-                    resource = waitForDeferred(request.locateResource(uri))
-                    yield resource
-                    resource = resource.getResult()
-                    if resource:
-                        resources.append((resource, uri))
-            else:
-                resources.append((self, request.uri))
+        # We need to access a directory service
+        principalCollection = resources[0][0]
+        if not hasattr(principalCollection, "directory"):
+            # Use Twisted's implementation instead in this case
+            result = (yield super(DirectoryPrincipalPropertySearchMixIn, self).report_DAV__principal_property_search(request, principal_property_search))
+            returnValue(result)
 
-            # We need to access a directory service
-            principalCollection = resources[0][0]
-            if not hasattr(principalCollection, "directory"):
-                # Use Twisted's implementation instead in this case
-                d = waitForDeferred(super(DirectoryPrincipalPropertySearchMixIn, self).report_DAV__principal_property_search(request, principal_property_search))
-                yield d
-                yield d.getResult()
-                return
+        dir = principalCollection.directory
 
-            dir = principalCollection.directory
+        # See if we can take advantage of the directory
+        fields = []
+        nonDirectorySearches = []
+        for props, match, caseless, matchType in propertySearches:
+            nonDirectoryProps = []
+            for prop in props:
+                fieldName, match = principalCollection.propertyToField(
+                    prop, match)
+                if fieldName:
+                    fields.append((fieldName, match, caseless, matchType))
+                else:
+                    nonDirectoryProps.append(prop)
+            if nonDirectoryProps:
+                nonDirectorySearches.append((nonDirectoryProps, match,
+                    caseless, matchType))
 
-            # See if we can take advantage of the directory
-            fields = []
-            nonDirectorySearches = []
-            for props, match, caseless, matchType in propertySearches:
-                nonDirectoryProps = []
-                for prop in props:
-                    fieldName, match = principalCollection.propertyToField(
-                        prop, match)
-                    if fieldName:
-                        fields.append((fieldName, match, caseless, matchType))
-                    else:
-                        nonDirectoryProps.append(prop)
-                if nonDirectoryProps:
-                    nonDirectorySearches.append((nonDirectoryProps, match,
-                        caseless, matchType))
+        matchingResources = []
+        matchcount = 0
 
-            matchingResources = []
-            matchcount = 0
+        # nonDirectorySearches are ignored
+        if fields:
 
-            # nonDirectorySearches are ignored
+            records = (yield dir.recordsMatchingFieldsWithCUType(fields,
+                operand=operand, cuType=cuType))
 
-            if fields:
+            for record in records:
+                resource = principalCollection.principalForRecord(record)
+                matchingResources.append(resource)
 
-                d = waitForDeferred(dir.recordsMatchingFieldsWithCUType(fields,
-                    operand=operand, cuType=cuType))
-                yield d
-                records = d.getResult()
+                # We've determined this is a matching resource
+                matchcount += 1
+                if clientLimit is not None and matchcount >= clientLimit:
+                    resultsWereLimited = ("client", matchcount)
+                    break
+                if matchcount >= max_number_of_matches:
+                    resultsWereLimited = ("server", matchcount)
+                    break
 
-                for record in records:
-                    resource = principalCollection.principalForRecord(record)
+        # Generate the response
+        responses = []
+        for resource in matchingResources:
+            url = resource.url()
+            yield prop_common.responseForHref(
+                request,
+                responses,
+                davxml.HRef.fromString(url),
+                resource,
+                propertiesForResource,
+                propElement
+            )
 
-                    # We've determined this is a matching resource
-                    matchcount += 1
-                    if matchcount > max_number_of_matches:
-                        raise NumberOfMatchesWithinLimits
-                    matchingResources.append(resource)
-
-            # Generate the response
-            responses = []
-            for resource in matchingResources:
-                url = resource.url()
-                d = waitForDeferred(prop_common.responseForHref(
-                    request,
-                    responses,
-                    davxml.HRef.fromString(url),
-                    resource,
-                    propertiesForResource,
-                    propElement
-                ))
-                yield d
-                d.getResult()
-
-
-        except NumberOfMatchesWithinLimits:
-            log.err("Too many matching components in prinicpal-property-search report")
-            raise HTTPError(ErrorResponse(
-                responsecode.FORBIDDEN,
-                (dav_namespace, "number-of-matches-within-limits")
+        if resultsWereLimited is not None:
+            if resultsWereLimited[0] == "server":
+                log.err("Too many matching resources in principal-property-search report")
+            responses.append(davxml.StatusResponse(
+                davxml.HRef.fromString(request.uri),
+                davxml.Status.fromResponseCode(responsecode.INSUFFICIENT_STORAGE_SPACE),
+                davxml.Error(davxml.NumberOfMatchesWithinLimits()),
+                davxml.ResponseDescription("Results limited by %s at %d" % resultsWereLimited),
             ))
+        returnValue(MultiStatusResponse(responses))
 
-        yield MultiStatusResponse(responses)
 
-
 class DAVResource (DirectoryPrincipalPropertySearchMixIn, SudoSACLMixin, SuperDAVResource, LoggingMixIn):
     """
     Extended L{twisted.web2.dav.resource.DAVResource} implementation.
@@ -598,7 +610,7 @@
         return super(DAVFile, self).readProperty(property, request)
 
     def resourceType(self):
-        # Allow live property to be overriden by dead property
+        # Allow live property to be overridden by dead property
         if self.deadProperties().contains((dav_namespace, "resourcetype")):
             return self.deadProperties().get((dav_namespace, "resourcetype"))
         if self.isCollection():
@@ -901,7 +913,7 @@
     """
     def __init__(self, code, element):
         """
-        @param xml_responses: an interable of davxml.Response objects.
+        @param xml_responses: an iterable of davxml.Response objects.
         """
         Response.__init__(self, code, stream=element.toxml())
         self.headers.setHeader("content-type", MimeType("text", "xml"))
@@ -933,7 +945,7 @@
                 self.log_debug("Cache miss: %r, %r, %r" % (self, self.resource.fp.path, qname))
                 try:
                     property = super(CachingXattrPropertyStore, self).get(qname)
-                except HTTPError, e:
+                except HTTPError:
                     self.log_debug("Cache double miss: %r, %r, %r" % (self, self.resource.fp.path, qname))
                     del cache[qname]
                     raise PropertyNotFoundError(qname)

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,6 +1,5 @@
-# -*- test-case-name: twisted.web2.dav.test.test_report -*-
 ##
-# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2005-2008 Apple Computer, Inc. All rights reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -42,11 +41,6 @@
 
 log = Logger()
 
-max_number_of_matches = 500
-
-class NumberOfMatchesWithinLimits(Exception):
-    pass
-
 @inlineCallbacks
 def http_REPORT(self, request):
     """

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_calquery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_calquery.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_calquery.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -132,7 +132,7 @@
                 # Check size of results is within limit
                 matchcount[0] += 1
                 if matchcount[0] > max_number_of_results:
-                    raise NumberOfMatchesWithinLimits
+                    raise NumberOfMatchesWithinLimits(max_number_of_results)
 
                 if name:
                     href = davxml.HRef.fromString(joinURL(uri, name))
@@ -223,6 +223,6 @@
         yield report_common.applyToCalendarCollections(self, request, request.uri, depth, doQuery, (davxml.Read(),))
     except NumberOfMatchesWithinLimits:
         log.err("Too many matching components in calendar-query report")
-        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "number-of-matches-within-limits")))
+        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, davxml.NumberOfMatchesWithinLimits()))
     
     returnValue(MultiStatusResponse(responses))

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_common.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_common.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -378,7 +378,7 @@
             # Check size of results is within limit
             matchtotal += 1
             if matchtotal > max_number_of_matches:
-                raise NumberOfMatchesWithinLimits
+                raise NumberOfMatchesWithinLimits(max_number_of_results)
 
             if calendar.mainType() == "VEVENT":
                 processEventFreeBusy(calendar, fbinfo, timerange, tzinfo)

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_freebusy.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_freebusy.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_freebusy.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -24,6 +24,7 @@
 from twisted.web2 import responsecode
 from twisted.web2.dav.element.base import dav_namespace
 from twisted.web2.dav.http import ErrorResponse
+from twisted.web2.dav import davxml
 from twisted.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twisted.web2.http import HTTPError, Response, StatusResponse
 from twisted.web2.http_headers import MimeType
@@ -79,7 +80,7 @@
         yield report_common.applyToCalendarCollections(self, request, request.uri, depth, generateFreeBusyInfo, (caldavxml.ReadFreeBusy(),))
     except NumberOfMatchesWithinLimits:
         log.err("Too many matching components in free-busy report")
-        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "number-of-matches-within-limits")))
+        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, davxml.NumberOfMatchesWithinLimits()))
     
     # Now build a new calendar object with the free busy info we have
     fbcalendar = report_common.buildFreeBusyResult(fbinfo, timerange)

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_multiget.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_multiget.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/method/report_multiget.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -82,7 +82,7 @@
     # Check size of results is within limit
     if len(resources) > max_number_of_multigets:
         log.err("Too many results in multiget report: %d" % len(resources))
-        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "number-of-matches-within-limits")))
+        raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, davxml.NumberOfMatchesWithinLimits()))
 
     """
     Three possibilities exist:

Modified: CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/scheduling/processing.py	2008-12-08 18:35:20 UTC (rev 3474)
+++ CalendarServer/branches/users/cdaboo/limits-3472/twistedcaldav/scheduling/processing.py	2008-12-08 18:54:31 UTC (rev 3475)
@@ -15,17 +15,17 @@
 ##
 
 from hashlib import md5
+from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.web2.dav.fileop import delete
+from twisted.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twisted.web2.dav.util import joinURL
 from twistedcaldav import customxml, caldavxml
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.ical import Property
 from twistedcaldav.log import Logger
 from twistedcaldav.method import report_common
-from twistedcaldav.method.report import NumberOfMatchesWithinLimits
 from twistedcaldav.scheduling.itip import iTipProcessing, iTIPRequestStatus
-from twisted.internet import reactor
 import datetime
 import time
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081208/692ca208/attachment-0001.html>


More information about the calendarserver-changes mailing list