[Checkins] SVN: zope.publisher/branches/3.4/src/zope/publisher/ Backport fix for LP #332061 from trunk.

Uli Fouquet uli at gnufix.de
Tue Jul 7 08:48:15 EDT 2009


Log message for revision 101699:
  Backport fix for LP #332061 from trunk.

Changed:
  U   zope.publisher/branches/3.4/src/zope/publisher/interfaces/__init__.py
  U   zope.publisher/branches/3.4/src/zope/publisher/publish.py
  U   zope.publisher/branches/3.4/src/zope/publisher/tests/test_publisher.py

-=-
Modified: zope.publisher/branches/3.4/src/zope/publisher/interfaces/__init__.py
===================================================================
--- zope.publisher/branches/3.4/src/zope/publisher/interfaces/__init__.py	2009-07-07 12:42:16 UTC (rev 101698)
+++ zope.publisher/branches/3.4/src/zope/publisher/interfaces/__init__.py	2009-07-07 12:48:15 UTC (rev 101699)
@@ -461,3 +461,21 @@
 class IRequest(IPublisherRequest, IPublicationRequest, IApplicationRequest):
     """The basic request contract
     """
+
+
+class IReRaiseException(Interface):
+    """An exception that should be reraised, when handled in publisher.
+
+    Under some circumstances (for instance if acting in a WSGI
+    pipeline with debugger middleware) certain exceptions occuring
+    while publishing should be handled by the Zope machinery and never
+    reach the 'outside world'.
+
+    Adapters providing this interface for a certain exception type
+    which also return ``False`` when being called, indicate by this
+    that the exception should not be reraised during publishing.
+
+    This makes it possible, for instance, to authenticate with
+    basic-auth when a debugger middleware is used and `IUnauthorized`
+    is raised.
+    """

Modified: zope.publisher/branches/3.4/src/zope/publisher/publish.py
===================================================================
--- zope.publisher/branches/3.4/src/zope/publisher/publish.py	2009-07-07 12:42:16 UTC (rev 101698)
+++ zope.publisher/branches/3.4/src/zope/publisher/publish.py	2009-07-07 12:48:15 UTC (rev 101699)
@@ -18,10 +18,10 @@
 $Id$
 """
 import sys
-from zope.publisher.interfaces import Retry
+from zope import component
+from zope.publisher.interfaces import Retry, IReRaiseException
 from zope.proxy import removeAllProxies
 
-
 _marker = object()  # Create a new marker object.
 
 def unwrapMethod(obj):
@@ -138,11 +138,18 @@
                             publication.afterCall(request, obj)
 
                         except:
+                            exc_info = sys.exc_info()
                             publication.handleException(
-                                obj, request, sys.exc_info(), True)
+                                obj, request, exc_info, True)
 
                             if not handle_errors:
-                                raise
+                                # Reraise only if there is no adapter
+                                # indicating that we shouldn't
+                                reraise = component.queryAdapter(
+                                    exc_info[1], IReRaiseException,
+                                    default=None)
+                                if reraise is None or reraise():
+                                    raise
                     finally:
                         publication.endRequest(request, obj)
 

Modified: zope.publisher/branches/3.4/src/zope/publisher/tests/test_publisher.py
===================================================================
--- zope.publisher/branches/3.4/src/zope/publisher/tests/test_publisher.py	2009-07-07 12:42:16 UTC (rev 101698)
+++ zope.publisher/branches/3.4/src/zope/publisher/tests/test_publisher.py	2009-07-07 12:48:15 UTC (rev 101699)
@@ -17,21 +17,18 @@
 """
 import unittest
 
+from zope import component
 from zope.publisher.publish import publish
 from zope.publisher.base import TestRequest
 from zope.publisher.base import DefaultPublication
 from zope.publisher.interfaces import Unauthorized, NotFound, DebugError
-from zope.publisher.interfaces import IPublication
+from zope.publisher.interfaces import IPublication, IReRaiseException
 
 from zope.interface.verify import verifyClass
 from zope.interface import implementedBy
 
 from StringIO import StringIO
 
-class TestPublication(DefaultPublication):
-    # Override handleException to reraise for testing purposes
-    def handleException(self, object, request, exc_info, retry_allowed=1):
-        raise exc_info[0], exc_info[1], exc_info[2]
 
 class PublisherTests(unittest.TestCase):
     def setUp(self):
@@ -58,7 +55,7 @@
         self.app.noDocString = NoDocstringItem()
 
     def _createRequest(self, path, **kw):
-        publication = TestPublication(self.app)
+        publication = DefaultPublication(self.app)
         path = path.split('/')
         path.reverse()
         request = TestRequest(StringIO(''), **kw)
@@ -72,6 +69,15 @@
         publish(request, handle_errors=False)
         return response._result
 
+    def _registerExcAdapter(self, factory):
+        component.provideAdapter(factory, (Unauthorized,), IReRaiseException)
+
+    def _unregisterExcAdapter(self, factory):
+        gsm = component.getGlobalSiteManager()
+        gsm.unregisterAdapter(
+            factory=factory, required=(Unauthorized,),
+            provided=IReRaiseException)
+
     def testImplementsIPublication(self):
         self.failUnless(IPublication.providedBy(
                             DefaultPublication(self.app)))
@@ -97,6 +103,30 @@
     def testDebugError(self):
         self.assertRaises(DebugError, self._publisherResults, '/noDocString')
 
+    def testIReRaiseExceptionAdapters(self):
+        def dontReRaiseAdapter(context):
+            def shouldBeReRaised():
+                return False
+            return shouldBeReRaised
+
+        self._registerExcAdapter(dontReRaiseAdapter)
+        try:
+            self._publisherResults('/_item')
+        except Unauthorized:
+            self.fail('Unauthorized raised though this should '
+                            'not happen')
+        finally:
+            self._unregisterExcAdapter(dontReRaiseAdapter)
+
+        def doReRaiseAdapter(context):
+            def shouldBeReRaised():
+                return True
+            return shouldBeReRaised
+
+        self._registerExcAdapter(doReRaiseAdapter)
+        self.failUnlessRaises(Unauthorized, self._publisherResults, '/_item')
+        self._unregisterExcAdapter(doReRaiseAdapter)
+            
 def test_suite():
     loader = unittest.TestLoader()
     return loader.loadTestsFromTestCase(PublisherTests)



More information about the Checkins mailing list