2
0
Эх сурвалжийг харах

Merge remote-tracking branch 'jonashaag/fix-140'

Jelmer Vernooij 9 жил өмнө
parent
commit
3a1025e798
3 өөрчлөгдсөн 42 нэмэгдсэн , 18 устгасан
  1. 3 0
      NEWS
  2. 33 13
      dulwich/tests/test_web.py
  3. 6 5
      dulwich/web.py

+ 3 - 0
NEWS

@@ -19,6 +19,9 @@
 
   * Fix hang on Gzip decompression. (Jonas Haag)
 
+  * Don't rely on working tell() and seek() methods
+    on wsgi.input. (Jonas Haag)
+
 0.12.0	2015-12-13
 
  IMPROVEMENTS

+ 33 - 13
dulwich/tests/test_web.py

@@ -64,6 +64,30 @@ from dulwich.tests.utils import (
     )
 
 
+class MinimalistWSGIInputStream(object):
+    """WSGI input stream with no 'seek()' and 'tell()' methods."""
+    def __init__(self, data):
+        self.data = data
+        self.pos = 0
+
+    def read(self, howmuch):
+        start = self.pos
+        end = self.pos + howmuch
+        if start >= len(self.data):
+            return ''
+        self.pos = end
+        return self.data[start:end]
+
+
+class MinimalistWSGIInputStream2(MinimalistWSGIInputStream):
+    """WSGI input stream with no *working* 'seek()' and 'tell()' methods."""
+    def seek(self, pos):
+        raise NotImplementedError
+
+    def tell(self):
+        raise NotImplementedError
+
+
 class TestHTTPGitRequest(HTTPGitRequest):
     """HTTPGitRequest with overridden methods to help test caching."""
 
@@ -497,19 +521,15 @@ class GunzipTestCase(HTTPGitApplicationTestCase):
         'wsgi.input' except for '.read()'.  (In particular, it shouldn't
         require '.seek()'. See https://github.com/jelmer/dulwich/issues/140.)
         """
-        class MinimalistWSGIInputStream(object):
-            def __init__(self, data):
-                self.data = data
-                self.pos = 0
-
-            def read(self, howmuch):
-                start = self.pos
-                end = self.pos + howmuch
-                if start >= len(self.data):
-                    return ''
-                self.pos = end
-                return self.data[start:end]
-
         zstream, zlength = self._get_zstream(self.example_text)
         self._test_call(self.example_text,
             MinimalistWSGIInputStream(zstream.read()), zlength)
+
+    def test_call_no_working_seek(self):
+        """
+        Similar to 'test_call_no_seek', but this time the methods are available
+        (but defunct).  See https://github.com/jonashaag/klaus/issues/154.
+        """
+        zstream, zlength = self._get_zstream(self.example_text)
+        self._test_call(self.example_text,
+            MinimalistWSGIInputStream2(zstream.read()), zlength)

+ 6 - 5
dulwich/web.py

@@ -371,13 +371,14 @@ class GunzipFilter(object):
 
     def __call__(self, environ, start_response):
         if environ.get('HTTP_CONTENT_ENCODING', '') == 'gzip':
-            if hasattr(environ['wsgi.input'], 'seek'):
+            try:
+                environ['wsgi.input'].tell()
                 wsgi_input = environ['wsgi.input']
-            else:
+            except (AttributeError, IOError, NotImplementedError):
                 # The gzip implementation in the standard library of Python 2.x
-                # requires the '.seek()' and '.tell()' methods to be available
-                # on the input stream.  Read the data into a temporary file to
-                # work around this limitation.
+                # requires working '.seek()' and '.tell()' methods on the input
+                # stream.  Read the data into a temporary file to work around
+                # this limitation.
                 wsgi_input = tempfile.SpooledTemporaryFile(16 * 1024 * 1024)
                 shutil.copyfileobj(environ['wsgi.input'], wsgi_input)
                 wsgi_input.seek(0)