diff options
| author | Michael Merickel <michael@merickel.org> | 2017-05-23 12:50:58 -0700 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2017-05-23 12:50:58 -0700 |
| commit | 07e0e15fdafb28843a92cd03681a07aa652008a9 (patch) | |
| tree | e83647cd7ddd1e5535212225b17bbf3c0917010c | |
| parent | 37d887705400e0c7631ec26afb972ebe9bfe35d5 (diff) | |
| download | pyramid-07e0e15fdafb28843a92cd03681a07aa652008a9.tar.gz pyramid-07e0e15fdafb28843a92cd03681a07aa652008a9.tar.bz2 pyramid-07e0e15fdafb28843a92cd03681a07aa652008a9.zip | |
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 |
