[Zope-Checkins] SVN: Zope/branches/2.13/ Merge r121832 from trunk to fix LP: #787541
Brian Sutherland
jinty at web.de
Mon May 30 08:04:30 EDT 2011
Log message for revision 121833:
Merge r121832 from trunk to fix LP: #787541
Changed:
U Zope/branches/2.13/doc/CHANGES.rst
U Zope/branches/2.13/src/ZPublisher/WSGIPublisher.py
U Zope/branches/2.13/src/ZPublisher/tests/test_WSGIPublisher.py
-=-
Modified: Zope/branches/2.13/doc/CHANGES.rst
===================================================================
--- Zope/branches/2.13/doc/CHANGES.rst 2011-05-30 11:47:48 UTC (rev 121832)
+++ Zope/branches/2.13/doc/CHANGES.rst 2011-05-30 12:04:30 UTC (rev 121833)
@@ -11,6 +11,10 @@
Bugs Fixed
++++++++++
+- LP #787541: Fix WSGIPublisher to close requests on abort unconditionally.
+ Previously an addAfterCommitHook was used, but this is not run on transaction
+ aborts. Now a Synchronizer is used which unconditionally closes the request
+ after a transaction is finished.
Features Added
++++++++++++++
Modified: Zope/branches/2.13/src/ZPublisher/WSGIPublisher.py
===================================================================
--- Zope/branches/2.13/src/ZPublisher/WSGIPublisher.py 2011-05-30 11:47:48 UTC (rev 121832)
+++ Zope/branches/2.13/src/ZPublisher/WSGIPublisher.py 2011-05-30 12:04:30 UTC (rev 121833)
@@ -200,6 +200,31 @@
return response
+class _RequestCloserForTransaction(object):
+ """Unconditionally close the request at the end of a transaction.
+
+ See transaction.interfaces.ISynchronizer
+ """
+
+ def __init__(self):
+ self.requests = {}
+
+ def add(self, txn, request):
+ assert txn not in self.requests
+ self.requests[txn] = request
+
+ def beforeCompletion(self, txn):
+ pass
+
+ newTransaction = beforeCompletion
+
+ def afterCompletion(self, txn):
+ request = self.requests.pop(txn, None)
+ if request is not None:
+ request.close()
+
+_request_closer_for_repoze_tm = _RequestCloserForTransaction()
+
def publish_module(environ, start_response,
_publish=publish, # only for testing
_response_factory=WSGIResponse, # only for testing
@@ -214,6 +239,13 @@
response._server_version = environ.get('SERVER_SOFTWARE')
request = _request_factory(environ['wsgi.input'], environ, response)
+
+ if 'repoze.tm.active' in environ:
+ # NOTE: registerSynch is a no-op after the first request
+ transaction.manager.registerSynch(_request_closer_for_repoze_tm)
+ txn = transaction.get()
+ _request_closer_for_repoze_tm.add(txn, request)
+
setDefaultSkin(request)
try:
@@ -237,10 +269,7 @@
# XXX This still needs verification that it really works.
result = (stdout.getvalue(), response.body)
- if 'repoze.tm.active' in environ:
- txn = transaction.get()
- txn.addAfterCommitHook(lambda ok: request.close())
- else:
+ if 'repoze.tm.active' not in environ:
request.close() # this aborts the transation!
stdout.close()
Modified: Zope/branches/2.13/src/ZPublisher/tests/test_WSGIPublisher.py
===================================================================
--- Zope/branches/2.13/src/ZPublisher/tests/test_WSGIPublisher.py 2011-05-30 11:47:48 UTC (rev 121832)
+++ Zope/branches/2.13/src/ZPublisher/tests/test_WSGIPublisher.py 2011-05-30 12:04:30 UTC (rev 121833)
@@ -414,6 +414,7 @@
def test_request_not_closed_when_tm_middleware_active(self):
import transaction
+ from ZPublisher import WSGIPublisher
environ = self._makeEnviron()
environ['repoze.tm.active'] = 1
start_response = DummyCallable()
@@ -430,7 +431,22 @@
_request_factory=_request_factory)
self.assertFalse(_request._closed)
txn = transaction.get()
- self.assertTrue(list(txn.getAfterCommitHooks()))
+ self.assertTrue(txn in WSGIPublisher._request_closer_for_repoze_tm.requests)
+ txn.commit()
+ self.assertTrue(_request._closed)
+ self.assertFalse(txn in WSGIPublisher._request_closer_for_repoze_tm.requests)
+ # try again, but this time raise an exception and abort
+ _request._closed = False
+ _publish._raise = Exception('oops')
+ self.assertRaises(Exception, self._callFUT,
+ environ, start_response, _publish,
+ _request_factory=_request_factory)
+ self.assertFalse(_request._closed)
+ txn = transaction.get()
+ self.assertTrue(txn in WSGIPublisher._request_closer_for_repoze_tm.requests)
+ txn.abort()
+ self.assertFalse(txn in WSGIPublisher._request_closer_for_repoze_tm.requests)
+ self.assertTrue(_request._closed)
class DummyRequest(dict):
More information about the Zope-Checkins
mailing list