[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