[Checkins] SVN: zope.server/trunk/ - When the result of a WSGI application was received, ``task.write()`` was
Stephan Richter
srichter at gmail.com
Tue Aug 24 15:12:50 EDT 2010
Log message for revision 115921:
- When the result of a WSGI application was received, ``task.write()`` was
only called once to transmit the data. This prohibited the transmission of
partial results. Now the WSGI server iterates through the result itself
making multiple ``task.write()`` calls, which will cause partial data to be
transmitted.
- Created a second test case instance for the post-mortem WSGI server, so it
is tested as well.
- Get ready for release.
Changed:
U zope.server/trunk/CHANGES.txt
U zope.server/trunk/setup.py
U zope.server/trunk/src/zope/server/dualmodechannel.py
U zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py
U zope.server/trunk/src/zope/server/http/wsgihttpserver.py
-=-
Modified: zope.server/trunk/CHANGES.txt
===================================================================
--- zope.server/trunk/CHANGES.txt 2010-08-24 15:30:57 UTC (rev 115920)
+++ zope.server/trunk/CHANGES.txt 2010-08-24 19:12:50 UTC (rev 115921)
@@ -3,9 +3,18 @@
=======
-3.8.1 (unreleased)
+3.8.1 (2010-08-24)
------------------
+- When the result of a WSGI application was received, ``task.write()`` was
+ only called once to transmit the data. This prohibited the transmission of
+ partial results. Now the WSGI server iterates through the result itself
+ making multiple ``task.write()`` calls, which will cause partial data to be
+ transmitted.
+
+- Created a second test case instance for the post-mortem WSGI server, so it
+ is tested as well.
+
- Using python's ``doctest`` module instead of deprecated
``zope.testing.doctest``.
Modified: zope.server/trunk/setup.py
===================================================================
--- zope.server/trunk/setup.py 2010-08-24 15:30:57 UTC (rev 115920)
+++ zope.server/trunk/setup.py 2010-08-24 19:12:50 UTC (rev 115921)
@@ -26,7 +26,7 @@
setup(
name='zope.server',
- version = '3.8.1dev',
+ version = '3.8.1',
author='Zope Foundation and Contributors',
author_email='zope-dev at zope.org',
description='Zope Server (Web and FTP)',
Modified: zope.server/trunk/src/zope/server/dualmodechannel.py
===================================================================
--- zope.server/trunk/src/zope/server/dualmodechannel.py 2010-08-24 15:30:57 UTC (rev 115920)
+++ zope.server/trunk/src/zope/server/dualmodechannel.py 2010-08-24 19:12:50 UTC (rev 115921)
@@ -154,7 +154,7 @@
if isinstance(data, str):
if data:
self.outbuf.append(data)
- wrote = len(data)
+ wrote = len(data)
else:
for v in data:
if v:
Modified: zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py
===================================================================
--- zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py 2010-08-24 15:30:57 UTC (rev 115920)
+++ zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py 2010-08-24 19:12:50 UTC (rev 115921)
@@ -131,10 +131,13 @@
class Tests(PlacelessSetup, unittest.TestCase):
- def setUp(self):
+ def _getServerClass(self):
# import only now to prevent the testrunner from importing it too early
# Otherwise dualmodechannel.the_trigger is closed by the ZEO tests
from zope.server.http.wsgihttpserver import WSGIHTTPServer
+ return WSGIHTTPServer
+
+ def setUp(self):
super(Tests, self).setUp()
zope.component.provideAdapter(HTTPCharsets, [IHTTPRequest],
IUserPreferredCharsets, '')
@@ -156,8 +159,9 @@
td.setThreadCount(4)
# Bind to any port on localhost.
- self.server = WSGIHTTPServer(application, 'Browser',
- LOCALHOST, 0, task_dispatcher=td)
+ ServerClass = self._getServerClass()
+ self.server = ServerClass(application, 'Browser',
+ LOCALHOST, 0, task_dispatcher=td)
self.port = self.server.socket.getsockname()[1]
self.run_loop = 1
@@ -290,10 +294,17 @@
'https://zope.org:8080/wsgi/proxy_host')
self.assertEqual('zope.org:8080', response_body)
- def test_server_uses_iterable(self):
- # Make sure that the task write method isn't called with a
- # str or non iterable
+ def test_ensure_multiple_task_write_calls(self):
+ # In order to get data out as fast as possible, the WSGI server needs
+ # to call task.write() multiple times.
+ orig_app = self.server.application
+ def app(eviron, start_response):
+ start_response('200 Ok', [])
+ return ['This', 'is', 'my', 'response.']
+ self.server.application = app
+
class FakeTask:
+ counter = 0
getCGIEnvironment = lambda _: {}
class request_data:
getBodyStream = lambda _: StringIO.StringIO()
@@ -301,14 +312,39 @@
setResponseStatus = appendResponseHeaders = lambda *_: None
def write(self, v):
- if isinstance(v, str):
- raise TypeError("Should only write iterables")
- list(v)
- self.server.executeRequest(FakeTask())
+ self.counter += 1
+ task = FakeTask()
+ self.server.executeRequest(task)
+ self.assertEqual(task.counter, 4)
+ self.server.application = orig_app
+
+
+class PMDBTests(Tests):
+
+ def _getServerClass(self):
+ # import only now to prevent the testrunner from importing it too early
+ # Otherwise dualmodechannel.the_trigger is closed by the ZEO tests
+ from zope.server.http.wsgihttpserver import PMDBWSGIHTTPServer
+ return PMDBWSGIHTTPServer
+
+ def testWSGIVariables(self):
+ # Assert that the environment contains all required WSGI variables
+ status, response_body = self.invokeRequest('/wsgi')
+ wsgi_variables = set(response_body.split())
+ self.assertEqual(wsgi_variables,
+ set(['wsgi.version', 'wsgi.url_scheme', 'wsgi.input',
+ 'wsgi.errors', 'wsgi.multithread',
+ 'wsgi.multiprocess', 'wsgi.handleErrors',
+ 'wsgi.run_once']))
+
+
def test_suite():
- return unittest.TestSuite(unittest.makeSuite(Tests))
+ return unittest.TestSuite((
+ unittest.makeSuite(Tests),
+ unittest.makeSuite(PMDBTests),
+ ))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
Modified: zope.server/trunk/src/zope/server/http/wsgihttpserver.py
===================================================================
--- zope.server/trunk/src/zope/server/http/wsgihttpserver.py 2010-08-24 15:30:57 UTC (rev 115920)
+++ zope.server/trunk/src/zope/server/http/wsgihttpserver.py 2010-08-24 19:12:50 UTC (rev 115921)
@@ -86,7 +86,11 @@
return fakeWrite
# Call the application to handle the request and write a response
- task.write(self.application(env, start_response))
+ result = self.application(env, start_response)
+ # By iterating manually at this point, we execute task.write()
+ # multiple times, allowing partial data to be sent.
+ for value in result:
+ task.write(value)
class PMDBWSGIHTTPServer(WSGIHTTPServer):
@@ -108,7 +112,11 @@
# Call the application to handle the request and write a response
try:
- task.write(self.application(env, start_response))
+ result = self.application(env, start_response)
+ # By iterating manually at this point, we execute task.write()
+ # multiple times, allowing partial data to be sent.
+ for value in result:
+ task.write(value)
except:
import sys, pdb
print "%s:" % sys.exc_info()[0]
More information about the checkins
mailing list