[Checkins] SVN: Zope/branches/2.12/ Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.

Martin Aspeli optilude at gmx.net
Fri Nov 13 00:59:42 EST 2009


Log message for revision 105589:
  Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
  This event is fired just before IPubFailure, but, crucially, while the transaction is still open.

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/ZPublisher/Publish.py
  U   Zope/branches/2.12/src/ZPublisher/interfaces.py
  U   Zope/branches/2.12/src/ZPublisher/pubevents.py
  U   Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===================================================================
--- Zope/branches/2.12/doc/CHANGES.rst	2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/doc/CHANGES.rst	2009-11-13 05:59:41 UTC (rev 105589)
@@ -11,6 +11,10 @@
 Features Added
 ++++++++++++++
 
+- Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
+  This event is fired just before IPubFailure, but, crucially, while the
+  transaction is still open.
+
 - Include bytes limited cache size in the cache parameters ZMI screen.
 
 - Officially supporting Python 2.6 only (with inofficial support for

Modified: Zope/branches/2.12/src/ZPublisher/Publish.py
===================================================================
--- Zope/branches/2.12/src/ZPublisher/Publish.py	2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/Publish.py	2009-11-13 05:59:41 UTC (rev 105589)
@@ -27,7 +27,7 @@
 from zope.event import notify
 
 from pubevents import PubStart, PubSuccess, PubFailure, \
-     PubBeforeCommit, PubAfterTraversal
+     PubBeforeCommit, PubAfterTraversal, PubBeforeAbort
 
 class Retry(Exception):
     """Raise this to retry a request
@@ -173,8 +173,12 @@
                                         )
                     retry = True
             finally:
+                
                 # Note: 'abort's can fail. Nevertheless, we want end request handling
                 try: 
+                    
+                    notify(PubBeforeAbort(request, exc_info, retry))
+                    
                     if transactions_manager:
                         transactions_manager.abort()
                 finally:
@@ -196,6 +200,9 @@
         else:
             # Note: 'abort's can fail. Nevertheless, we want end request handling
             try:
+                
+                notify(PubBeforeAbort(request, exc_info, False))
+                
                 if transactions_manager:
                     transactions_manager.abort()
             finally:

Modified: Zope/branches/2.12/src/ZPublisher/interfaces.py
===================================================================
--- Zope/branches/2.12/src/ZPublisher/interfaces.py	2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/interfaces.py	2009-11-13 05:59:41 UTC (rev 105589)
@@ -41,5 +41,12 @@
 
 class IPubBeforeCommit(IPubEvent):
     """notified immediately before the transaction commit (i.e. after the main
-    request processing is finished.
+    request processing is finished).
     """
+
+class IPubBeforeAbort(IPubEvent):
+    """notified immediately before the transaction abort (i.e. after the main
+    request processing is finished, and there was an error).
+    """
+    exc_info = Attribute('''The exception info as returned by 'sys.exc_info()'.''')
+    retry = Attribute('Whether the request will be retried')

Modified: Zope/branches/2.12/src/ZPublisher/pubevents.py
===================================================================
--- Zope/branches/2.12/src/ZPublisher/pubevents.py	2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/pubevents.py	2009-11-13 05:59:41 UTC (rev 105589)
@@ -10,7 +10,7 @@
 from zope.interface import implements
 
 from interfaces import IPubStart, IPubSuccess, IPubFailure, \
-     IPubAfterTraversal, IPubBeforeCommit
+     IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort
 
 class _Base(object):
     """PubEvent base class."""
@@ -42,3 +42,10 @@
 class PubBeforeCommit(_Base):
     """notified immediately before the commit."""
     implements(IPubBeforeCommit)
+
+class PubBeforeAbort(_Base):
+    """notified immediately before an abort."""
+    implements(IPubBeforeAbort)
+    
+    def __init__(self, request, exc_info, retry):
+        self.request, self.exc_info, self.retry = request, exc_info, retry

Modified: Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py
===================================================================
--- Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py	2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py	2009-11-13 05:59:41 UTC (rev 105589)
@@ -8,7 +8,7 @@
 from ZPublisher.Publish import publish, Retry
 from ZPublisher.BaseRequest import BaseRequest
 from ZPublisher.pubevents import PubStart, PubSuccess, PubFailure, \
-     PubAfterTraversal, PubBeforeCommit
+     PubAfterTraversal, PubBeforeCommit, PubBeforeAbort
 from ZPublisher.interfaces import \
      IPubStart, IPubEnd, IPubSuccess, IPubFailure, \
      IPubAfterTraversal, IPubBeforeCommit
@@ -74,40 +74,58 @@
         r = self.request; r.action = 'fail_return'
         publish(r, PUBMODULE, [None])
         events = self.reporter.events
-        self.assertEqual(len(events), 2)
+        self.assertEqual(len(events), 3)
         self.assert_(isinstance(events[0], PubStart))
         self.assertEqual(events[0].request, r)
-        self.assert_(isinstance(events[1], PubFailure))
+        self.assert_(isinstance(events[1], PubBeforeAbort))
         self.assertEqual(events[1].request, r)
         self.assertEqual(events[1].retry, False)
-        self.assertEqual(len(events[1].exc_info), 3)
+        self.assert_(isinstance(events[2], PubFailure))
+        self.assertEqual(events[2].request, r)
+        self.assertEqual(events[2].retry, False)
+        self.assertEqual(len(events[2].exc_info), 3)
 
     def testFailureException(self):
         r = self.request; r.action = 'fail_exception'
         self.assertRaises(Exception, publish, r, PUBMODULE, [None])
         events = self.reporter.events
-        self.assertEqual(len(events), 2)
+        self.assertEqual(len(events), 3)
         self.assert_(isinstance(events[0], PubStart))
         self.assertEqual(events[0].request, r)
-        self.assert_(isinstance(events[1], PubFailure))
+        self.assert_(isinstance(events[1], PubBeforeAbort))
         self.assertEqual(events[1].request, r)
         self.assertEqual(events[1].retry, False)
         self.assertEqual(len(events[1].exc_info), 3)
+        self.assert_(isinstance(events[2], PubFailure))
+        self.assertEqual(events[2].request, r)
+        self.assertEqual(events[2].retry, False)
+        self.assertEqual(len(events[2].exc_info), 3)
 
     def testFailureConflict(self):
         r = self.request; r.action = 'conflict'
         publish(r, PUBMODULE, [None])
         events = self.reporter.events
-        self.assertEqual(len(events), 6)
+        self.assertEqual(len(events), 7)
+        
         self.assert_(isinstance(events[0], PubStart))
         self.assertEqual(events[0].request, r)
-        self.assert_(isinstance(events[1], PubFailure))
+        
+        self.assert_(isinstance(events[1], PubBeforeAbort))
         self.assertEqual(events[1].request, r)
         self.assertEqual(events[1].retry, True)
         self.assertEqual(len(events[1].exc_info), 3)
         self.assert_(isinstance(events[1].exc_info[1], ConflictError))
-        self.assert_(isinstance(events[2], PubStart))
-        self.assert_(isinstance(events[5], PubSuccess))
+        
+        self.assert_(isinstance(events[2], PubFailure))
+        self.assertEqual(events[2].request, r)
+        self.assertEqual(events[2].retry, True)
+        self.assertEqual(len(events[2].exc_info), 3)
+        self.assert_(isinstance(events[2].exc_info[1], ConflictError))
+        
+        self.assert_(isinstance(events[3], PubStart))
+        self.assert_(isinstance(events[4], PubAfterTraversal))
+        self.assert_(isinstance(events[5], PubBeforeCommit))
+        self.assert_(isinstance(events[6], PubSuccess))
 
 # Auxiliaries
 def _succeed():



More information about the checkins mailing list