Skip to content

Commit

Permalink
Don't expect 'wsgi.input' to have working 'seek' method
Browse files Browse the repository at this point in the history
This is a follow-up to 5a69c46 which misses the fact that even though an
input stream might have 'seek' and 'tell' methods, they do not
necessarily have to be implemented.  See also http://bugs.python.org/issue12877
  • Loading branch information
jonashaag committed Apr 12, 2016
1 parent 7b70438 commit fe9bf84
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
46 changes: 33 additions & 13 deletions dulwich/tests/test_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,30 @@
)


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."""

Expand Down Expand Up @@ -497,19 +521,15 @@ def test_call_no_seek(self):
'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)
11 changes: 6 additions & 5 deletions dulwich/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,14 @@ def __init__(self, application):

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)
Expand Down

0 comments on commit fe9bf84

Please sign in to comment.