summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2016-03-02 23:46:37 -0600
committerMichael Merickel <michael@merickel.org>2016-03-02 23:46:37 -0600
commitd5225795b3b98b8ef746ba5f9a807eb701d099bb (patch)
tree3794e58109b4c8cdcd6ac0d1d910ecf3cad44cac
parent4ff751448a205d14ad03eeab205e51a17a0c05f9 (diff)
downloadpyramid-d5225795b3b98b8ef746ba5f9a807eb701d099bb.tar.gz
pyramid-d5225795b3b98b8ef746ba5f9a807eb701d099bb.tar.bz2
pyramid-d5225795b3b98b8ef746ba5f9a807eb701d099bb.zip
fix and add tests for invoke_exception_view
-rw-r--r--pyramid/tests/test_view.py132
-rw-r--r--pyramid/view.py7
2 files changed, 136 insertions, 3 deletions
diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py
index e6b9f9e7e..2be47e318 100644
--- a/pyramid/tests/test_view.py
+++ b/pyramid/tests/test_view.py
@@ -673,6 +673,138 @@ class Test_view_defaults(unittest.TestCase):
class Bar(Foo): pass
self.assertEqual(Bar.__view_defaults__, {})
+class TestViewMethodsMixin(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def _makeOne(self, environ=None):
+ from pyramid.decorator import reify
+ from pyramid.view import ViewMethodsMixin
+ if environ is None:
+ environ = {}
+ class Request(ViewMethodsMixin):
+ def __init__(self, environ):
+ self.environ = environ
+
+ @reify
+ def response(self):
+ return DummyResponse()
+ request = Request(environ)
+ request.registry = self.config.registry
+ return request
+
+ def test_it(self):
+ def exc_view(exc, request):
+ self.assertTrue(exc is dummy_exc)
+ self.assertTrue(request.exception is dummy_exc)
+ return DummyResponse(b'foo')
+ self.config.add_view(exc_view, context=RuntimeError)
+ request = self._makeOne()
+ dummy_exc = RuntimeError()
+ try:
+ raise dummy_exc
+ except RuntimeError:
+ response = request.invoke_exception_view()
+ self.assertEqual(response.app_iter, [b'foo'])
+ else: # pragma: no cover
+ self.fail()
+
+ def test_it_hides_attrs(self):
+ def exc_view(exc, request):
+ self.assertTrue(exc is not orig_exc)
+ self.assertTrue(request.exception is not orig_exc)
+ self.assertTrue(request.exc_info is not orig_exc_info)
+ self.assertTrue(request.response is not orig_response)
+ request.response.app_iter = [b'bar']
+ return request.response
+ self.config.add_view(exc_view, context=RuntimeError)
+ request = self._makeOne()
+ orig_exc = request.exception = DummyContext()
+ orig_exc_info = request.exc_info = DummyContext()
+ orig_response = request.response = DummyResponse(b'foo')
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ response = request.invoke_exception_view()
+ self.assertEqual(response.app_iter, [b'bar'])
+ self.assertTrue(request.exception is orig_exc)
+ self.assertTrue(request.exc_info is orig_exc_info)
+ self.assertTrue(request.response is orig_response)
+ else: # pragma: no cover
+ self.fail()
+
+ def test_it_supports_alternate_requests(self):
+ def exc_view(exc, request):
+ self.assertTrue(request is other_req)
+ return DummyResponse(b'foo')
+ self.config.add_view(exc_view, context=RuntimeError)
+ request = self._makeOne()
+ other_req = self._makeOne()
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ response = request.invoke_exception_view(request=other_req)
+ self.assertEqual(response.app_iter, [b'foo'])
+ else: # pragma: no cover
+ self.fail()
+
+ def test_it_supports_threadlocal_registry(self):
+ def exc_view(exc, request):
+ return DummyResponse(b'foo')
+ self.config.add_view(exc_view, context=RuntimeError)
+ request = self._makeOne()
+ del request.registry
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ response = request.invoke_exception_view()
+ self.assertEqual(response.app_iter, [b'foo'])
+ else: # pragma: no cover
+ self.fail()
+
+ def test_it_supports_alternate_exc_info(self):
+ def exc_view(exc, request):
+ self.assertTrue(request.exc_info is exc_info)
+ return DummyResponse(b'foo')
+ self.config.add_view(exc_view, context=RuntimeError)
+ request = self._makeOne()
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ exc_info = sys.exc_info()
+ response = request.invoke_exception_view(exc_info=exc_info)
+ self.assertEqual(response.app_iter, [b'foo'])
+
+ def test_it_rejects_secured_view(self):
+ from pyramid.exceptions import Forbidden
+ def exc_view(exc, request): pass
+ self.config.testing_securitypolicy(permissive=False)
+ self.config.add_view(exc_view, context=RuntimeError, permission='view')
+ request = self._makeOne()
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ self.assertRaises(Forbidden, request.invoke_exception_view)
+ else: # pragma: no cover
+ self.fail()
+
+ def test_it_allows_secured_view(self):
+ def exc_view(exc, request):
+ return DummyResponse(b'foo')
+ self.config.testing_securitypolicy(permissive=False)
+ self.config.add_view(exc_view, context=RuntimeError, permission='view')
+ request = self._makeOne()
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ response = request.invoke_exception_view(secure=False)
+ self.assertEqual(response.app_iter, [b'foo'])
+ else: # pragma: no cover
+ self.fail()
+
class ExceptionResponse(Exception):
status = '404 Not Found'
app_iter = ['Not Found']
diff --git a/pyramid/view.py b/pyramid/view.py
index 16b60b77a..9108f120e 100644
--- a/pyramid/view.py
+++ b/pyramid/view.py
@@ -598,14 +598,15 @@ class ViewMethodsMixin(object):
registry = get_current_registry()
if exc_info is None:
exc_info = sys.exc_info()
+ exc = exc_info[1]
attrs = request.__dict__
- context_iface = providedBy(exc_info[0])
+ context_iface = providedBy(exc)
# clear old generated request.response, if any; it may
# have been mutated by the view, and its state is not
# sane (e.g. caching headers)
with hide_attrs(request, 'exception', 'exc_info', 'response'):
- attrs['exception'] = exc_info[0]
+ attrs['exception'] = exc
attrs['exc_info'] = exc_info
# we use .get instead of .__getitem__ below due to
# https://github.com/Pylons/pyramid/issues/700
@@ -613,7 +614,7 @@ class ViewMethodsMixin(object):
response = _call_view(
registry,
request,
- exc_info[0],
+ exc,
context_iface,
'',
view_types=None,