[CalendarServer-changes] [8111] CalendarServer/trunk/txdav/caldav/datastore

source_changes at macosforge.org source_changes at macosforge.org
Wed Sep 21 01:02:44 PDT 2011


Revision: 8111
          http://trac.macosforge.org/projects/calendarserver/changeset/8111
Author:   glyph at apple.com
Date:     2011-09-21 01:02:43 -0700 (Wed, 21 Sep 2011)
Log Message:
-----------
don't conflict with attachments of the same name: they have to be in the same dropbox, too.

Modified Paths:
--------------
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-09-20 21:04:39 UTC (rev 8110)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-09-21 08:02:43 UTC (rev 8111)
@@ -729,10 +729,14 @@
     @inlineCallbacks
     def createAttachmentWithName(self, name):
 
-        # We need to know the resource_ID of the home collection of the owner (not sharee)
-        # of this event
+        # We need to know the resource_ID of the home collection of the owner
+        # (not sharee) of this event
         sharerHomeID = (yield self._parentCollection.sharerHomeID())
-        returnValue((yield Attachment.create(self._txn, self._dropboxID, name, sharerHomeID)))
+        returnValue((
+            yield Attachment.create(
+                self._txn, (yield self.dropboxID()), name, sharerHomeID
+            )
+        ))
 
     @inlineCallbacks
     def removeAttachmentWithName(self, name):
@@ -849,7 +853,9 @@
                     att.MD5          : self._attachment._md5,
                     att.MODIFIED     : utcNowSQL
                 },
-                Where=att.PATH == self._attachment.name(),
+                Where=(att.PATH == self._attachment.name()).And(
+                    att.DROPBOX_ID == self._attachment._dropboxID
+                ),
                 Return=(att.CREATED, att.MODIFIED)).on(self._txn))[0]
         )
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-09-20 21:04:39 UTC (rev 8110)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-09-21 08:02:43 UTC (rev 8111)
@@ -152,7 +152,26 @@
 )
 
 
+class CaptureProtocol(Protocol):
+    """
+    A proocol that captures the data delivered to it, and calls back a Deferred
+    with that data.
 
+    @ivar deferred: a L{Deferred} which will be called back with all the data
+        yet delivered to C{dataReceived} when C{connectionLost} is called.
+    """
+
+    def __init__(self):
+        self.deferred = Deferred()
+        self.io = StringIO()
+        self.dataReceived = self.io.write
+
+
+    def connectionLost(self, reason):
+        self.deferred.callback(self.io.getvalue())
+
+
+
 class CommonTests(CommonCommonTests):
     """
     Tests for common functionality of interfaces defined in
@@ -247,14 +266,14 @@
 
 
     @inlineCallbacks
-    def calendarObjectUnderTest(self):
+    def calendarObjectUnderTest(self, name="1.ics"):
         """
         Get the calendar detailed by
-        C{requirements['home1']['calendar_1']['1.ics']}.
+        C{requirements['home1']['calendar_1'][name]}.
         """
         returnValue(
             (yield (yield self.calendarUnderTest())
-                .calendarObjectWithName("1.ics")))
+                .calendarObjectWithName(name)))
 
 
     def test_calendarStoreProvides(self):
@@ -1560,18 +1579,9 @@
         t.write(" text")
         yield t.loseConnection()
         obj = yield refresh(obj)
-        class CaptureProtocol(Protocol):
-            buf = ''
-            def dataReceived(self, data):
-                self.buf += data
-            def connectionLost(self, reason):
-                self.deferred.callback(self.buf)
-        capture = CaptureProtocol()
-        capture.deferred = Deferred()
         attachment = yield obj.attachmentWithName("new.attachment")
         self.assertProvides(IAttachment, attachment)
-        attachment.retrieve(capture)
-        data = yield capture.deferred
+        data = yield self.attachmentToString(attachment)
         self.assertEquals(data, "new attachment text")
         contentType = attachment.contentType()
         self.assertIsInstance(contentType, MimeType)
@@ -1583,6 +1593,68 @@
         )
 
 
+    @inlineCallbacks
+    def test_twoAttachmentsWithTheSameName(self):
+        """
+        Attachments are uniquely identified by their associated object and path;
+        two attachments with the same name won't overwrite each other.
+        """
+        obj = yield self.calendarObjectUnderTest()
+        obj2 = yield self.calendarObjectUnderTest("2.ics")
+        att1 = yield self.stringToAttachment(obj, "sample.attachment",
+                                             "test data 1")
+        att2 = yield self.stringToAttachment(obj2, "sample.attachment",
+                                             "test data 2")
+        data1 = yield self.attachmentToString(att1)
+        data2 = yield self.attachmentToString(att2)
+        self.assertEquals(data1, "test data 1")
+        self.assertEquals(data2, "test data 2")
+
+
+    @inlineCallbacks
+    def stringToAttachment(self, obj, name, contents,
+                           mimeType=MimeType("text", "x-fixture")):
+        """
+        Convenience for producing an attachment from a calendar object.
+
+        @param obj: the calendar object which owns the dropbox associated with
+            the to-be-created attachment.
+
+        @param name: the (utf-8 encoded) name to create the attachment with.
+
+        @type name: C{bytes}
+
+        @param contents: the desired contents of the new attachment.
+
+        @type contents: C{bytes}
+
+        @param mimeType: the mime type of the incoming bytes.
+
+        @return: a L{Deferred} that fires with the L{IAttachment} that is
+            created, once all the bytes have been stored.
+        """
+        att = yield obj.createAttachmentWithName(name)
+        t = att.store(mimeType)
+        t.write(contents)
+        yield t.loseConnection()
+        returnValue(att)
+
+
+    def attachmentToString(self, attachment):
+        """
+        Convenience to convert an L{IAttachment} to a string.
+
+        @param attachment: an L{IAttachment} provider to convert into a string.
+
+        @return: a L{Deferred} that fires with the contents of the attachment.
+
+        @rtype: L{Deferred} firing C{bytes}
+        """
+        capture = CaptureProtocol()
+        attachment.retrieve(capture)
+        return capture.deferred
+
+
     def test_createAttachment(self):
         """
         L{ICalendarObject.createAttachmentWithName} will store an
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110921/25f08ff0/attachment-0001.html>


More information about the calendarserver-changes mailing list