summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyramid/router.py14
-rw-r--r--pyramid/tests/test_router.py27
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