diff options
| author | Michael Merickel <mmerickel@users.noreply.github.com> | 2016-05-12 11:06:17 -0500 |
|---|---|---|
| committer | Michael Merickel <mmerickel@users.noreply.github.com> | 2016-05-12 11:06:17 -0500 |
| commit | fefc6499ed7356dc47d529c0acecd9c9ad407a88 (patch) | |
| tree | dbd47208b9814dba6d4edac27e2d3cc8ae1672c6 | |
| parent | a8cad050d8d0e5095a3bf487132f8d6e315779ec (diff) | |
| parent | de61f454cdda890ffa1eebf29dc2df817398a34b (diff) | |
| download | pyramid-fefc6499ed7356dc47d529c0acecd9c9ad407a88.tar.gz pyramid-fefc6499ed7356dc47d529c0acecd9c9ad407a88.tar.bz2 pyramid-fefc6499ed7356dc47d529c0acecd9c9ad407a88.zip | |
Merge pull request #2567 from mmerickel/fix/excview-should-reraise-original-exception
fix excview tween to reraise the original exception if left unhandled…
| -rw-r--r-- | docs/api/interfaces.rst | 3 | ||||
| -rw-r--r-- | pyramid/tests/test_tweens.py | 73 | ||||
| -rw-r--r-- | pyramid/tweens.py | 31 |
3 files changed, 97 insertions, 10 deletions
diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index 272820a91..521d65d2b 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -59,6 +59,9 @@ Other Interfaces .. autointerface:: IRenderer :members: + .. autointerface:: IRequestFactory + :members: + .. autointerface:: IResponseFactory :members: diff --git a/pyramid/tests/test_tweens.py b/pyramid/tests/test_tweens.py new file mode 100644 index 000000000..c8eada34c --- /dev/null +++ b/pyramid/tests/test_tweens.py @@ -0,0 +1,73 @@ +import unittest +from pyramid import testing + +class Test_excview_tween_factory(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def _makeOne(self, handler, registry=None): + from pyramid.tweens import excview_tween_factory + if registry is None: + registry = self.config.registry + return excview_tween_factory(handler, registry) + + def test_it_passthrough_no_exception(self): + dummy_response = DummyResponse() + def handler(request): + return dummy_response + tween = self._makeOne(handler) + request = DummyRequest() + result = tween(request) + self.assertTrue(result is dummy_response) + + def test_it_catches_notfound(self): + from pyramid.request import Request + from pyramid.httpexceptions import HTTPNotFound + self.config.add_notfound_view(lambda exc, request: exc) + def handler(request): + raise HTTPNotFound + tween = self._makeOne(handler) + request = Request.blank('/') + result = tween(request) + self.assertEqual(result.status, '404 Not Found') + + def test_it_catches_with_predicate(self): + from pyramid.request import Request + from pyramid.response import Response + def excview(request): + return Response('foo') + self.config.add_view(excview, context=ValueError, request_method='GET') + def handler(request): + raise ValueError + tween = self._makeOne(handler) + request = Request.blank('/') + result = tween(request) + self.assertTrue(b'foo' in result.body) + + def test_it_reraises_on_mismatch(self): + from pyramid.request import Request + def excview(request): pass + self.config.add_view(excview, context=ValueError, request_method='GET') + def handler(request): + raise ValueError + tween = self._makeOne(handler) + request = Request.blank('/') + request.method = 'POST' + self.assertRaises(ValueError, lambda: tween(request)) + + def test_it_reraises_on_no_match(self): + from pyramid.request import Request + def handler(request): + raise ValueError + tween = self._makeOne(handler) + request = Request.blank('/') + self.assertRaises(ValueError, lambda: tween(request)) + +class DummyRequest: + pass + +class DummyResponse: + pass diff --git a/pyramid/tweens.py b/pyramid/tweens.py index d6044dcdc..a842b1133 100644 --- a/pyramid/tweens.py +++ b/pyramid/tweens.py @@ -1,5 +1,7 @@ import sys +from pyramid.compat import reraise +from pyramid.exceptions import PredicateMismatch from pyramid.interfaces import ( IExceptionViewClassifier, IRequest, @@ -38,17 +40,26 @@ def excview_tween_factory(handler, registry): # https://github.com/Pylons/pyramid/issues/700 request_iface = attrs.get('request_iface', IRequest) provides = providedBy(exc) - response = _call_view( - registry, - request, - exc, - provides, - '', - view_classifier=IExceptionViewClassifier, - request_iface=request_iface.combined - ) + try: + response = _call_view( + registry, + request, + exc, + provides, + '', + view_classifier=IExceptionViewClassifier, + request_iface=request_iface.combined + ) + + # if views matched but did not pass predicates, squash the error + # and re-raise the original exception + except PredicateMismatch: + response = None + + # re-raise the original exception as no exception views were + # able to handle the error if response is None: - raise + reraise(*attrs['exc_info']) return response |
