Sorry for the late answer.

On Sun, Jun 06, 2010 at 11:33:20PM +0100, Enrico Zini wrote: 
> Bottle seems to be extracting the first element from the iterable in
> order to look at what the iterator returns and possibly add transparent
> recoding and whatnot, then it returns a chain iterator with the first
> element it took out and the rest.
> 
> Now, the WSGI server, even if it supports the file_wrapper
> optimisation[1], will never be able to see that we are returning a
> file_wrapper, so the optimisation will never trigger, in the face of
> what Bottle's documentation says.
>
> The same also defeats the idea that in WSGI, if you return an object
> that has a close() method, it will be called at the end of the request.
> In this case, Bottle will wrap our returned generator (which has a close
> method) in one that doesn't.
> 
> Goodbye cleanup after streaming ends.

Fixed in 590f213238d7b65eabc53fd5f7c47375b02a075e

> So, much more simple and readable, and with only one environ lookup:
> 
>         # Cast Files into iterables
>         if hasattr(out, 'read'):
>             wrapper = request.environ.get('wsgi.file_wrapper', None)
>             if wrapper: out = wrapper(out)
>             return out

The 'wsgi.file_wrapper' is optional and we must return an iterable. Some
file-like objects may not be iterable. A working fallback won't hurt :)

-- 
Mit freundlichen Grüßen
Marcel Hellkamp
>From 590f213238d7b65eabc53fd5f7c47375b02a075e Mon Sep 17 00:00:00 2001
From: Marcel Hellkamp <m...@gsites.de>
Date: Fri, 18 Jun 2010 23:53:19 +0200
Subject: [PATCH] fix: Return wsgi.file_wrapper wrapped files directly to the wsgi server.

Thanks to Alex Popescu, Enrico Zini and David Paleino.
---
 bottle.py |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bottle.py b/bottle.py
index fef1837..e968bdd 100755
--- a/bottle.py
+++ b/bottle.py
@@ -508,8 +508,8 @@ class Bottle(object):
 
         # File-like objects. Wrap or transfer in chunks that fit into memory.
         if hasattr(out, 'read'):
-            out = request.environ.get('wsgi.file_wrapper',
-                  lambda x, y: iter(lambda: x.read(y), tob('')))(out, 1024*64)
+            return request.environ.get('wsgi.file_wrapper',
+                   lambda x: iter(lambda: x.read(1024*64), tob('')))(out)
 
         # Handle Iterables. We peek into them to detect their inner type.
         try:
-- 
1.7.0.4

Reply via email to