[CalendarServer-changes] [7198] CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 16 14:03:08 PDT 2011


Revision: 7198
          http://trac.macosforge.org/projects/calendarserver/changeset/7198
Author:   cdaboo at apple.com
Date:     2011-03-16 14:03:07 -0700 (Wed, 16 Mar 2011)
Log Message:
-----------
Tweaks to get bulk POST implementation correct.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/caldavxml.py
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/carddavxml.py
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/customxml.py
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/method/put_common.py
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/storebridge.py

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/caldavxml.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/caldavxml.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -340,6 +340,8 @@
         else:
             raise ValueError("Not a calendar: %s" % (calendar,))
 
+    fromTextData = fromCalendar
+
     def __init__(self, *children, **attributes):
         super(CalendarData, self).__init__(*children, **attributes)
 

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/carddavxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/carddavxml.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/carddavxml.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -200,6 +200,8 @@
         """
         return clazz(davxml.PCDATAElement(addressdata))
 
+    fromTextData = fromAddressData
+
     def __init__(self, *children, **attributes):
         super(AddressData, self).__init__(*children, **attributes)
 

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/customxml.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/customxml.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -1063,11 +1063,11 @@
         (mm_namespace, "max-bytes")       : (1, 1),
     }
 
-class MaxResources (davxml.WebDAVTextElement):
+class MaxBulkResources (davxml.WebDAVTextElement):
     namespace = mm_namespace
     name = "max-resources"
 
-class MaxBytes (davxml.WebDAVTextElement):
+class MaxBulkBytes (davxml.WebDAVTextElement):
     namespace = mm_namespace
     name = "max-bytes"
 

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/method/put_common.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/method/put_common.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -815,6 +815,9 @@
     @inlineCallbacks
     def doStore(self, implicit):
 
+        # Stash the current calendar data as we may need to return it
+        self.returndata = str(self.calendar)
+
         # Always do the per-user data merge right before we store
         yield self.mergePerUserData()
 

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/stdconfig.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/stdconfig.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -436,7 +436,10 @@
     "EnableDropBox"           : False, # Calendar Drop Box
     "EnablePrivateEvents"     : False, # Private Events
     "EnableTimezoneService"   : False, # Timezone service
-    "EnableBatchUpload"       : False, # POST batch uploads
+
+    "EnableBatchUpload"       : False,    # POST batch uploads
+    "MaxResourcesBatchUpload" : 100,      # Maximum number of resources in a batch POST
+    "MaxBytesBatchUpload"     : 10485760, # Maximum size of a batch POST (10 MB)
     
     "Sharing": {
         "Enabled"             : False, # Overall on/off switch

Modified: CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/storebridge.py	2011-03-16 19:26:24 UTC (rev 7197)
+++ CalendarServer/branches/users/cdaboo/batchupload-6699/twistedcaldav/storebridge.py	2011-03-16 21:03:07 UTC (rev 7198)
@@ -37,7 +37,8 @@
     DisabledCacheNotifier
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config
-from twistedcaldav.ical import Component as VCalendar, Property as VProperty
+from twistedcaldav.ical import Component as VCalendar, Property as VProperty,\
+    InvalidICalendarDataError
 from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
 from twistedcaldav.method.put_addressbook_common import StoreAddressObjectResource
 from twistedcaldav.method.put_common import StoreCalendarObjectResource
@@ -45,7 +46,7 @@
 from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource
 from twistedcaldav.schedule import ScheduleInboxResource
 from twistedcaldav.scheduling.implicit import ImplicitScheduler
-from twistedcaldav.vcard import Component as VCard
+from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError
 from txdav.base.propertystore.base import PropertyName
 from txdav.common.icommondatastore import NoSuchObjectResourceError
 from urlparse import urlsplit
@@ -221,6 +222,9 @@
         if config.MaxResourcesPerCollection:
             props += (customxml.MaxResources.qname(),)
 
+        if config.EnableBatchUpload:
+            props += (customxml.BulkRequests.qname(),)
+
         return props
 
     @inlineCallbacks
@@ -487,26 +491,18 @@
         yield self._newStoreObject.rename(basename)
         returnValue(NO_CONTENT)
 
-    def liveProperties(self):
-        baseProperties = ()
-        if config.EnableBatchUpload:
-            baseProperties += (
-                customxml.BulkRequests.qname(),
-            )
-        return super(_CommonHomeChildCollectionMixin, self).liveProperties() + baseProperties
-
     @inlineCallbacks
     def _readGlobalProperty(self, qname, property, request):
 
         if config.EnableBatchUpload and qname == customxml.BulkRequests.qname():
             returnValue(customxml.BulkRequests(
                 customxml.Simple(
-                    customxml.MaxResources.fromString("100"),
-                    customxml.MaxBytes.fromString("%d" % (10*1024*1024,)),
+                    customxml.MaxBulkResources.fromString(str(config.MaxResourcesBatchUpload)),
+                    customxml.MaxBulkBytes.fromString(str(config.MaxBytesBatchUpload)),
                 ),
                 customxml.CRUD(
-                    customxml.MaxResources.fromString("100"),
-                    customxml.MaxBytes.fromString("%d" % (10*1024*1024,)),
+                    customxml.MaxBulkResources.fromString(str(config.MaxResourcesBatchUpload)),
+                    customxml.MaxBulkBytes.fromString(str(config.MaxBytesBatchUpload)),
                 ),
             ))
         else:
@@ -547,6 +543,8 @@
         data = (yield allDataFromStream(request.stream))
         
         components = self.componentsFromData(data)
+        if components is None:
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Could not parse valid data from request body"))
         
         # Build response
         xmlresponses = []
@@ -564,18 +562,8 @@
                 # Get a resource for the new item
                 newchildURL = joinURL(request.path, name)
                 newchild = (yield request.locateResource(newchildURL))
-                yield self.storeResourceData(request, newchild, newchildURL, componentdata)
+                dataChanged = (yield self.storeResourceData(request, newchild, newchildURL, componentdata))
 
-                # FIXME: figure out return_changed behavior
-                if return_changed:
-                    pass
-#                    note = component.getProperty("NOTE")
-#                    if note is None:
-#                        component.addProperty(VCardProperty("NOTE", component.resourceUID()))
-#                    else:
-#                        note.setValue(component.resourceUID())
-#                    dataChanged = str(component)
-
             except HTTPError, e:
                 # Extract the pre-condition
                 code = e.response.code
@@ -587,7 +575,7 @@
             
             if code is None:
                 
-                if not return_changed or not dataChanged:
+                if not return_changed or dataChanged is None:
                     xmlresponses.append(
                         davxml.PropertyStatusResponse(
                             davxml.HRef.fromString(newchildURL),
@@ -607,7 +595,7 @@
                             davxml.PropertyStatus(
                                 davxml.PropertyContainer(
                                     davxml.GETETag.fromString(newchild.etag().generate()),
-                                    self.xmlDataElementType().fromAddressData(dataChanged),
+                                    self.xmlDataElementType().fromTextData(dataChanged),
                                 ),
                                 davxml.Status.fromResponseCode(responsecode.OK),
                             )
@@ -660,9 +648,14 @@
             # Determine the multiput operation: create, update, delete
             href = xmlchild.childOfType(davxml.HRef.qname())
             set = xmlchild.childOfType(davxml.Set.qname())
-            xmldata = set.childOfType(self.xmlDataElementType().qname()) if set is not None else None
+            prop = set.childOfType(davxml.PropertyContainer.qname()) if set is not None else None
+            xmldata_root = prop if prop else set
+            xmldata = xmldata_root.childOfType(self.xmlDataElementType().qname()) if xmldata_root is not None else None
             if href is None:
                 
+                if xmldata is None:
+                    raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Could not parse valid data from request body without a DAV:Href present"))
+                
                 # Do privilege check on collection once 
                 if checkedBindPrivelege is None:
                     try:
@@ -679,6 +672,10 @@
                 if ifmatch:
                     ifmatch = str(ifmatch.children[0]) if len(ifmatch.children) == 1 else None
                 if delete is None:
+                    if set is None:
+                        raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Could not parse valid data from request body - no set of delete operation"))
+                    if xmldata is None:
+                        raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Could not parse valid data from request body for set operation"))
                     yield self.crudUpdate(request, str(href), xmldata.generateComponent(), ifmatch, return_changed, xmlresponses)
                 else:
                     # Do privilege check on collection once 
@@ -979,7 +976,11 @@
         results = []
 
         # Split into components by UID and TZID
-        vcal =  VCalendar.fromString(data)
+        try:
+            vcal =  VCalendar.fromString(data)
+        except InvalidICalendarDataError:
+            return None
+
         by_uid = {}
         by_tzid = {}
         for subcomponent in vcal.subcomponents():
@@ -1034,6 +1035,9 @@
             calendar = data,
         )
         yield storer.run()
+        
+        returnValue(storer.returndata if hasattr(storer, "returndata") else None)
+            
 
     @inlineCallbacks
     def storeRemove(self, request, implicitly, where):
@@ -1926,7 +1930,10 @@
 
     @classmethod
     def componentsFromData(cls, data):
-        return VCard.allFromString(data)
+        try:
+            return VCard.allFromString(data)
+        except InvalidVCardDataError:
+            return None
 
     @classmethod
     def resourceSuffix(cls):
@@ -1948,8 +1955,9 @@
             vcard = data,
         )
         yield storer.run()
+        
+        returnValue(storer.returndata if hasattr(storer, "returndata") else None)
 
-
 class GlobalAddressBookCollectionResource(GlobalAddressBookResource, AddressBookCollectionResource):
     """
     Wrapper around a L{txdav.carddav.iaddressbook.IAddressBook}.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110316/65197624/attachment-0001.html>


More information about the calendarserver-changes mailing list