[CalendarServer-changes] [8967] CalendarServer/trunk/twext/web2

source_changes at macosforge.org source_changes at macosforge.org
Mon Apr 2 17:48:11 PDT 2012


Revision: 8967
          http://trac.macosforge.org/projects/calendarserver/changeset/8967
Author:   wsanchez at apple.com
Date:     2012-04-02 17:48:11 -0700 (Mon, 02 Apr 2012)
Log Message:
-----------
Move web2.dav.stream.MD5StreamWrapper to web2.stream.MD5Stream.

Modified Paths:
--------------
    CalendarServer/trunk/twext/web2/dav/method/put_common.py
    CalendarServer/trunk/twext/web2/dav/test/test_stream.py
    CalendarServer/trunk/twext/web2/stream.py
    CalendarServer/trunk/twext/web2/test/test_stream.py

Removed Paths:
-------------
    CalendarServer/trunk/twext/web2/dav/stream.py

Modified: CalendarServer/trunk/twext/web2/dav/method/put_common.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/method/put_common.py	2012-04-03 00:31:50 UTC (rev 8966)
+++ CalendarServer/trunk/twext/web2/dav/method/put_common.py	2012-04-03 00:48:11 UTC (rev 8967)
@@ -33,7 +33,7 @@
 from twext.web2.dav.fileop import copy, delete, put
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.resource import TwistedGETContentMD5
-from twext.web2.dav.stream import MD5StreamWrapper
+from twext.web2.stream import MD5Stream
 from twext.web2.http import HTTPError
 from twext.web2.http_headers import generateContentType
 from twext.web2.iweb import IResponse
@@ -198,7 +198,7 @@
             datastream = request.stream
             if data is not None:
                 datastream = MemoryStream(data)
-            md5 = MD5StreamWrapper(datastream)
+            md5 = MD5Stream(datastream)
             response = maybeDeferred(put, md5, destination.fp)
 
         response = waitForDeferred(response)

Deleted: CalendarServer/trunk/twext/web2/dav/stream.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/stream.py	2012-04-03 00:31:50 UTC (rev 8966)
+++ CalendarServer/trunk/twext/web2/dav/stream.py	2012-04-03 00:48:11 UTC (rev 8967)
@@ -1,106 +0,0 @@
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-##
-
-"""
-Class that implements a stream that calculates the MD5 hash of the data
-as the data is read.
-"""
-
-__all__ = ["MD5StreamWrapper"]
-
-from twisted.python.hashlib import md5
-from twisted.internet.defer import Deferred
-from twext.web2.stream import SimpleStream
-
-
-class MD5StreamWrapper(SimpleStream):
-    """
-    An L{IByteStream} wrapper which computes the MD5 hash of the data read from
-    the wrapped stream.
-
-    @ivar _stream: The stream which is wrapped.
-    @ivar _md5: The object used to compute the running md5 hash.
-    @ivar _md5value: The hex encoded md5 hash, only set after C{close}.
-    """
-
-    def __init__(self, wrap):
-        if wrap is None:
-            raise ValueError("Stream to wrap must be provided")
-        self._stream = wrap
-        self._md5 = md5()
-
-
-    def _update(self, value):
-        """
-        Update the MD5 hash object.
-
-        @param value: L{None} or a L{str} with which to update the MD5 hash
-            object.
-
-        @return: C{value}
-        """
-        if value is not None:
-            self._md5.update(value)
-        return value
-
-
-    def read(self):
-        """
-        Read from the wrapped stream and update the MD5 hash object.
-        """
-        if self._stream is None:
-            raise RuntimeError("Cannot read after stream is closed")
-        b = self._stream.read()
-
-        if isinstance(b, Deferred):
-            b.addCallback(self._update)
-        else:
-            if b is not None:
-                self._md5.update(b)
-        return b
-
-
-    def close(self):
-        """
-        Compute the final hex digest of the contents of the wrapped stream.
-        """
-        SimpleStream.close(self)
-        self._md5value = self._md5.hexdigest()
-        self._stream = None
-        self._md5 = None
-
-
-    def getMD5(self):
-        """
-        Return the hex encoded MD5 digest of the contents of the wrapped
-        stream.  This may only be called after C{close}.
-
-        @rtype: C{str}
-        @raise RuntimeError: If C{close} has not yet been called.
-        """
-        if self._md5 is not None:
-            raise RuntimeError("Cannot get MD5 value until stream is closed")
-        return self._md5value

Modified: CalendarServer/trunk/twext/web2/dav/test/test_stream.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/test/test_stream.py	2012-04-03 00:31:50 UTC (rev 8966)
+++ CalendarServer/trunk/twext/web2/dav/test/test_stream.py	2012-04-03 00:48:11 UTC (rev 8967)
@@ -23,11 +23,8 @@
 # SOFTWARE.
 ##
 
-from twisted.python.hashlib import md5
 from twisted.internet.defer import Deferred
 from twisted.trial.unittest import TestCase
-from twext.web2.stream import MemoryStream
-from twext.web2.dav.stream import MD5StreamWrapper
 
 
 class AsynchronousDummyStream(object):
@@ -47,83 +44,3 @@
 
     def _write(self, bytes):
         self._readResults.pop(0).callback(bytes)
-
-
-
-class MD5StreamWrapperTests(TestCase):
-    """
-    Tests for L{MD5StreamWrapper}.
-    """
-    data = "I am sorry Dave, I can't do that.\n--HAL 9000"
-    digest = md5(data).hexdigest()
-
-    def test_synchronous(self):
-        """
-        L{MD5StreamWrapper} computes the MD5 hash of the contents of the stream
-        around which it is wrapped.  It supports L{IByteStream} providers which
-        return C{str} from their C{read} method.
-        """
-        dataStream = MemoryStream(self.data)
-        md5Stream = MD5StreamWrapper(dataStream)
-
-        self.assertEquals(str(md5Stream.read()), self.data)
-        self.assertIdentical(md5Stream.read(), None)
-        md5Stream.close()
-
-        self.assertEquals(self.digest, md5Stream.getMD5())
-
-
-    def test_asynchronous(self):
-        """
-        L{MD5StreamWrapper} also supports L{IByteStream} providers which return
-        L{Deferreds} from their C{read} method.
-        """
-        dataStream = AsynchronousDummyStream()
-        md5Stream = MD5StreamWrapper(dataStream)
-
-        result = md5Stream.read()
-        dataStream._write(self.data)
-        result.addCallback(self.assertEquals, self.data)
-
-        def cbRead(ignored):
-            result = md5Stream.read()
-            dataStream._write(None)
-            result.addCallback(self.assertIdentical, None)
-            return result
-        result.addCallback(cbRead)
-
-        def cbClosed(ignored):
-            md5Stream.close()
-            self.assertEquals(md5Stream.getMD5(), self.digest)
-        result.addCallback(cbClosed)
-
-        return result
-
-
-    def test_getMD5FailsBeforeClose(self):
-        """
-        L{MD5StreamWrapper.getMD5} raises L{RuntimeError} if called before
-        L{MD5StreamWrapper.close}.
-        """
-        dataStream = MemoryStream(self.data)
-        md5Stream = MD5StreamWrapper(dataStream)
-        self.assertRaises(RuntimeError, md5Stream.getMD5)
-
-
-    def test_initializationFailsWithoutStream(self):
-        """
-        L{MD5StreamWrapper.__init__} raises L{ValueError} if passed C{None} as
-        the stream to wrap.
-        """
-        self.assertRaises(ValueError, MD5StreamWrapper, None)
-
-
-    def test_readAfterClose(self):
-        """
-        L{MD5StreamWrapper.read} raises L{RuntimeError} if called after
-        L{MD5StreamWrapper.close}.
-        """
-        dataStream = MemoryStream(self.data)
-        md5Stream = MD5StreamWrapper(dataStream)
-        md5Stream.close()
-        self.assertRaises(RuntimeError, md5Stream.read)

Modified: CalendarServer/trunk/twext/web2/stream.py
===================================================================
--- CalendarServer/trunk/twext/web2/stream.py	2012-04-03 00:31:50 UTC (rev 8966)
+++ CalendarServer/trunk/twext/web2/stream.py	2012-04-03 00:48:11 UTC (rev 8967)
@@ -61,6 +61,7 @@
 from twisted.internet import interfaces as ti_interfaces, defer, reactor, protocol, error as ti_error
 from twisted.python import components, log
 from twisted.python.failure import Failure
+from twisted.python.hashlib import md5
 
 # Python 2.4.2 (only) has a broken mmap that leaks a fd every time you call it.
 if sys.version_info[0:3] != (2,4,2):
@@ -1090,6 +1091,75 @@
         return pre, post
 
         
+#########################
+####    MD5Stream    ####
+#########################
+
+class MD5Stream(SimpleStream):
+    """
+    An wrapper which computes the MD5 hash of the data read from the
+    wrapped stream.
+    """
+
+    def __init__(self, wrap):
+        if wrap is None:
+            raise ValueError("Stream to wrap must be provided")
+        self._stream = wrap
+        self._md5 = md5()
+
+
+    def _update(self, value):
+        """
+        Update the MD5 hash object.
+
+        @param value: L{None} or a L{str} with which to update the MD5 hash
+            object.
+
+        @return: C{value}
+        """
+        if value is not None:
+            self._md5.update(value)
+        return value
+
+
+    def read(self):
+        """
+        Read from the wrapped stream and update the MD5 hash object.
+        """
+        if self._stream is None:
+            raise RuntimeError("Cannot read after stream is closed")
+        b = self._stream.read()
+
+        if isinstance(b, Deferred):
+            b.addCallback(self._update)
+        else:
+            self._update(b)
+        return b
+
+
+    def close(self):
+        """
+        Compute the final hex digest of the contents of the wrapped stream.
+        """
+        SimpleStream.close(self)
+        self._md5value = self._md5.hexdigest()
+        self._stream = None
+        self._md5 = None
+
+
+    def getMD5(self):
+        """
+        Return the hex encoded MD5 digest of the contents of the wrapped
+        stream.  This may only be called after C{close}.
+
+        @rtype: C{str}
+        @raise RuntimeError: If C{close} has not yet been called.
+        """
+        if self._md5 is not None:
+            raise RuntimeError("Cannot get MD5 value until stream is closed")
+        return self._md5value
+
+
 def substream(stream, start, end):
     if start > end:
         raise ValueError("start position must be less than end position %r"
@@ -1101,6 +1171,5 @@
 
 __all__ = ['IStream', 'IByteStream', 'FileStream', 'MemoryStream', 'CompoundStream',
            'readAndDiscard', 'fallbackSplit', 'ProducerStream', 'StreamProducer',
-           'BufferedStream', 'readStream', 'ProcessStreamer', 'readIntoFile',
+           'BufferedStream', 'MD5Stream', 'readStream', 'ProcessStreamer', 'readIntoFile',
            'generatorToStream']
-

Modified: CalendarServer/trunk/twext/web2/test/test_stream.py
===================================================================
--- CalendarServer/trunk/twext/web2/test/test_stream.py	2012-04-03 00:31:50 UTC (rev 8966)
+++ CalendarServer/trunk/twext/web2/test/test_stream.py	2012-04-03 00:48:11 UTC (rev 8967)
@@ -11,6 +11,7 @@
 
 from twisted.python.util import sibpath
 sibpath # sibpath is *not* unused - the doctests use it.
+from twisted.python.hashlib import md5
 from twisted.internet import reactor, defer, interfaces
 from twisted.trial import unittest
 from twext.web2 import stream
@@ -615,6 +616,99 @@
     """
 
 
+class AsynchronousDummyStream(object):
+    """
+    An L{IByteStream} implementation which always returns a
+    L{defer.Deferred} from C{read} and lets an external driver fire
+    them.
+    """
+    def __init__(self):
+        self._readResults = []
+
+    def read(self):
+        result = defer.Deferred()
+        self._readResults.append(result)
+        return result
+
+    def _write(self, bytes):
+        self._readResults.pop(0).callback(bytes)
+
+class MD5StreamTest(unittest.TestCase):
+    """
+    Tests for L{stream.MD5Stream}.
+    """
+    data = "I am sorry Dave, I can't do that.\n--HAL 9000"
+    digest = md5(data).hexdigest()
+
+    def test_synchronous(self):
+        """
+        L{stream.MD5Stream} computes the MD5 hash of the contents of the stream
+        around which it is wrapped.  It supports L{IByteStream} providers which
+        return C{str} from their C{read} method.
+        """
+        dataStream = stream.MemoryStream(self.data)
+        md5Stream = stream.MD5Stream(dataStream)
+
+        self.assertEquals(str(md5Stream.read()), self.data)
+        self.assertIdentical(md5Stream.read(), None)
+        md5Stream.close()
+
+        self.assertEquals(self.digest, md5Stream.getMD5())
+
+    def test_asynchronous(self):
+        """
+        L{stream.MD5Stream} also supports L{IByteStream} providers which return
+        L{Deferreds} from their C{read} method.
+        """
+        dataStream = AsynchronousDummyStream()
+        md5Stream = stream.MD5Stream(dataStream)
+
+        result = md5Stream.read()
+        dataStream._write(self.data)
+        result.addCallback(self.assertEquals, self.data)
+
+        def cbRead(ignored):
+            result = md5Stream.read()
+            dataStream._write(None)
+            result.addCallback(self.assertIdentical, None)
+            return result
+        result.addCallback(cbRead)
+
+        def cbClosed(ignored):
+            md5Stream.close()
+            self.assertEquals(md5Stream.getMD5(), self.digest)
+        result.addCallback(cbClosed)
+
+        return result
+
+    def test_getMD5FailsBeforeClose(self):
+        """
+        L{stream.MD5Stream.getMD5} raises L{RuntimeError} if called before
+        L{stream.MD5Stream.close}.
+        """
+        dataStream = stream.MemoryStream(self.data)
+        md5Stream = stream.MD5Stream(dataStream)
+        self.assertRaises(RuntimeError, md5Stream.getMD5)
+
+    def test_initializationFailsWithoutStream(self):
+        """
+        L{stream.MD5Stream.__init__} raises L{ValueError} if passed C{None} as
+        the stream to wrap.
+        """
+        self.assertRaises(ValueError, stream.MD5Stream, None)
+
+    def test_readAfterClose(self):
+        """
+        L{stream.MD5Stream.read} raises L{RuntimeError} if called after
+        L{stream.MD5Stream.close}.
+        """
+        dataStream = stream.MemoryStream(self.data)
+        md5Stream = stream.MD5Stream(dataStream)
+        md5Stream.close()
+        self.assertRaises(RuntimeError, md5Stream.read)
+
+
+
 __doctests__ = ['twext.web2.test.test_stream', 'twext.web2.stream']
 # TODO:
 # CompoundStreamTest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120402/6035245d/attachment-0001.html>


More information about the calendarserver-changes mailing list