summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hellkamp <marc@gsites.de>2010-06-19 14:41:20 +0200
committerMarcel Hellkamp <marc@gsites.de>2010-06-19 14:41:20 +0200
commitb294b57793b716346c18aaed9effaf465d1c22fd (patch)
treeb7152090cdca3fc9927a5f9b5b0cea79eb2bf833
parent27bbe40d2a3ecbefce55f8efc7c73fe5a2efb4c5 (diff)
downloadbottle-b294b57793b716346c18aaed9effaf465d1c22fd.tar.gz
fix: A fallback for 'wsgi.file_wrapper' MUST have a close() method that invokes the original file-like object's close() method.
Thanks to Enrico Zini.
-rwxr-xr-xbottle.py21
1 files changed, 18 insertions, 3 deletions
diff --git a/bottle.py b/bottle.py
index e968bdd..197871f 100755
--- a/bottle.py
+++ b/bottle.py
@@ -506,10 +506,12 @@ class Bottle(object):
out.apply(response)
return self._cast(out.output, request, response)
- # File-like objects. Wrap or transfer in chunks that fit into memory.
+ # File-like objects.
if hasattr(out, 'read'):
- return request.environ.get('wsgi.file_wrapper',
- lambda x: iter(lambda: x.read(1024*64), tob('')))(out)
+ if 'wsgi.file_wrapper' in request.environ:
+ return request.environ['wsgi.file_wrapper'](out)
+ elif hasattr(out, 'close') or not hasattr(out, '__iter__'):
+ return WSGIFileWrapper(out)
# Handle Iterables. We peek into them to detect their inner type.
try:
@@ -944,6 +946,19 @@ class AppStack(list):
self.append(value)
return value
+class WSGIFileWrapper(object):
+
+ def __init__(self, fp, buffer_size=1024*64):
+ self.fp, self.buffer_size = fp, buffer_size
+ for attr in ('fileno', 'close', 'read', 'readlines'):
+ if hasattr(fp, attr): setattr(self, attr, getattr(fp, attr))
+
+ def __iter__(self):
+ read, buff = self.fp.read, self.buffer_size
+ while True:
+ part = read(buff)
+ if not part: break
+ yield part