Am Samstag, den 19.06.2010, 08:33 +0200 schrieb Enrico Zini:
> ...in this case we still lose the .close() method in case
> wsgi.file_wrapper is not present in the environment.

True. I simplified your wrapper a bit but hope it still catches all
eventualities. See b294b57793b716346c18aaed9effaf465d1c22fd or the
attached patch.

-- 
Mit freundlichen Grüßen
Marcel Hellkamp
>From b294b57793b716346c18aaed9effaf465d1c22fd Mon Sep 17 00:00:00 2001
From: Marcel Hellkamp <m...@gsites.de>
Date: Sat, 19 Jun 2010 14:41:20 +0200
Subject: [PATCH] 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.
---
 bottle.py |   21 ++++++++++++++++++---
 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
 
 
 
-- 
1.7.0.4

Reply via email to