[CalendarServer-changes] [11070] CalendarServer/branches/users/cdaboo/store-scheduling
source_changes at macosforge.org
source_changes at macosforge.org
Fri Apr 19 13:52:47 PDT 2013
Revision: 11070
http://trac.calendarserver.org//changeset/11070
Author: cdaboo at apple.com
Date: 2013-04-19 13:52:47 -0700 (Fri, 19 Apr 2013)
Log Message:
-----------
Checkpoint: initial CDT implicit tests passing.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/delivery.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/delivery.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/implicit.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/itip.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/processing.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/scheduler.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_implicit.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_utils.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/icalendarstore.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -2320,11 +2320,11 @@
@inlineCallbacks
- def storeComponent(self, component):
+ def storeComponent(self, component, **kwargs):
try:
if self._newStoreObject:
- yield self._newStoreObject.setComponent(component)
+ yield self._newStoreObject.setComponent(component, **kwargs)
returnValue(NO_CONTENT)
else:
self._newStoreObject = (yield self._newStoreParent.createObjectResourceWithName(
@@ -2631,7 +2631,7 @@
self._parentResource._newStoreObject._txn._authz_uid = authz.record.guid
try:
- response = (yield self.storeComponent(component))
+ response = (yield self.storeComponent(component, smart_merge=schedule_tag_match))
except ResourceDeletedError:
# This is OK - it just means the server deleted the resource during the PUT. We make it look
# like the PUT succeeded.
@@ -2675,6 +2675,21 @@
raise
+ @requiresPermissions(fromParent=[davxml.Unbind()])
+ def http_DELETE(self, request):
+ """
+ Override http_DELETE to do schedule tag behavior.
+ """
+ if not self.exists():
+ log.debug("Resource not found: %s" % (self,))
+ raise HTTPError(NOT_FOUND)
+
+ # Do schedule tag check
+ self.validIfScheduleMatch(request)
+
+ return self.storeRemove(request)
+
+
@requiresPermissions(davxml.WriteContent())
@inlineCallbacks
def POST_handler_attachment(self, request, action):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/delivery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/delivery.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/delivery.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -150,7 +150,7 @@
if store_inbox:
# Copy calendar to inbox
try:
- yield recipient.inbox._createCalendarObjectWithNameInternal(name, self.scheduler.calendar, ComponentUpdateState.INBOX)
+ child = yield recipient.inbox._createCalendarObjectWithNameInternal(name, self.scheduler.calendar, ComponentUpdateState.INBOX)
except Exception as e:
# FIXME: Bare except
log.err("Could not store data in Inbox : %s %s" % (recipient.inbox, e,))
@@ -165,9 +165,9 @@
returnValue(False)
else:
# Store CS:schedule-changes property if present
- if changes:
- props = recipient.inbox.properties()
- props[PropertyName(*changes.qname())] = changes
+ if changes is not None:
+ props = child.properties()
+ props[PropertyName.fromElement(changes)] = changes
responses.add(recipient.cuaddr, responsecode.OK, reqstatus=iTIPRequestStatus.MESSAGE_DELIVERED)
if autoprocessed:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -24,7 +24,7 @@
class CalDAV (twistedcaldav.test.util.TestCase):
"""
- twistedcaldav.scheduling.caldav tests
+ txdav.caldav.datastore.scheduling.caldav tests
"""
@inlineCallbacks
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/delivery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/delivery.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/delivery.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -1,4 +1,4 @@
-# -*- test-case-name: twistedcaldav.scheduling.test.test_imip -*-
+# -*- test-case-name: txdav.caldav.datastore.scheduling.test.test_imip -*-
##
# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
#
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -26,9 +26,9 @@
from twistedcaldav.directory import augment
from twistedcaldav.directory.xmlfile import XMLDirectoryService
from twistedcaldav.ical import Component
-from twistedcaldav.scheduling.imip.outbound import IMIPInvitationWork
-from twistedcaldav.scheduling.imip.outbound import MailSender
-from twistedcaldav.scheduling.imip.outbound import StringFormatTemplateLoader
+from txdav.caldav.datastore.scheduling.imip.outbound import IMIPInvitationWork
+from txdav.caldav.datastore.scheduling.imip.outbound import MailSender
+from txdav.caldav.datastore.scheduling.imip.outbound import StringFormatTemplateLoader
from twistedcaldav.test.util import TestCase, xmlFile, augmentsFile
from txdav.common.datastore.test.util import buildStore
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/implicit.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/implicit.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -61,6 +61,7 @@
self.return_status = ImplicitScheduler.STATUS_OK
self.logItems = {}
self.allowed_to_schedule = True
+ self.suppress_refresh = False
NotAllowedExceptionDetails = collections.namedtuple("NotAllowedExceptionDetails", ("type", "args", "kwargs",))
@@ -326,19 +327,19 @@
@inlineCallbacks
- def refreshAllAttendeesExceptSome(self, request, resource, except_attendees=(), only_attendees=None):
+ def refreshAllAttendeesExceptSome(self, txn, resource, except_attendees=(), only_attendees=None):
"""
Refresh the iCalendar data for all attendees except the one specified in attendees.
"""
self.txn = resource._txn
- self.request = request
self.resource = resource
- self.calendar = (yield self.resource.iCalendarForUser(self.request))
+ self.calendar_home = self.resource.parentCollection().ownerHome()
+ self.calendar_owner = self.calendar_home.uid()
+ self.calendar = (yield self.resource.componentForUser())
self.state = "organizer"
self.action = "modify"
- self.calendar_owner = None
self.internal_request = True
self.except_attendees = except_attendees
self.only_refresh_attendees = only_attendees
@@ -347,7 +348,7 @@
# Get some useful information from the calendar
yield self.extractCalendarData()
- self.organizerPrincipal = self.home.directoryService().recordWithCalendarUserAddress(self.organizer)
+ self.organizerPrincipal = self.calendar_home.directoryService().recordWithCalendarUserAddress(self.organizer)
self.organizerAddress = (yield addressmapping.mapper.getCalendarUser(self.organizer, self.organizerPrincipal))
# Originator is the organizer in this case
@@ -355,38 +356,38 @@
self.originator = self.organizer
# We want to suppress chatty iMIP messages when other attendees reply
- self.request.suppressRefresh = False
+ self.suppress_refresh = False
for attendee in self.calendar.getAllAttendeeProperties():
if attendee.parameterValue("PARTSTAT", "NEEDS-ACTION").upper() == "NEEDS-ACTION":
- self.request.suppressRefresh = True
+ self.suppress_refresh = True
- if hasattr(self.request, "doing_attendee_refresh"):
- self.request.doing_attendee_refresh += 1
+ if hasattr(self.txn, "doing_attendee_refresh"):
+ self.txn.doing_attendee_refresh += 1
else:
- self.request.doing_attendee_refresh = 1
+ self.txn.doing_attendee_refresh = 1
try:
refreshCount = (yield self.processRequests())
finally:
- self.request.doing_attendee_refresh -= 1
- if self.request.doing_attendee_refresh == 0:
- delattr(self.request, "doing_attendee_refresh")
+ self.txn.doing_attendee_refresh -= 1
+ if self.txn.doing_attendee_refresh == 0:
+ delattr(self.txn, "doing_attendee_refresh")
if refreshCount:
self.logItems["itip.refreshes"] = refreshCount
@inlineCallbacks
- def sendAttendeeReply(self, request, resource, calendar, attendee):
+ def sendAttendeeReply(self, txn, resource, calendar, attendee):
- self.txn = resource._txn
- self.request = request
+ self.txn = txn
self.resource = resource
+ self.calendar_home = self.resource.parentCollection().ownerHome()
+ self.calendar_owner = self.calendar_home.uid()
self.calendar = calendar
self.action = "modify"
self.state = "attendee"
- self.calendar_owner = None
self.internal_request = True
self.changed_rids = None
@@ -940,7 +941,7 @@
# Do the PUT processing
log.info("Implicit CANCEL - organizer: '%s' to attendee: '%s', UID: '%s', RIDs: '%s'" % (self.organizer, attendee, self.uid, rids))
- response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True))
+ response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True, suppress_refresh=self.suppress_refresh))
self.handleSchedulingResponse(response, True)
count += 1
@@ -983,7 +984,7 @@
# Do the PUT processing
log.info("Implicit REQUEST - organizer: '%s' to attendee: '%s', UID: '%s'" % (self.organizer, attendee, self.uid,))
- response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True))
+ response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True, suppress_refresh=self.suppress_refresh))
self.handleSchedulingResponse(response, True)
count += 1
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/scheduler.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/scheduler.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -37,10 +37,10 @@
from txdav.caldav.datastore.scheduling.ischedule.dkim import DKIMVerifier, \
DKIMVerificationError, DKIMMissingError
from twext.web2.http_headers import MimeType
-from twistedcaldav.scheduling.ischedule.xml import ischedule_namespace
+from txdav.caldav.datastore.scheduling.ischedule.xml import ischedule_namespace
from txdav.xml.base import WebDAVUnknownElement
-from twistedcaldav.scheduling.ischedule.utils import getIPsFromHost
-from twistedcaldav.scheduling.ischedule import xml
+from txdav.caldav.datastore.scheduling.ischedule.utils import getIPsFromHost
+from txdav.caldav.datastore.scheduling.ischedule import xml
from twistedcaldav.ical import normalizeCUAddress
"""
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -18,13 +18,13 @@
from twisted.internet.defer import inlineCallbacks
from twisted.python.modules import getModule
from twistedcaldav.config import config
-from twistedcaldav.scheduling.ischedule import utils
+from txdav.caldav.datastore.scheduling.ischedule import utils
from twisted.names import client
from txdav.caldav.datastore.scheduling.ischedule.delivery import ScheduleViaISchedule
class CalDAV (twistedcaldav.test.util.TestCase):
"""
- twistedcaldav.scheduling.caldav tests
+ txdav.caldav.datastore.scheduling.caldav tests
"""
def tearDown(self):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -16,7 +16,7 @@
from twisted.internet.defer import inlineCallbacks
from twistedcaldav.config import config
-from twistedcaldav.scheduling.ischedule import utils
+from txdav.caldav.datastore.scheduling.ischedule import utils
from twistedcaldav.test.util import TestCase
from twisted.python.modules import getModule
from twisted.names.authority import BindAuthority
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/itip.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/itip.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -103,7 +103,7 @@
return None, None
# Merge Organizer data with Attendee's own changes (VALARMs, Comment only for now).
- from twistedcaldav.scheduling.icaldiff import iCalDiff
+ from txdav.caldav.datastore.scheduling.icaldiff import iCalDiff
rids = iCalDiff(calendar, itip_message, False).whatIsDifferent()
# Different behavior depending on whether a master component is present or not
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/processing.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/processing.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -44,6 +44,7 @@
import uuid
from txdav.caldav.icalendarstore import ComponentUpdateState, \
ComponentRemoveState
+from twext.enterprise.locking import NamedLock
"""
CalDAV implicit processing.
@@ -199,6 +200,8 @@
# Update the organizer's copy of the event
log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:REPLY, UID: '%s' - updating event" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
self.organizer_calendar_resource = (yield self.writeCalendarResource(None, self.recipient_calendar_resource, self.recipient_calendar))
+ self.organizer_uid = self.organizer_calendar_resource.parentCollection().ownerHome().uid()
+ self.organizer_calendar_resource_id = self.organizer_calendar_resource.id()
organizer = self.recipient_calendar.getOrganizer()
@@ -323,10 +326,10 @@
@type only_attendees: C{tuple}
"""
log.debug("ImplicitProcessing - refreshing UID: '%s', Attendees: %s" % (self.uid, ", ".join(only_attendees) if only_attendees else "all"))
- from twistedcaldav.scheduling.implicit import ImplicitScheduler
+ from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler
scheduler = ImplicitScheduler()
yield scheduler.refreshAllAttendeesExceptSome(
- self.request,
+ self.txn,
organizer_resource,
exclude_attendees,
only_attendees=only_attendees,
@@ -343,44 +346,30 @@
@type attendeesToProcess: C{list}
"""
- # We need to get the UID lock for implicit processing whilst we send the auto-reply
- # as the Organizer processing will attempt to write out data to other attendees to
- # refresh them. To prevent a race we need a lock.
- uidlock = MemcacheLock(
- "ImplicitUIDLock",
- self.uid,
- timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
- expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
- )
+ # The original transaction is still around but likely committed at this point, so we need a brand new
+ # transaction to do this work.
+ txn = yield self.txn.store().newTransaction("Delayed attendee refresh for UID: %s" % (self.uid,))
try:
- yield uidlock.acquire()
- except MemcacheLockTimeoutError:
- # Just try again to get the lock
- reactor.callLater(2.0, self._doDelayedRefresh, attendeesToProcess)
- else:
+ # We need to get the UID lock for implicit processing whilst we send the auto-reply
+ # as the Organizer processing will attempt to write out data to other attendees to
+ # refresh them. To prevent a race we need a lock.
+ yield NamedLock.acquire(txn, "ImplicitUIDLock:%s" % (hashlib.md5(self.uid).hexdigest(),))
- # inNewTransaction wipes out the remembered resource<-> URL mappings in the
- # request object but we need to be able to map the actual reply resource to its
- # URL when doing auto-processing, so we have to sneak that mapping back in here.
- txn = yield self.organizer_calendar_resource.inNewTransaction(self.request, label="Delayed attendee refresh")
-
- try:
- organizer_resource = (yield self.request.locateResource(self.organizer_calendar_resource._url))
- if organizer_resource.exists():
- yield self._doRefresh(organizer_resource, only_attendees=attendeesToProcess)
- else:
- log.debug("ImplicitProcessing - skipping refresh of missing UID: '%s'" % (self.uid,))
- except Exception, e:
- log.debug("ImplicitProcessing - refresh exception UID: '%s', %s" % (self.uid, str(e)))
- yield txn.abort()
- except:
- log.debug("ImplicitProcessing - refresh bare exception UID: '%s'" % (self.uid,))
- yield txn.abort()
+ organizer_home = (yield txn.calendarHomeForUID(self.organizer_uid))
+ organizer_resource = (yield organizer_home.objectResourceWithID(self.organizer_calendar_resource_id))
+ if organizer_resource is not None:
+ yield self._doRefresh(organizer_resource, only_attendees=attendeesToProcess)
else:
- yield txn.commit()
- finally:
- yield uidlock.clean()
+ log.debug("ImplicitProcessing - skipping refresh of missing UID: '%s'" % (self.uid,))
+ except Exception, e:
+ log.debug("ImplicitProcessing - refresh exception UID: '%s', %s" % (self.uid, str(e)))
+ yield txn.abort()
+ except:
+ log.debug("ImplicitProcessing - refresh bare exception UID: '%s'" % (self.uid,))
+ yield txn.abort()
+ else:
+ yield txn.commit()
def _enqueueBatchRefresh(self):
@@ -712,9 +701,9 @@
self.request._rememberResource(resource, resource._url)
# Send out a reply
log.debug("ImplicitProcessing - recipient '%s' processing UID: '%s' - auto-reply: %s" % (self.recipient.cuaddr, self.uid, partstat))
- from twistedcaldav.scheduling.implicit import ImplicitScheduler
+ from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler
scheduler = ImplicitScheduler()
- yield scheduler.sendAttendeeReply(self.request, resource, calendar, self.recipient)
+ yield scheduler.sendAttendeeReply(txn, resource, calendar, self.recipient)
except Exception, e:
log.debug("ImplicitProcessing - auto-reply exception UID: '%s', %s" % (self.uid, str(e)))
yield txn.abort()
@@ -947,10 +936,15 @@
Write out the calendar resource (iTIP) message to the specified calendar, either over-writing the named
resource or by creating a new one.
- @param collection: the L{Calendar} for the calendar collection to store the resource in.
- @param resource: the L{CalendarObject} for the resource name to write into, or {None} to write a new resource.
- @param calendar: the L{Component} calendar to write.
- @return: L{Deferred} -> L{CalDAVResource}
+ @param collection: the calendar collection to store the resource in.
+ @type: L{Calendar}
+ @param resource: the resource object to write to, or C{None} to write a new resource.
+ @type: L{CalendarObject}
+ @param calendar: the calendar data to write.
+ @type: L{Component}
+
+ @return: the object resource written to (either the one passed in or a new one)
+ @rtype: L{CalendarObject}
"""
# Create a new name if one was not provided
@@ -960,7 +954,7 @@
newchild = (yield collection._createCalendarObjectWithNameInternal(name, calendar, internal_state))
else:
yield resource._setComponentInternal(calendar, internal_state=internal_state)
- newchild = None
+ newchild = resource
returnValue(newchild)
@@ -1036,16 +1030,16 @@
raise ImplicitProcessorException("5.1;Service unavailable")
# Locate the originator's copy of the event
- calendar_resource, _ignore_name, _ignore_collection, _ignore_uri = (yield getCalendarObjectForRecord(self.request, self.originator.principal, self.uid))
+ calendar_resource, _ignore_name, _ignore_collection, _ignore_uri = (yield getCalendarObjectForRecord(self.txn, self.originator.principal, self.uid))
if not calendar_resource:
raise ImplicitProcessorException("5.1;Service unavailable")
- originator_calendar = (yield calendar_resource.iCalendarForUser(self.request))
+ originator_calendar = (yield calendar_resource.componentForUser(self.originator.principal.uid))
# Get attendee's view of that
originator_calendar.attendeesView((self.recipient.cuaddr,))
# Locate the attendee's copy of the event if it exists.
- recipient_resource, recipient_resource_name, recipient_collection, recipient_collection_uri = (yield getCalendarObjectForRecord(self.request, self.recipient.principal, self.uid))
+ recipient_resource, recipient_resource_name, recipient_collection, recipient_collection_uri = (yield getCalendarObjectForRecord(self.txn, self.recipient.principal, self.uid))
# We only need to fix data that already exists
if recipient_resource:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/scheduler.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/scheduler.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -278,75 +278,6 @@
self.recipients = list(attendees)
- def loadFromRequestHeaders(self):
- """
- Load Originator and Recipient from request headers.
- """
- self.loadOriginatorFromRequestHeaders()
- self.loadRecipientsFromRequestHeaders()
-
-
- def loadOriginatorFromRequestHeaders(self):
- # Must have Originator header
- originator = self.request.headers.getRawHeaders("originator")
- if originator is None or (len(originator) != 1):
- log.err("%s request must have Originator header" % (self.method,))
- raise HTTPError(self.errorResponse(
- responsecode.FORBIDDEN,
- self.errorElements["originator-missing"],
- "Missing originator",
- ))
- else:
- self.originator = originator[0]
-
-
- def loadRecipientsFromRequestHeaders(self):
- # Get list of Recipient headers
- rawRecipients = self.request.headers.getRawHeaders("recipient")
- if rawRecipients is None or (len(rawRecipients) == 0):
- log.err("%s request must have at least one Recipient header" % (self.method,))
- raise HTTPError(self.errorResponse(
- responsecode.FORBIDDEN,
- self.errorElements["recipient-missing"],
- "No recipients",
- ))
-
- # Recipient header may be comma separated list
- self.recipients = []
- for rawRecipient in rawRecipients:
- for r in rawRecipient.split(","):
- r = r.strip()
- if len(r):
- self.recipients.append(r)
-
-
- @inlineCallbacks
- def loadCalendarFromRequest(self):
- # Must be content-type text/calendar
- contentType = self.request.headers.getHeader("content-type")
- if contentType is not None and (contentType.mediaType, contentType.mediaSubtype) != ("text", "calendar"):
- log.err("MIME type %s not allowed in calendar collection" % (contentType,))
- raise HTTPError(self.errorResponse(
- responsecode.FORBIDDEN,
- self.errorElements["invalid-calendar-data-type"],
- "Data is not calendar data",
- ))
-
- # Parse the calendar object from the HTTP request stream
- try:
- self.calendar = (yield Component.fromIStream(self.request.stream))
-
- self.preProcessCalendarData()
- except:
- # FIXME: Bare except
- log.err("Error while handling %s: %s" % (self.method, Failure(),))
- raise HTTPError(self.errorResponse(
- responsecode.FORBIDDEN,
- self.errorElements["invalid-calendar-data"],
- description="Can't parse calendar data"
- ))
-
-
def preProcessCalendarData(self):
"""
After loading calendar data from the request, do some optional processing of it. This method will be
@@ -596,11 +527,11 @@
# Now process partitioned recipients
if partitioned_recipients:
- yield self.generateRemoteSchedulingResponses(partitioned_recipients, responses, freebusy, getattr(self.request, 'doing_attendee_refresh', False))
+ yield self.generateRemoteSchedulingResponses(partitioned_recipients, responses, freebusy, getattr(self.txn, 'doing_attendee_refresh', False))
# Now process other server recipients
if otherserver_recipients:
- yield self.generateRemoteSchedulingResponses(otherserver_recipients, responses, freebusy, getattr(self.request, 'doing_attendee_refresh', False))
+ yield self.generateRemoteSchedulingResponses(otherserver_recipients, responses, freebusy, getattr(self.txn, 'doing_attendee_refresh', False))
# To reduce chatter, we suppress certain messages
if not self.suppress_refresh:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_implicit.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_implicit.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_implicit.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -21,7 +21,7 @@
from twext.web2 import responsecode
from twext.web2.http import HTTPError
-from twisted.internet.defer import succeed, inlineCallbacks
+from twisted.internet.defer import succeed, inlineCallbacks, returnValue
from twisted.trial.unittest import TestCase
from twistedcaldav.ical import Component
@@ -36,6 +36,7 @@
import hashlib
import sys
+from twistedcaldav.config import config
class FakeScheduler(object):
"""
@@ -46,7 +47,7 @@
self.recipients = recipients
- def doSchedulingViaPUT(self, originator, recipients, calendar, internal_request=False):
+ def doSchedulingViaPUT(self, originator, recipients, calendar, internal_request=False, suppress_refresh=False):
self.recipients.extend(recipients)
return succeed(ScheduleResponseQueue("FAKE", responsecode.OK))
@@ -904,6 +905,12 @@
"inbox": {
},
},
+ "user03": {
+ "calendar_1": {
+ },
+ "inbox": {
+ },
+ },
}
@@ -915,6 +922,44 @@
@inlineCallbacks
+ def _createCalendarObject(self, data, user, name):
+ calendar_collection = (yield self.calendarUnderTest(home=user))
+ yield calendar_collection.createCalendarObjectWithName("test.ics", Component.fromString(data))
+ yield self.commit()
+
+
+ @inlineCallbacks
+ def _listCalendarObjects(self, user, collection_name="calendar_1"):
+ collection = (yield self.calendarUnderTest(name=collection_name, home=user))
+ items = (yield collection.listCalendarObjects())
+ yield self.commit()
+ returnValue(items)
+
+
+ @inlineCallbacks
+ def _getCalendarData(self, user, name=None):
+ if name is None:
+ items = (yield self._listCalendarObjects(user))
+ name = items[0]
+
+ calendar_resource = (yield self.calendarObjectUnderTest(name=name, home=user))
+ calendar = (yield calendar_resource.component())
+ yield self.commit()
+ returnValue(str(calendar).replace("\r\n ", ""))
+
+
+ @inlineCallbacks
+ def _setCalendarData(self, data, user, name=None):
+ if name is None:
+ items = (yield self._listCalendarObjects(user))
+ name = items[0]
+
+ calendar_resource = (yield self.calendarObjectUnderTest(name=name, home=user))
+ yield calendar_resource.setComponent(Component.fromString(data))
+ yield self.commit()
+
+
+ @inlineCallbacks
def test_testImplicitSchedulingPUT_ScheduleState(self):
"""
Test that checkImplicitState() always returns True for any organizer, valid or not.
@@ -1102,21 +1147,17 @@
END:VEVENT
END:VCALENDAR
"""
- calendar_collection = (yield self.calendarUnderTest(home="user01"))
- calendar = Component.fromString(data)
- yield calendar_collection.createCalendarObjectWithName("test.ics", calendar)
- yield self.commit()
+ yield self._createCalendarObject(data, "user01", "test.ics")
- calendar_collection2 = (yield self.calendarUnderTest(home="user02"))
- items = (yield calendar_collection2.listCalendarObjects())
- self.assertEqual(len(items), 1)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
- inbox2 = (yield self.calendarUnderTest(name="inbox", home="user02"))
- items = (yield inbox2.listCalendarObjects())
- self.assertEqual(len(items), 1)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02"))
+ self.assertEqual(len(list2), 1)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 1)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+
@inlineCallbacks
def test_doImplicitScheduling_UpdateOrganizerEvent(self):
"""
@@ -1151,27 +1192,20 @@
END:VEVENT
END:VCALENDAR
"""
- calendar_collection = (yield self.calendarUnderTest(home="user01"))
- calendar = Component.fromString(data1)
- yield calendar_collection.createCalendarObjectWithName("test.ics", calendar)
- yield self.commit()
+ yield self._createCalendarObject(data1, "user01", "test.ics")
- calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01"))
- calendar = Component.fromString(data2)
- yield calendar_resource.setComponent(calendar)
- yield self.commit()
+ yield self._setCalendarData(data2, "user01", "test.ics")
- calendar_collection2 = (yield self.calendarUnderTest(home="user02"))
- items = (yield calendar_collection2.listCalendarObjects())
- self.assertEqual(len(items), 1)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
- inbox2 = (yield self.calendarUnderTest(name="inbox", home="user02"))
- items = (yield inbox2.listCalendarObjects())
- self.assertEqual(len(items), 2)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
- self.assertTrue(items[1].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02"))
+ self.assertEqual(len(list2), 1)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 2)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ self.assertTrue(list2[1].startswith(hashlib.md5("12345-67890").hexdigest()))
+
@inlineCallbacks
def test_doImplicitScheduling_DeleteOrganizerEvent(self):
"""
@@ -1192,41 +1226,22 @@
END:VEVENT
END:VCALENDAR
"""
- data2 = """BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:12345-67890
-DTSTAMP:20080601T120000Z
-DTSTART:20080601T130000Z
-DTEND:20080601T140000Z
-ORGANIZER;CN="User 01":mailto:user01 at example.com
-ATTENDEE:mailto:user01 at example.com
-ATTENDEE:mailto:user02 at example.com
-END:VEVENT
-END:VCALENDAR
-"""
- calendar_collection = (yield self.calendarUnderTest(home="user01"))
- calendar = Component.fromString(data1)
- yield calendar_collection.createCalendarObjectWithName("test.ics", calendar)
- yield self.commit()
+ yield self._createCalendarObject(data1, "user01", "test.ics")
calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01"))
- calendar = Component.fromString(data2)
yield calendar_resource.remove()
yield self.commit()
- calendar_collection2 = (yield self.calendarUnderTest(home="user02"))
- items = (yield calendar_collection2.listCalendarObjects())
- self.assertEqual(len(items), 1)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
- inbox2 = (yield self.calendarUnderTest(name="inbox", home="user02"))
- items = (yield inbox2.listCalendarObjects())
- self.assertEqual(len(items), 2)
- self.assertTrue(items[0].startswith(hashlib.md5("12345-67890").hexdigest()))
- self.assertTrue(items[1].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02"))
+ self.assertEqual(len(list2), 1)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 2)
+ self.assertTrue(list2[0].startswith(hashlib.md5("12345-67890").hexdigest()))
+ self.assertTrue(list2[1].startswith(hashlib.md5("12345-67890").hexdigest()))
+
@inlineCallbacks
def test_doImplicitScheduling_AttendeeEventNoOrganizerEvent(self):
"""
@@ -1247,26 +1262,19 @@
END:VEVENT
END:VCALENDAR
"""
- calendar_collection = (yield self.calendarUnderTest(home="user02"))
- calendar = Component.fromString(data)
try:
- yield calendar_collection.createCalendarObjectWithName("test.ics", calendar)
+ yield self._createCalendarObject(data, "user02", "test.ics")
except AttendeeAllowedError:
pass
except:
self.fail("Wrong exception raised: %s" % (sys.exc_info()[0].__name__,))
else:
self.fail("Exception not raised")
- yield self.commit()
- calendar_collection = (yield self.calendarUnderTest(home="user02"))
- calendar = Component.fromString(data)
+ list1 = (yield self._listCalendarObjects("user01", "inbox"))
+ self.assertEqual(len(list1), 0)
- inbox1 = (yield self.calendarUnderTest(name="inbox", home="user01"))
- items = (yield inbox1.listCalendarObjects())
- self.assertEqual(len(items), 0)
-
@inlineCallbacks
def test_doImplicitScheduling_AttendeeReply(self):
"""
@@ -1301,32 +1309,101 @@
END:VEVENT
END:VCALENDAR
"""
- calendar_collection = (yield self.calendarUnderTest(home="user01"))
- calendar1 = Component.fromString(data1)
- yield calendar_collection.createCalendarObjectWithName("test.ics", calendar1)
- yield self.commit()
+ yield self._createCalendarObject(data1, "user01", "test.ics")
- calendar_resource1 = (yield self.calendarObjectUnderTest(name="test.ics", home="user01"))
- calendar1 = (yield calendar_resource1.component())
- self.assertTrue("SCHEDULE-STATUS=1.2" in str(calendar1).replace("\r\n ", ""))
+ calendar1 = (yield self._getCalendarData("user01", "test.ics"))
+ self.assertTrue("SCHEDULE-STATUS=1.2" in calendar1)
- inbox2 = (yield self.calendarUnderTest(name="inbox", home="user02"))
- items = (yield inbox2.listCalendarObjects())
- self.assertEqual(len(items), 1)
- yield self.commit()
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 1)
- calendar_collection2 = (yield self.calendarUnderTest(home="user02"))
- items = (yield calendar_collection2.listCalendarObjects())
- calendar_resource2 = (yield self.calendarObjectUnderTest(name=items[0], home="user02",))
- calendar2 = Component.fromString(data2)
- yield calendar_resource2.setComponent(calendar2)
- yield self.commit()
+ yield self._setCalendarData(data2, "user02")
- inbox1 = (yield self.calendarUnderTest(name="inbox", home="user01"))
- items = (yield inbox1.listCalendarObjects())
- self.assertEqual(len(items), 1)
+ list1 = (yield self._listCalendarObjects("user01", "inbox"))
+ self.assertEqual(len(list1), 1)
- calendar_resource1 = (yield self.calendarObjectUnderTest(name="test.ics", home="user01"))
- calendar1 = (yield calendar_resource1.component())
- self.assertTrue("SCHEDULE-STATUS=2.0" in str(calendar1).replace("\r\n ", ""))
- self.assertTrue("PARTSTAT=ACCEPTED" in str(calendar1).replace("\r\n ", ""))
+ calendar1 = (yield self._getCalendarData("user01", "test.ics"))
+ self.assertTrue("SCHEDULE-STATUS=2.0" in calendar1)
+ self.assertTrue("PARTSTAT=ACCEPTED" in calendar1)
+
+
+ @inlineCallbacks
+ def test_doImplicitScheduling_refreshAllAttendeesExceptSome(self):
+ """
+ Test that doImplicitScheduling delivers scheduling messages to attendees who can then reply.
+ """
+
+ data1 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-attendee-reply
+DTSTAMP:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+ATTENDEE:mailto:user03 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
+ data2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-attendee-reply
+DTSTAMP:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+ATTENDEE:mailto:user03 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
+
+ # Need refreshes to occur immediately, not via reactor.callLater
+ self.patch(config.Scheduling.Options, "AttendeeRefreshBatch", False)
+
+ yield self._createCalendarObject(data1, "user01", "test.ics")
+
+ list1 = (yield self._listCalendarObjects("user01", "inbox"))
+ self.assertEqual(len(list1), 0)
+
+ calendar1 = (yield self._getCalendarData("user01", "test.ics"))
+ self.assertTrue("SCHEDULE-STATUS=1.2" in calendar1)
+
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 1)
+
+ calendar2 = (yield self._getCalendarData("user02"))
+ self.assertTrue("PARTSTAT=ACCEPTED" not in calendar2)
+
+ list3 = (yield self._listCalendarObjects("user03", "inbox"))
+ self.assertEqual(len(list3), 1)
+
+ calendar3 = (yield self._getCalendarData("user03"))
+ self.assertTrue("PARTSTAT=ACCEPTED" not in calendar3)
+
+ yield self._setCalendarData(data2, "user02")
+
+ list1 = (yield self._listCalendarObjects("user01", "inbox"))
+ self.assertEqual(len(list1), 1)
+
+ calendar1 = (yield self._getCalendarData("user01", "test.ics"))
+ self.assertTrue("SCHEDULE-STATUS=2.0" in calendar1)
+ self.assertTrue("PARTSTAT=ACCEPTED" in calendar1)
+
+ list2 = (yield self._listCalendarObjects("user02", "inbox"))
+ self.assertEqual(len(list2), 1)
+
+ calendar2 = (yield self._getCalendarData("user02"))
+ self.assertTrue("PARTSTAT=ACCEPTED" in calendar2)
+
+ list3 = (yield self._listCalendarObjects("user03", "inbox"))
+ self.assertEqual(len(list3), 1)
+
+ calendar3 = (yield self._getCalendarData("user03"))
+ self.assertTrue("PARTSTAT=ACCEPTED" in calendar3)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_utils.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_utils.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/scheduling/test/test_utils.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -146,7 +146,7 @@
@inlineCallbacks
def test_getCalendarObjectForRecord(self):
"""
- Test that L{twistedcaldav.scheduling.utils.getCalendarObjectForRecord} detects and removes
+ Test that L{txdav.caldav.datastore.scheduling.utils.getCalendarObjectForRecord} detects and removes
resources with duplicate UIDs in the same calendar home.
"""
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -1451,8 +1451,6 @@
"""
# Basic validation
- #TODO: figure out what to do about etag/schedule-tag
- self.validIfScheduleMatch(False, False, internal_state)
# Do validation on external requests
if internal_state == ComponentUpdateState.NORMAL:
@@ -1492,30 +1490,6 @@
self.validAccess(component, inserting, internal_state)
- def validIfScheduleMatch(self, etag_match, schedule_tag, internal_state):
- """
- Check for If-ScheduleTag-Match header behavior.
- """
- # Only when a direct request
- self.schedule_tag_match = False
- if not self.calendar().isInbox() and internal_state == ComponentUpdateState.NORMAL:
- if schedule_tag:
- self._validIfScheduleMatch(self.request)
- self.schedule_tag_match = True
- elif config.Scheduling.CalDAV.ScheduleTagCompatibility:
- # Compatibility with old clients. Policy:
- #
- # 1. If If-Match header is not present, never do smart merge.
- # 2. If If-Match is present and the specified ETag is
- # considered a "weak" match to the current Schedule-Tag,
- # then do smart merge, else reject with a 412.
- #
- # Actually by the time we get here the precondition will
- # already have been tested and found to be OK, so we can just
- # always do smart merge now if If-Match is present.
- self.schedule_tag_match = etag_match is not None
-
-
def validCalendarDataCheck(self, component, inserting):
"""
Check that the calendar data is valid iCalendar.
@@ -1915,9 +1889,9 @@
# from the Organizer then the schedule tag changes.
# Check what kind of processing is going on
- change_scheduletag = internal_state not in (
- ComponentUpdateState.ORGANIZER_ITIP_UPDATE,
- ComponentUpdateState.ATTENDEE_ITIP_REFRESH,
+ change_scheduletag = not (
+ (internal_state == ComponentUpdateState.ORGANIZER_ITIP_UPDATE) or
+ (internal_state == ComponentUpdateState.ATTENDEE_ITIP_UPDATE) and not hasattr(self._txn, "doing_attendee_refresh")
)
if change_scheduletag or not self.scheduleTag:
@@ -1969,17 +1943,17 @@
raise UIDExistsError("UID already exists.")
- def setComponent(self, component, inserting=False):
+ def setComponent(self, component, inserting=False, smart_merge=False):
"""
Public api for storing a component. This will do full data validation checks on the specified component.
Scheduling will be done automatically.
"""
- return self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL)
+ return self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL, smart_merge)
@inlineCallbacks
- def _setComponentInternal(self, component, inserting=False, internal_state=ComponentUpdateState.NORMAL):
+ def _setComponentInternal(self, component, inserting=False, internal_state=ComponentUpdateState.NORMAL, smart_merge=False):
"""
Setting the component internally to the store itself. This will bypass a whole bunch of data consistency checks
on the assumption that those have been done prior to the component data being provided, provided the flag is set.
@@ -1987,6 +1961,7 @@
"""
self._componentChanged = False
+ self.schedule_tag_match = not self.calendar().isInbox() and internal_state == ComponentUpdateState.NORMAL and smart_merge
if internal_state != ComponentUpdateState.RAW:
# Handle all validation operations here.
@@ -2466,14 +2441,6 @@
isinbox = self._calendar.isInbox()
- # Do If-Schedule-Tag-Match behavior first
- # Important: this should only ever be done when storeRemove is called
- # directly as a result of an HTTP DELETE to ensure the proper If-
- # header is used in this test.
- if not isinbox and internal_state == ComponentRemoveState.NORMAL:
- #TODO: figure out what to do about etag/schedule-tag
- self.validIfScheduleMatch(False, False, internal_state)
-
# Pre-flight scheduling operation
scheduler = None
if not isinbox and internal_state == ComponentRemoveState.NORMAL:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/test/test_sql.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -1149,7 +1149,7 @@
home = yield self.transactionUnderTest().calendarHomeWithUID("home_defaults")
self.assertEqual(home._default_events, default_events._resourceID)
self.assertEqual(home._default_tasks, default_tasks._resourceID)
- yield home.removeCalendarWithName("todos")
+ yield home.removeCalendarWithName("calendar_1-vtodo")
yield self.commit()
home = yield self.transactionUnderTest().calendarHomeWithUID("home_defaults")
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/icalendarstore.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/icalendarstore.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -74,10 +74,6 @@
iTIP message. Some validation and implicit scheduling is not done. Schedule-Tag
is changed.
- ATTENDEE_ITIP_REFRESH - the store is an update to an attendee's data caused by processing an incoming
- iTIP message. Some validation and implicit scheduling is not done. Schedule-Tag
- is changed.
-
RAW - store the supplied data as-is without any processing or validation. This is used
for unit testing purposes only.
"""
@@ -86,14 +82,12 @@
INBOX = NamedConstant()
ORGANIZER_ITIP_UPDATE = NamedConstant()
ATTENDEE_ITIP_UPDATE = NamedConstant()
- ATTENDEE_ITIP_REFRESH = NamedConstant()
RAW = NamedConstant()
NORMAL.description = "normal"
INBOX.description = "inbox"
ORGANIZER_ITIP_UPDATE.description = "organizer-update"
ATTENDEE_ITIP_UPDATE.description = "attendee-update"
- ATTENDEE_ITIP_REFRESH.description = "attendee-refresh"
RAW.description = "raw"
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-04-19 18:52:27 UTC (rev 11069)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-04-19 20:52:47 UTC (rev 11070)
@@ -1630,6 +1630,16 @@
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
+ def id(self):
+ """
+ Retrieve the store identifier for this home.
+
+ @return: store identifier.
+ @rtype: C{int}
+ """
+ return self._resourceID
+
+
def uid(self):
"""
Retrieve the unique identifier for this home.
@@ -3380,6 +3390,16 @@
yield self._loadPropertyStore()
+ def id(self):
+ """
+ Retrieve the store identifier for this collection.
+
+ @return: store identifier.
+ @rtype: C{int}
+ """
+ return self._resourceID
+
+
@property
def _txn(self):
return self._home._txn
@@ -4301,6 +4321,16 @@
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
+ def id(self):
+ """
+ Retrieve the store identifier for this object resource.
+
+ @return: store identifier.
+ @rtype: C{int}
+ """
+ return self._resourceID
+
+
@property
def _txn(self):
return self._parentCollection._txn
@@ -4314,6 +4344,10 @@
return self._txn.store().directoryService()
+ def parentCollection(self):
+ return self._parentCollection
+
+
@classmethod
def _selectForUpdateQuery(cls, nowait): #@NoSelf
"""
@@ -4578,6 +4612,16 @@
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
+ def id(self):
+ """
+ Retrieve the store identifier for this collection.
+
+ @return: store identifier.
+ @rtype: C{int}
+ """
+ return self._resourceID
+
+
def name(self):
return "notification"
@@ -4930,6 +4974,16 @@
return self._propertyStore
+ def id(self):
+ """
+ Retrieve the store identifier for this object.
+
+ @return: store identifier.
+ @rtype: C{int}
+ """
+ return self._resourceID
+
+
@property
def _txn(self):
return self._home._txn
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130419/5d052ba1/attachment-0001.html>
More information about the calendarserver-changes
mailing list