[Python-checkins] cpython (merge 3.2 -> 3.3): Issue #16220: wsgiref now always calls close() on an iterable response.

antoine.pitrou python-checkins at python.org
Sun Oct 21 14:17:16 CEST 2012


http://hg.python.org/cpython/rev/2530acc092d8
changeset:   79870:2530acc092d8
branch:      3.3
parent:      79864:265fe07f55ec
parent:      79869:058fcf5eb644
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sun Oct 21 14:14:34 2012 +0200
summary:
  Issue #16220: wsgiref now always calls close() on an iterable response.
Patch by Brent Tubbs.

files:
  Lib/test/test_wsgiref.py |  106 ++++----------------------
  Lib/wsgiref/handlers.py  |   12 +-
  Misc/ACKS                |    1 +
  Misc/NEWS                |    3 +
  4 files changed, 29 insertions(+), 93 deletions(-)


diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -41,9 +41,6 @@
         pass
 
 
-
-
-
 def hello_app(environ,start_response):
     start_response("200 OK", [
         ('Content-Type','text/plain'),
@@ -65,28 +62,6 @@
 
     return out.getvalue(), err.getvalue()
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 def compare_generic_iter(make_it,match):
     """Utility to compare a generic 2.1/2.2+ iterator with an iterable
 
@@ -124,10 +99,6 @@
             raise AssertionError("Too many items from .__next__()", it)
 
 
-
-
-
-
 class IntegrationTests(TestCase):
 
     def check_hello(self, out, has_length=True):
@@ -201,8 +172,6 @@
                 out)
 
 
-
-
 class UtilityTests(TestCase):
 
     def checkShift(self,sn_in,pi_in,part,sn_out,pi_out):
@@ -241,11 +210,6 @@
         util.setup_testing_defaults(kw)
         self.assertEqual(util.request_uri(kw,query),uri)
 
-
-
-
-
-
     def checkFW(self,text,size,match):
 
         def make_it(text=text,size=size):
@@ -264,7 +228,6 @@
         it.close()
         self.assertTrue(it.filelike.closed)
 
-
     def testSimpleShifts(self):
         self.checkShift('','/', '', '/', '')
         self.checkShift('','/x', 'x', '/x', '')
@@ -272,7 +235,6 @@
         self.checkShift('/a','/x/y', 'x', '/a/x', '/y')
         self.checkShift('/a','/x/',  'x', '/a/x', '/')
 
-
     def testNormalizedShifts(self):
         self.checkShift('/a/b', '/../y', '..', '/a', '/y')
         self.checkShift('', '/../y', '..', '', '/y')
@@ -286,7 +248,6 @@
         self.checkShift('/a/b', '/x//', 'x', '/a/b/x', '/')
         self.checkShift('/a/b', '/.', None, '/a/b', '')
 
-
     def testDefaults(self):
         for key, value in [
             ('SERVER_NAME','127.0.0.1'),
@@ -306,7 +267,6 @@
         ]:
             self.checkDefault(key,value)
 
-
     def testCrossDefaults(self):
         self.checkCrossDefault('HTTP_HOST',"foo.bar",SERVER_NAME="foo.bar")
         self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="on")
@@ -316,7 +276,6 @@
         self.checkCrossDefault('SERVER_PORT',"80",HTTPS="foo")
         self.checkCrossDefault('SERVER_PORT',"443",HTTPS="on")
 
-
     def testGuessScheme(self):
         self.assertEqual(util.guess_scheme({}), "http")
         self.assertEqual(util.guess_scheme({'HTTPS':"foo"}), "http")
@@ -324,10 +283,6 @@
         self.assertEqual(util.guess_scheme({'HTTPS':"yes"}), "https")
         self.assertEqual(util.guess_scheme({'HTTPS':"1"}), "https")
 
-
-
-
-
     def testAppURIs(self):
         self.checkAppURI("http://127.0.0.1/")
         self.checkAppURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam")
@@ -452,15 +407,6 @@
         raise   # for testing, we want to see what's happening
 
 
-
-
-
-
-
-
-
-
-
 class HandlerTests(TestCase):
 
     def checkEnvironAttrs(self, handler):
@@ -501,7 +447,6 @@
         h=TestHandler(); h.setup_environ()
         self.assertEqual(h.environ['wsgi.url_scheme'],'http')
 
-
     def testAbstractMethods(self):
         h = BaseHandler()
         for name in [
@@ -510,7 +455,6 @@
             self.assertRaises(NotImplementedError, getattr(h,name))
         self.assertRaises(NotImplementedError, h._write, "test")
 
-
     def testContentLength(self):
         # Demo one reason iteration is better than write()...  ;)
 
@@ -602,7 +546,6 @@
             "\r\n".encode("iso-8859-1")+MSG))
         self.assertIn("AssertionError", h.stderr.getvalue())
 
-
     def testHeaderFormats(self):
 
         def non_error_app(e,s):
@@ -662,40 +605,27 @@
             b"data",
             h.stdout.getvalue())
 
-# This epilogue is needed for compatibility with the Python 2.5 regrtest module
+    def testCloseOnError(self):
+        side_effects = {'close_called': False}
+        MSG = b"Some output has been sent"
+        def error_app(e,s):
+            s("200 OK",[])(MSG)
+            class CrashyIterable(object):
+                def __iter__(self):
+                    while True:
+                        yield b'blah'
+                        raise AssertionError("This should be caught by handler")
+                def close(self):
+                    side_effects['close_called'] = True
+            return CrashyIterable()
+
+        h = ErrorHandler()
+        h.run(error_app)
+        self.assertEqual(side_effects['close_called'], True)
+
 
 def test_main():
     support.run_unittest(__name__)
 
 if __name__ == "__main__":
     test_main()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# the above lines intentionally left blank
diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py
--- a/Lib/wsgiref/handlers.py
+++ b/Lib/wsgiref/handlers.py
@@ -174,11 +174,13 @@
         in the event loop to iterate over the data, and to call
         'self.close()' once the response is finished.
         """
-        if not self.result_is_file() or not self.sendfile():
-            for data in self.result:
-                self.write(data)
-            self.finish_content()
-        self.close()
+        try:
+            if not self.result_is_file() or not self.sendfile():
+                for data in self.result:
+                    self.write(data)
+                self.finish_content()
+        finally:
+            self.close()
 
 
     def get_scheme(self):
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1178,6 +1178,7 @@
 Matthias Troffaes
 John Tromp
 Jason Trowbridge
+Brent Tubbs
 Anthony Tuininga
 Erno Tukia
 David Turner
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -46,6 +46,9 @@
 Library
 -------
 
+- Issue #16220: wsgiref now always calls close() on an iterable response.
+  Patch by Brent Tubbs.
+
 - Issue #16270: urllib may hang when used for retrieving files via FTP by using
   a context manager.  Patch by Giampaolo Rodola'.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list