From d6c90d154b74107da325a1c45c7a2c4f35ea03c5 Mon Sep 17 00:00:00 2001 From: Amos Latteier Date: Thu, 2 Jun 2016 16:39:45 -0700 Subject: Add add_exception_view --- pyramid/config/views.py | 65 +++++++++++++++++++++++++ pyramid/tests/test_config/test_views.py | 84 +++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 198fde5e8..b13885833 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1613,6 +1613,71 @@ class ViewsConfiguratorMixin(object): set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias + @viewdefaults + @action_method + def add_exception_view( + self, + view=None, + context=None, + attr=None, + renderer=None, + wrapper=None, + route_name=None, + request_type=None, + request_method=None, + request_param=None, + containment=None, + xhr=None, + accept=None, + header=None, + path_info=None, + custom_predicates=(), + decorator=None, + mapper=None, + match_param=None, + **view_options + ): + """ Add a view for an exception to the current configuration state. + The view will be called when Pyramid or application code raises an + the given exception. + + .. versionadded:: 1.8 + """ + for arg in ( + 'name', 'permission', 'for_', 'http_cache', + 'require_csrf', 'exception_only', + ): + if arg in view_options: + raise ConfigurationError( + '%s may not be used as an argument to add_exception_view' + % arg + ) + if context is None: + raise ConfigurationError('context exception must be specified') + settings = dict( + view=view, + context=context, + wrapper=wrapper, + renderer=renderer, + request_type=request_type, + request_method=request_method, + request_param=request_param, + containment=containment, + xhr=xhr, + accept=accept, + header=header, + path_info=path_info, + custom_predicates=custom_predicates, + decorator=decorator, + mapper=mapper, + match_param=match_param, + route_name=route_name, + permission=NO_PERMISSION_REQUIRED, + require_csrf=False, + exception_only=True, + ) + return self.add_view(**settings) + @action_method def set_view_mapper(self, mapper): """ diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index c93175ff9..1adde9225 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -1847,6 +1847,90 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.add_view, view, context=NotAnException, exception_only=True ) + def test_add_exception_view(self): + from zope.interface import implementedBy + from pyramid.interfaces import IRequest + from pyramid.renderers import null_renderer + view1 = lambda *arg: 'OK' + config = self._makeOne(autocommit=True) + config.add_exception_view(view=view1, context=Exception, renderer=null_renderer) + wrapper = self._getViewCallable( + config, ctx_iface=implementedBy(Exception), exception_view=True, + ) + context = Exception() + request = self._makeRequest(config) + self.assertEqual(wrapper(context, request), 'OK') + + def test_add_exception_view_disallows_name(self): + config = self._makeOne(autocommit=True) + self.assertRaises(ConfigurationError, + config.add_exception_view, + context=Exception(), + name='foo') + + def test_add_exception_view_disallows_permission(self): + config = self._makeOne(autocommit=True) + self.assertRaises(ConfigurationError, + config.add_exception_view, + context=Exception(), + permission='foo') + + def test_add_exception_view_disallows_for_(self): + config = self._makeOne(autocommit=True) + self.assertRaises(ConfigurationError, + config.add_exception_view, + context=Exception(), + for_='foo') + + def test_add_exception_view_disallows_http_cache(self): + config = self._makeOne(autocommit=True) + self.assertRaises(ConfigurationError, + config.add_exception_view, + context=Exception(), + http_cache='foo') + + def test_add_exception_view_disallows_exception_only(self): + config = self._makeOne(autocommit=True) + self.assertRaises(ConfigurationError, + config.add_exception_view, + context=Exception(), + exception_only=True) + + def test_add_exception_view_requires_context(self): + config = self._makeOne(autocommit=True) + view = lambda *a: 'OK' + self.assertRaises(ConfigurationError, + config.add_exception_view, view=view) + + def test_add_exception_view_with_view_defaults(self): + from pyramid.renderers import null_renderer + from pyramid.exceptions import PredicateMismatch + from pyramid.httpexceptions import HTTPNotFound + from zope.interface import directlyProvides + from zope.interface import implementedBy + class view(object): + __view_defaults__ = { + 'containment':'pyramid.tests.test_config.IDummy' + } + def __init__(self, request): + pass + def __call__(self): + return 'OK' + config = self._makeOne(autocommit=True) + config.add_exception_view( + view=view, + context=Exception, + renderer=null_renderer) + wrapper = self._getViewCallable( + config, ctx_iface=implementedBy(Exception), exception_view=True) + context = DummyContext() + directlyProvides(context, IDummy) + request = self._makeRequest(config) + self.assertEqual(wrapper(context, request), 'OK') + context = DummyContext() + request = self._makeRequest(config) + self.assertRaises(PredicateMismatch, wrapper, context, request) + def test_derive_view_function(self): from pyramid.renderers import null_renderer def view(request): -- cgit v1.2.3