summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2012-10-21 12:15:06 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2012-10-21 12:15:06 (GMT)
commitd3a3e640b60484aa1450ca4a605d0e817f9e108f (patch)
treeb59528c5cdf8d0c57f7eec65f3bb5ab606d5abff /Lib
parent777d0c5c21916a0104d366da5205218ae99556b2 (diff)
parent550841253fc237f7aed14663de9717d6313e340d (diff)
downloadcpython-d3a3e640b60484aa1450ca4a605d0e817f9e108f.zip
cpython-d3a3e640b60484aa1450ca4a605d0e817f9e108f.tar.gz
cpython-d3a3e640b60484aa1450ca4a605d0e817f9e108f.tar.bz2
Issue #16220: wsgiref now always calls close() on an iterable response.
Patch by Brent Tubbs.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_wsgiref.py106
-rw-r--r--Lib/wsgiref/handlers.py12
2 files changed, 25 insertions, 93 deletions
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
index 398c53a..05c1f4f 100644
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -41,9 +41,6 @@ class MockHandler(WSGIRequestHandler):
pass
-
-
-
def hello_app(environ,start_response):
start_response("200 OK", [
('Content-Type','text/plain'),
@@ -65,28 +62,6 @@ def run_amock(app=hello_app, data=b"GET / HTTP/1.0\n\n"):
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 @@ def compare_generic_iter(make_it,match):
raise AssertionError("Too many items from .__next__()", it)
-
-
-
-
class IntegrationTests(TestCase):
def check_hello(self, out, has_length=True):
@@ -201,8 +172,6 @@ class IntegrationTests(TestCase):
out)
-
-
class UtilityTests(TestCase):
def checkShift(self,sn_in,pi_in,part,sn_out,pi_out):
@@ -241,11 +210,6 @@ class UtilityTests(TestCase):
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 @@ class UtilityTests(TestCase):
it.close()
self.assertTrue(it.filelike.closed)
-
def testSimpleShifts(self):
self.checkShift('','/', '', '/', '')
self.checkShift('','/x', 'x', '/x', '')
@@ -272,7 +235,6 @@ class UtilityTests(TestCase):
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 @@ class UtilityTests(TestCase):
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 @@ class UtilityTests(TestCase):
]:
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 @@ class UtilityTests(TestCase):
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 @@ class UtilityTests(TestCase):
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 @@ class TestHandler(ErrorHandler):
raise # for testing, we want to see what's happening
-
-
-
-
-
-
-
-
-
class HandlerTests(TestCase):
def checkEnvironAttrs(self, handler):
@@ -501,7 +447,6 @@ class HandlerTests(TestCase):
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 @@ class HandlerTests(TestCase):
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 @@ class HandlerTests(TestCase):
"\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 @@ class HandlerTests(TestCase):
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
index 67064a6..63d5993 100644
--- a/Lib/wsgiref/handlers.py
+++ b/Lib/wsgiref/handlers.py
@@ -174,11 +174,13 @@ class BaseHandler:
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):