summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmos Latteier <amos@latteier.com>2016-06-02 16:39:45 -0700
committerAmos Latteier <amos@latteier.com>2016-06-02 16:39:45 -0700
commitd6c90d154b74107da325a1c45c7a2c4f35ea03c5 (patch)
tree4628412d2a54d2001cfad3328b9a8c0822270239
parentb0d20b5c3fe7df472633899024cdab685483807a (diff)
downloadpyramid-d6c90d154b74107da325a1c45c7a2c4f35ea03c5.tar.gz
pyramid-d6c90d154b74107da325a1c45c7a2c4f35ea03c5.tar.bz2
pyramid-d6c90d154b74107da325a1c45c7a2c4f35ea03c5.zip
Add add_exception_view
-rw-r--r--pyramid/config/views.py65
-rw-r--r--pyramid/tests/test_config/test_views.py84
2 files changed, 149 insertions, 0 deletions
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):