[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