[CalendarServer-changes] [5233] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 3 13:08:47 PST 2010


Revision: 5233
          http://trac.macosforge.org/projects/calendarserver/changeset/5233
Author:   sagen at apple.com
Date:     2010-03-03 13:08:46 -0800 (Wed, 03 Mar 2010)
Log Message:
-----------
Adds sidecar task for purging events older than a given number of days

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/sidecar/task.py
    CalendarServer/trunk/calendarserver/util.py
    CalendarServer/trunk/twext/web2/resource.py
    CalendarServer/trunk/twistedcaldav/method/delete_common.py

Added Paths:
-----------
    CalendarServer/trunk/calendarserver/tools/purge.py
    CalendarServer/trunk/calendarserver/tools/test/purge/
    CalendarServer/trunk/calendarserver/tools/test/purge/accounts.xml
    CalendarServer/trunk/calendarserver/tools/test/test_purge.py

Modified: CalendarServer/trunk/calendarserver/sidecar/task.py
===================================================================
--- CalendarServer/trunk/calendarserver/sidecar/task.py	2010-03-03 17:39:59 UTC (rev 5232)
+++ CalendarServer/trunk/calendarserver/sidecar/task.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -23,6 +23,7 @@
 ]
 
 import os
+from datetime import date, timedelta
 
 from zope.interface import implements
 
@@ -31,7 +32,6 @@
 from twisted.internet.reactor import callLater
 from twisted.plugin import IPlugin
 from twisted.python.usage import Options, UsageError
-from twext.web2.http_headers import Headers
 
 from twext.python.log import Logger, LoggingMixIn
 from twext.python.log import logLevelForNamespace, setLogLevelForNamespace
@@ -42,52 +42,11 @@
 from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
 from twistedcaldav.scheduling.scheduler import DirectScheduler
 
-from calendarserver.util import getRootResource
+from calendarserver.util import getRootResource, FakeRequest
+from calendarserver.tools.purge import purgeOldEvents
 
 log = Logger()
 
-class FakeRequest(object):
-
-    def __init__(self, rootResource, method):
-        self.rootResource = rootResource
-        self.method = method
-        self._resourcesByURL = {}
-        self._urlsByResource = {}
-        self.headers = Headers()
-
-    @inlineCallbacks
-    def _getChild(self, resource, segments):
-        if not segments:
-            returnValue(resource)
-
-        child, remaining = (yield resource.locateChild(self, segments))
-        returnValue((yield self._getChild(child, remaining)))
-
-    @inlineCallbacks
-    def locateResource(self, url):
-        url = url.strip("/")
-        segments = url.split("/")
-        resource = (yield self._getChild(self.rootResource, segments))
-        if resource:
-            self._rememberResource(resource, url)
-        returnValue(resource)
-
-    def _rememberResource(self, resource, url):
-        self._resourcesByURL[url] = resource
-        self._urlsByResource[resource] = url
-        return resource
-
-    def urlForResource(self, resource):
-        url = self._urlsByResource.get(resource, None)
-        if url is None:
-            class NoURLForResourceError(RuntimeError):
-                pass
-            raise NoURLForResourceError(resource)
-        return url
-
-    def addResponseFilter(*args, **kwds):
-        pass
-
 @inlineCallbacks
 def processInboxItem(rootResource, directory, inboxFile, inboxItemFile, uuid):
     log.debug("Processing inbox item %s" % (inboxItemFile,))
@@ -192,13 +151,31 @@
         os.remove(self.taskFile)
 
 
+    @inlineCallbacks
+    def task_purgeoldevents(self):
 
+        with open(self.taskFile) as input:
+            try:
+                value = input.read().strip()
+                days = int(value)
+            except ValueError:
+                log.error("Illegal value for purge days: %s" % (value,))
+            else:
+                cutoff = (date.today() -
+                    timedelta(days=days)).strftime("%Y%m%dT000000Z")
+                count = (yield purgeOldEvents(self.service.directory,
+                    self.service.root, cutoff))
+                log.info("Purged %d events" % (count,))
+
+        os.remove(self.taskFile)
+
+
 class CalDAVTaskService(Service):
 
     def __init__(self, root):
         self.root = root
         self.directory = root.directory
-        self.seconds = 30 # How often to check for new tasks in incomingDir
+        self.seconds = 5 # How often to check for new tasks in incomingDir
         self.taskDir = os.path.join(config.DataRoot, "tasks")
         # New task files are placed into "incoming"
         self.incomingDir = os.path.join(self.taskDir, "incoming")

Added: CalendarServer/trunk/calendarserver/tools/purge.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/purge.py	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/tools/purge.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+
+##
+# Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twext.python.log import Logger
+from twistedcaldav import caldavxml
+from twistedcaldav.caldavxml import TimeRange
+from twistedcaldav.ical import Component as iComponent
+from twistedcaldav.method.delete_common import DeleteResource
+from twisted.internet.defer import inlineCallbacks, returnValue
+from calendarserver.util import FakeRequest
+
+log = Logger()
+
+ at inlineCallbacks
+def purgeOldEvents(directory, root, date):
+
+    calendars = root.getChild("calendars")
+    uidsFPath = calendars.fp.child("__uids__")
+
+    records = []
+    if uidsFPath.exists():
+        for firstFPath in uidsFPath.children():
+            if len(firstFPath.basename()) == 2:
+                for secondFPath in firstFPath.children():
+                    if len(secondFPath.basename()) == 2:
+                        for homeFPath in secondFPath.children():
+                            uid = homeFPath.basename()
+                            record = directory.recordWithUID(uid)
+                            if record is not None:
+                                records.append(record)
+
+    log.info("Purging events from %d calendar homes" % (len(records),))
+
+    filter =  caldavxml.Filter(
+          caldavxml.ComponentFilter(
+              caldavxml.ComponentFilter(
+                  TimeRange(end=date,),
+                  name=("VEVENT", "VFREEBUSY", "VAVAILABILITY"),
+              ),
+              name="VCALENDAR",
+           )
+      )
+
+    eventCount = 0
+    for record in records:
+        # Get the calendar home
+        principalCollection = directory.principalCollection
+        principal = principalCollection.principalForRecord(record)
+        calendarHome = principal.calendarHome()
+
+        # For each collection in calendar home...
+        for collName in calendarHome.listChildren():
+            collection = calendarHome.getChild(collName)
+            if collection.isCalendarCollection():
+                # ...use their indexes to figure out which events to purge
+                for name, uid, type in collection.index().indexedSearch(filter):
+                    resource = collection.getChild(name)
+
+                    # indexedSearch also returns endless repeating events, but
+                    # we don't want to purge those
+                    data = resource.iCalendarText()
+                    try:
+                        calendar = iComponent.fromString(data)
+                    except ValueError, e:
+                        log.error("Error parsing %s: %s" % (name, e))
+                        continue
+                    if calendar.isRecurringUnbounded():
+                        continue
+
+                    uri = "/calendars/__uids__/%s/%s/%s" % (
+                        record.uid,
+                        collName,
+                        name
+                    )
+                    try:
+                        response = (yield deleteResource(root, collection,
+                            resource, uri))
+                        eventCount += 1
+                    except Exception, e:
+                        log.error("Failed to purge old event: %s (%s)" %
+                            (uri, e))
+
+    returnValue(eventCount)
+
+
+def deleteResource(root, collection, resource, uri):
+    request = FakeRequest(root, "DELETE", uri)
+
+    # TODO: this seems hacky, even for a stub request:
+    request._rememberResource(resource, uri)
+
+    deleter = DeleteResource(request, resource, uri,
+        collection, "infinity", allowImplicitSchedule=False)
+    return deleter.run()


Property changes on: CalendarServer/trunk/calendarserver/tools/purge.py
___________________________________________________________________
Added: svn:executable
   + *

Added: CalendarServer/trunk/calendarserver/tools/test/purge/accounts.xml
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/purge/accounts.xml	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/tools/test/purge/accounts.xml	2010-03-03 21:08:46 UTC (rev 5233)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE accounts SYSTEM "../../../conf/auth/accounts.dtd">
+
+<accounts realm="/Search">
+  <user>
+    <uid>example</uid>
+    <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
+    <password>example</password>
+    <name>Example User</name>
+    <email-address>example at example.com</email-address>
+  </user>
+</accounts>

Added: CalendarServer/trunk/calendarserver/tools/test/test_purge.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_purge.py	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/tools/test/test_purge.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -0,0 +1,293 @@
+##
+# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+import os
+import zlib
+
+from twext.python.filepath import CachingFilePath as FilePath
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
+
+from twistedcaldav.config import config
+from twistedcaldav.test.util import TestCase
+from calendarserver.util import getRootResource
+from calendarserver.tools.purge import purgeOldEvents
+
+resourceAttr = "WebDAV:{DAV:}resourcetype"
+collectionType = zlib.compress("""<?xml version='1.0' encoding='UTF-8'?>
+<resourcetype xmlns='DAV:'>
+    <collection/>
+    <calendar xmlns='urn:ietf:params:xml:ns:caldav'/>
+</resourcetype>
+""")
+
+
+class PurgeOldEventsTestCase(TestCase):
+
+    def setUp(self):
+        super(PurgeOldEventsTestCase, self).setUp()
+
+        config.DirectoryService.params['xmlFile'] = os.path.join(os.path.dirname(__file__), "purge", "accounts.xml")
+        self.rootResource = getRootResource(config)
+        self.directory = self.rootResource.getDirectory()
+
+    @inlineCallbacks
+    def test_purge(self):
+        before = {
+            "calendars" : {
+                "__uids__" : {
+                    "64" : {
+                        "23" : {
+                            "6423F94A-6B76-4A3A-815B-D52CFD77935D" : {
+                                "calendar": {
+                                    "@xattrs" :
+                                    {
+                                        resourceAttr : collectionType,
+                                    },
+                                    "oneshot.ics": {
+                                        "@contents" : OLD_ICS,
+                                    },
+                                    "repeating.ics": {
+                                        "@contents" : REPEATING_ICS,
+                                    },
+                                    "awhile.ics": {
+                                        "@contents" : REPEATING_AWHILE_ICS,
+                                    },
+                                    "recent.ics": {
+                                        "@contents" : RECENT_ICS,
+                                    },
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        }
+        self.createHierarchy(before, config.DocumentRoot)
+
+        count = (yield purgeOldEvents(self.directory, self.rootResource,
+            "20100303T000000Z"))
+
+        self.assertEquals(count, 2)
+
+        after = {
+            "calendars" : {
+                "__uids__" : {
+                    "64" : {
+                        "23" : {
+                            "6423F94A-6B76-4A3A-815B-D52CFD77935D" : {
+                                "calendar": {
+                                    ".db.sqlite": {
+                                        "@contents" : None, # ignore contents
+                                    },
+                                    "repeating.ics": {
+                                        "@contents" : REPEATING_ICS,
+                                    },
+                                    "recent.ics": {
+                                        "@contents" : RECENT_ICS,
+                                    },
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        }
+        self.assertTrue(self.verifyHierarchy(config.DocumentRoot, after))
+
+
+
+
+OLD_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYMONTH=10;BYDAY=-1SU
+DTSTART:19621028T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYMONTH=4;BYDAY=1SU
+DTSTART:19870405T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:685BC3A1-195A-49B3-926D-388DDACA78A6
+DTEND;TZID=US/Pacific:20000307T151500
+TRANSP:OPAQUE
+SUMMARY:Ancient event
+DTSTART;TZID=US/Pacific:20000307T111500
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+REPEATING_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYMONTH=10;BYDAY=-1SU
+DTSTART:19621028T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYMONTH=4;BYDAY=1SU
+DTSTART:19870405T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20100303T194654Z
+UID:9FDE0E4C-1495-4CAF-863B-F7F0FB15FE8C
+DTEND;TZID=US/Pacific:20000308T151500
+RRULE:FREQ=YEARLY;INTERVAL=1
+TRANSP:OPAQUE
+SUMMARY:Ancient Repeating Endless
+DTSTART;TZID=US/Pacific:20000308T111500
+DTSTAMP:20100303T194710Z
+SEQUENCE:4
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+REPEATING_AWHILE_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYMONTH=10;BYDAY=-1SU
+DTSTART:19621028T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYMONTH=4;BYDAY=1SU
+DTSTART:19870405T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20100303T194716Z
+UID:76236B32-2BC4-4D78-956B-8D42D4086200
+DTEND;TZID=US/Pacific:20000309T151500
+RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=3
+TRANSP:OPAQUE
+SUMMARY:Ancient Repeat Awhile
+DTSTART;TZID=US/Pacific:20000309T111500
+DTSTAMP:20100303T194747Z
+SEQUENCE:6
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+RECENT_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:PDT
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:PST
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20100303T195159Z
+UID:F2F14D94-B944-43D9-8F6F-97F95B2764CA
+DTEND;TZID=US/Pacific:20100304T141500
+TRANSP:OPAQUE
+SUMMARY:Recent
+DTSTART;TZID=US/Pacific:20100304T120000
+DTSTAMP:20100303T195203Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+

Modified: CalendarServer/trunk/calendarserver/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/util.py	2010-03-03 17:39:59 UTC (rev 5232)
+++ CalendarServer/trunk/calendarserver/util.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -17,6 +17,7 @@
 
 __all__ = [
     "getRootResource",
+    "FakeRequest",
 ]
 
 import errno
@@ -26,6 +27,7 @@
 from twisted.python.reflect import namedClass
 from twisted.internet import reactor
 from twisted.cred.portal import Portal
+from twext.web2.http_headers import Headers
 from twext.web2.dav import auth
 from twext.web2.auth.basic import BasicCredentialFactory
 from twext.web2.static import File as FileResource
@@ -50,6 +52,7 @@
 from twistedcaldav.static import TimezoneServiceFile
 from twistedcaldav.static import AddressBookHomeProvisioningFile, DirectoryBackedAddressBookFile
 from twistedcaldav.timezones import TimezoneCache
+from twisted.internet.defer import inlineCallbacks, returnValue
 
 try:
     from twistedcaldav.authkerb import NegotiateCredentialFactory
@@ -429,3 +432,49 @@
 
     return logWrapper
 
+
+
+
+class FakeRequest(object):
+
+    def __init__(self, rootResource, method, path):
+        self.rootResource = rootResource
+        self.method = method
+        self.path = path
+        self._resourcesByURL = {}
+        self._urlsByResource = {}
+        self.headers = Headers()
+
+    @inlineCallbacks
+    def _getChild(self, resource, segments):
+        if not segments:
+            returnValue(resource)
+
+        child, remaining = (yield resource.locateChild(self, segments))
+        returnValue((yield self._getChild(child, remaining)))
+
+    @inlineCallbacks
+    def locateResource(self, url):
+        url = url.strip("/")
+        segments = url.split("/")
+        resource = (yield self._getChild(self.rootResource, segments))
+        if resource:
+            self._rememberResource(resource, url)
+        returnValue(resource)
+
+    def _rememberResource(self, resource, url):
+        self._resourcesByURL[url] = resource
+        self._urlsByResource[resource] = url
+        return resource
+
+    def urlForResource(self, resource):
+        url = self._urlsByResource.get(resource, None)
+        if url is None:
+            class NoURLForResourceError(RuntimeError):
+                pass
+            raise NoURLForResourceError(resource)
+        return url
+
+    def addResponseFilter(*args, **kwds):
+        pass
+

Modified: CalendarServer/trunk/twext/web2/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/resource.py	2010-03-03 17:39:59 UTC (rev 5232)
+++ CalendarServer/trunk/twext/web2/resource.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -312,5 +312,8 @@
             return x.addCallback(lambda data: self.resource)
         return self.resource
 
+    def getChild(self, name):
+        return self.resource.getChild(name)
 
+
 __all__ = ['RenderMixin', 'Resource', 'PostableResource', 'LeafResource', 'WrapperResource']

Modified: CalendarServer/trunk/twistedcaldav/method/delete_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/delete_common.py	2010-03-03 17:39:59 UTC (rev 5232)
+++ CalendarServer/trunk/twistedcaldav/method/delete_common.py	2010-03-03 21:08:46 UTC (rev 5233)
@@ -43,7 +43,8 @@
 
 class DeleteResource(object):
     
-    def __init__(self, request, resource, resource_uri, parent, depth, internal_request=False):
+    def __init__(self, request, resource, resource_uri, parent, depth,
+        internal_request=False, allowImplicitSchedule=True):
         
         self.request = request
         self.resource = resource
@@ -51,6 +52,7 @@
         self.parent = parent
         self.depth = depth
         self.internal_request = internal_request
+        self.allowImplicitSchedule = allowImplicitSchedule
 
     def validIfScheduleMatch(self):
         """
@@ -139,7 +141,7 @@
         
         scheduler = None
         lock = None
-        if not self.internal_request:
+        if not self.internal_request and self.allowImplicitSchedule:
             # Get data we need for implicit scheduling
             calendar = delresource.iCalendar()
             scheduler = ImplicitScheduler()
@@ -164,7 +166,7 @@
                 index.deleteResource(delresource.fp.basename(), newrevision)
     
                 # Do scheduling
-                if scheduler and not self.internal_request:
+                if scheduler and not self.internal_request and self.allowImplicitSchedule:
                     yield scheduler.doImplicitScheduling()
     
         except MemcacheLockTimeoutError:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100303/05558a19/attachment-0001.html>


More information about the calendarserver-changes mailing list