[Repoze-checkins] r961 - in repoze.zope2/trunk: . repoze/zope2 repoze/zope2/tests
Chris McDonough
chrism at agendaless.com
Mon May 5 22:47:33 EDT 2008
Author: Chris McDonough <chrism at agendaless.com>
Date: Mon May 5 22:47:33 2008
New Revision: 961
Log:
- ZServer didn't call app_iter.close after it finished a request as
required by the WSGI spec (found via Paste#lint).
Modified:
repoze.zope2/trunk/CHANGES.txt
repoze.zope2/trunk/repoze/zope2/server.py
repoze.zope2/trunk/repoze/zope2/tests/test_server.py
Modified: repoze.zope2/trunk/CHANGES.txt
==============================================================================
--- repoze.zope2/trunk/CHANGES.txt (original)
+++ repoze.zope2/trunk/CHANGES.txt Mon May 5 22:47:33 2008
@@ -1,3 +1,8 @@
+After 0.3.8
+
+ - ZServer didn't call app_iter.close after it finished a request as
+ required by the WSGI spec (found via Paste#lint).
+
0.3.8 (2008-05-02)
- Cause zope2testrunner to sys.exit with a nonzero exit code when
Modified: repoze.zope2/trunk/repoze/zope2/server.py
==============================================================================
--- repoze.zope2/trunk/repoze/zope2/server.py (original)
+++ repoze.zope2/trunk/repoze/zope2/server.py Mon May 5 22:47:33 2008
@@ -16,12 +16,14 @@
# Use the WSGI component of the zope3 reimplementation of ZServer
-from zope.server.http import wsgihttpserver
-import sys
import re
+import sys
+import traceback
+
+from zope.server.http import wsgihttpserver
class ZServer(wsgihttpserver.WSGIHTTPServer):
- def executeRequest(self, task):
+ def executeRequest(self, task, stderr=sys.stderr):
"""Overrides WSGIHTTPServer's executeRequest so it accepts the
optional exc_info argument (although it does nothing with it) """
env = task.getCGIEnvironment()
@@ -34,7 +36,7 @@
# extend wsgihttpserver environment with PEP-333-mandated envvars
env['wsgi.version'] = (1,0)
env['wsgi.url_scheme'] = 'http'
- env['wsgi.errors'] = sys.stderr
+ env['wsgi.errors'] = stderr
env['wsgi.multithread'] = 1
env['wsgi.multiprocess'] = 0
env['wsgi.run_once'] = 0
@@ -49,7 +51,13 @@
return wsgihttpserver.fakeWrite
# Call the application to handle the request and write a response
- task.write(self.application(env, start_response))
+ iterator = self.application(env, start_response)
+ task.write(iterator)
+ if hasattr(iterator, 'close'):
+ try:
+ iterator.close()
+ except:
+ traceback.print_exc(file=env['wsgi.errors'])
def get_zserver(wsgi_app, host, port, threads):
from zope.server.taskthreads import ThreadedTaskDispatcher
Modified: repoze.zope2/trunk/repoze/zope2/tests/test_server.py
==============================================================================
--- repoze.zope2/trunk/repoze/zope2/tests/test_server.py (original)
+++ repoze.zope2/trunk/repoze/zope2/tests/test_server.py Mon May 5 22:47:33 2008
@@ -18,3 +18,67 @@
self.assertEqual(server.server_name, 'localhost')
self.assertEqual(server.port, 66666)
self.assertEqual(len(server.task_dispatcher.threads), 20)
+
+ def test_zserver_executeRequest_closes_app_iter(self):
+ from repoze.zope2.server import ZServer
+ host = 'localhost'
+ port = '199764'
+ td = None
+ from StringIO import StringIO
+ io = StringIO()
+ wsgi_app = FakeApp(io)
+ server = ZServer(wsgi_app, ip=host, port=int(port), task_dispatcher=td)
+ try:
+ env = {'CHANNEL_CREATION_TIME':1}
+ task = FakeTask(env)
+ server.executeRequest(task)
+ self.assertEqual(io.closed, True)
+ finally:
+ server.close()
+
+ def test_zserver_executeRequest_app_iter_close_raises(self):
+ from repoze.zope2.server import ZServer
+ host = 'localhost'
+ port = '199764'
+ td = None
+ from StringIO import StringIO
+ io = StringIO()
+ def close():
+ raise ValueError, 'foo'
+ io.close = close
+ wsgi_app = FakeApp(io)
+ server = ZServer(wsgi_app, ip=host, port=int(port), task_dispatcher=td)
+ try:
+ env = {'CHANNEL_CREATION_TIME':1}
+ task = FakeTask(env)
+ errors = StringIO()
+ server.executeRequest(task, errors)
+ self.assertEqual(io.closed, False)
+ errorval = errors.getvalue()
+ self.failUnless(errorval.find('ValueError')!=-1, errorval)
+ finally:
+ server.close()
+
+class FakeRequestData:
+ def getBodyStream(self):
+ from StringIO import StringIO
+ return StringIO()
+
+class FakeTask:
+ def __init__(self, env):
+ self.env = env
+ self.request_data = FakeRequestData()
+ def getCGIEnvironment(self):
+ return self.env
+ def write(self, app_iter):
+ self.app_iter = app_iter
+
+class FakeApp:
+ def __init__(self, io):
+ self.io = io
+ def __call__(self, environ, start_response):
+ self.environ = environ
+ self.start_response = start_response
+ return self.io
+
+
More information about the Repoze-checkins
mailing list