[Checkins] SVN: zope.server/branches/achapman-exc-info/src/zope/server/http/ further compliance with WSGI PEP.
Satchidanand Haridas
satchit at zope.com
Tue May 17 10:14:21 EDT 2011
Log message for revision 121687:
further compliance with WSGI PEP.
and tests.
Changed:
U zope.server/branches/achapman-exc-info/src/zope/server/http/tests/test_wsgiserver.py
U zope.server/branches/achapman-exc-info/src/zope/server/http/wsgihttpserver.py
-=-
Modified: zope.server/branches/achapman-exc-info/src/zope/server/http/tests/test_wsgiserver.py
===================================================================
--- zope.server/branches/achapman-exc-info/src/zope/server/http/tests/test_wsgiserver.py 2011-05-17 12:41:54 UTC (rev 121686)
+++ zope.server/branches/achapman-exc-info/src/zope/server/http/tests/test_wsgiserver.py 2011-05-17 14:14:20 UTC (rev 121687)
@@ -312,13 +312,15 @@
self.server.application = app
class FakeTask:
+ wrote_header = 0
counter = 0
getCGIEnvironment = lambda _: {}
class request_data:
getBodyStream = lambda _: StringIO.StringIO()
request_data = request_data()
setResponseStatus = appendResponseHeaders = lambda *_: None
-
+ def wroteResponseHeader(self):
+ return self.wrote_header
def write(self, v):
self.counter += 1
@@ -334,7 +336,10 @@
try:
raise DummyException()
except DummyException as e:
- start_response('500 Internal Error', [], sys.exc_info())
+ start_response(
+ '500 Internal Error',
+ [('Content-type', 'text/plain')],
+ sys.exc_info())
return ERROR_RESPONSE.split()
return RESPONSE.split()
@@ -343,11 +348,16 @@
status = None
reason = None
response = []
+ accumulated_headers = []
getCGIEnvironment = lambda _: {}
class request_data:
getBodyStream = lambda _: StringIO.StringIO()
request_data = request_data()
- appendResponseHeaders = lambda *_: None
+ def appendResponseHeaders(self, lst):
+ accum = self.accumulated_headers
+ if accum is None:
+ self.accumulated_headers = accum = []
+ accum.extend(lst)
def setResponseStatus(self, status, reason):
self.status = status
self.reason = reason
@@ -363,13 +373,27 @@
# start_response exc_info if no headers have been sent
orig_app = self.server.application
self.server.application, task = self._getFakeAppAndTask()
+ task.accumulated_headers = ['header1', 'header2']
self.server.executeRequest(task)
self.assertEqual(task.status, "500")
self.assertEqual(task.response, ERROR_RESPONSE.split())
+ # any headers written before are cleared and
+ # only the most recent one is added.
+ self.assertEqual(task.accumulated_headers, ['Content-type: text/plain'])
+ self.server.application = orig_app
+
+ def test_multiple_start_response_calls(self):
+ # if start_response is called more than once with no exc_info
+ ignore, task = self._getFakeAppAndTask()
+ task.wrote_header = 1
+
+ self.assertRaises(AssertionError, self.server.executeRequest, task)
+
+
def test_start_response_with_headers_sent(self):
# If headers have been sent it raises the exception
orig_app = self.server.application
@@ -399,6 +423,26 @@
'wsgi.multiprocess', 'wsgi.handleErrors',
'wsgi.run_once']))
+ def test_multiple_start_response_calls(self):
+ # if start_response is called more than once with no exc_info
+ ignore, task = self._getFakeAppAndTask()
+ task.wrote_header = 1
+
+ # monkey-patch pdb.post_mortem so we don't go into pdb session.
+ pm_traceback = []
+ def fake_post_mortem(tb):
+ import traceback
+ pm_traceback.extend(traceback.format_tb(tb))
+
+ import pdb
+ orig_post_mortem = pdb.post_mortem
+ pdb.post_mortem = fake_post_mortem
+
+ self.assertRaises(AssertionError, self.server.executeRequest, task)
+ expected_msg = "start_response called a second time"
+ self.assertTrue(expected_msg in pm_traceback[-1])
+ pdb.post_mortem = orig_post_mortem
+
def test_start_response_with_headers_sent(self):
# If headers have been sent it raises the exception, which will
# be caught by the server and invoke pdb.post_mortem.
@@ -418,6 +462,7 @@
self.assertRaises(DummyException, self.server.executeRequest, task)
self.assertTrue("raise DummyException" in pm_traceback[-1])
+
self.server.application = orig_app
pdb.post_mortem = orig_post_mortem
Modified: zope.server/branches/achapman-exc-info/src/zope/server/http/wsgihttpserver.py
===================================================================
--- zope.server/branches/achapman-exc-info/src/zope/server/http/wsgihttpserver.py 2011-05-17 12:41:54 UTC (rev 121686)
+++ zope.server/branches/achapman-exc-info/src/zope/server/http/wsgihttpserver.py 2011-05-17 14:14:20 UTC (rev 121687)
@@ -77,12 +77,16 @@
env = self._constructWSGIEnvironment(task)
def start_response(status, headers, exc_info=None):
+ if task.wroteResponseHeader() and not exc_info:
+ raise AssertionError("start_response called a second time "
+ "without providing exc_info.")
if exc_info:
try:
if task.wroteResponseHeader():
raise exc_info[0], exc_info[1], exc_info[2]
else:
- pass
+ # As per WSGI spec existing headers must be cleared
+ task.accumulated_headers = None
finally:
exc_info = None
# Prepare the headers for output
@@ -110,12 +114,16 @@
env['wsgi.handleErrors'] = False
def start_response(status, headers, exc_info=None):
+ if task.wroteResponseHeader() and not exc_info:
+ raise AssertionError("start_response called a second time "
+ "without providing exc_info.")
if exc_info:
try:
if task.wroteResponseHeader():
raise exc_info[0], exc_info[1], exc_info[2]
else:
- pass
+ # As per WSGI spec existing headers must be cleared
+ task.accumulated_headers = None
finally:
exc_info = None
# Prepare the headers for output
More information about the checkins
mailing list