diff options
| author | Bert JW Regeer <xistence@0x58.com> | 2017-05-23 14:18:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-23 14:18:24 -0700 |
| commit | 636d45bbad90a84048a5e3e8952678d08cb24e96 (patch) | |
| tree | dc1e80a87882df778b8e781cd58e4a042ac8b67e | |
| parent | 50d216a549bc848f411769690d722d367c91fdb4 (diff) | |
| parent | 07e0e15fdafb28843a92cd03681a07aa652008a9 (diff) | |
| download | pyramid-636d45bbad90a84048a5e3e8952678d08cb24e96.tar.gz pyramid-636d45bbad90a84048a5e3e8952678d08cb24e96.tar.bz2 pyramid-636d45bbad90a84048a5e3e8952678d08cb24e96.zip | |
Merge pull request #3061 from Pylons/render-last-exception
allow the execution policy to perform a last-ditch effort to render an exception view
| -rw-r--r-- | pyramid/router.py | 14 | ||||
| -rw-r--r-- | pyramid/tests/test_router.py | 27 |
2 files changed, 39 insertions, 2 deletions
diff --git a/pyramid/router.py b/pyramid/router.py index 8b7b7b6bc..7f3f9fbea 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -1,3 +1,4 @@ +import sys from zope.interface import ( implementer, providedBy, @@ -24,6 +25,7 @@ from pyramid.events import ( BeforeTraversal, ) +from pyramid.compat import reraise from pyramid.httpexceptions import HTTPNotFound from pyramid.request import Request from pyramid.view import _call_view @@ -252,7 +254,15 @@ class Router(object): response = self.execution_policy(environ, self) return response(environ, start_response) - def default_execution_policy(environ, router): request = router.make_request(environ) - return router.invoke_request(request) + try: + return router.invoke_request(request) + except Exception: + exc_info = sys.exc_info() + try: + return request.invoke_exception_view(exc_info) + except HTTPNotFound: + reraise(*exc_info) + finally: + del exc_info # avoid local ref cycle diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index a5da5c627..bd023824c 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -1284,6 +1284,33 @@ class TestRouter(unittest.TestCase): self.assertEqual(resp.status_code, 200) self.assertEqual(resp.body, b'foo') + def test_execution_policy_handles_exception(self): + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IExceptionViewClassifier + from pyramid.interfaces import IRequest + class Exception1(Exception): + pass + class Exception2(Exception): + pass + req_iface = self._registerRouteRequest('foo') + self._connectRoute('foo', 'archives/:action/:article', None) + view = DummyView(DummyResponse(), raise_exception=Exception1) + self._registerView(view, '', IViewClassifier, req_iface, None) + exception_view1 = DummyView(DummyResponse(), + raise_exception=Exception2) + self._registerView(exception_view1, '', IExceptionViewClassifier, + IRequest, Exception1) + response = DummyResponse() + response.app_iter = ["Hello, world"] + exception_view2 = DummyView(response) + self._registerView(exception_view2, '', IExceptionViewClassifier, + IRequest, Exception2) + environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') + start_response = DummyStartResponse() + router = self._makeOne() + result = router(environ, start_response) + self.assertEqual(result, ["Hello, world"]) + class DummyPredicate(object): def __call__(self, info, request): return True |
