summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <mmerickel@users.noreply.github.com>2016-05-12 11:06:17 -0500
committerMichael Merickel <mmerickel@users.noreply.github.com>2016-05-12 11:06:17 -0500
commitfefc6499ed7356dc47d529c0acecd9c9ad407a88 (patch)
treedbd47208b9814dba6d4edac27e2d3cc8ae1672c6
parenta8cad050d8d0e5095a3bf487132f8d6e315779ec (diff)
parentde61f454cdda890ffa1eebf29dc2df817398a34b (diff)
downloadpyramid-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.rst3
-rw-r--r--pyramid/tests/test_tweens.py73
-rw-r--r--pyramid/tweens.py31
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