diff options
| author | Amos Latteier <amos@latteier.com> | 2016-06-02 17:03:18 -0700 |
|---|---|---|
| committer | Amos Latteier <amos@latteier.com> | 2016-06-02 17:03:18 -0700 |
| commit | 93c94b9ea69d25da63604e494f89d8c619e7babb (patch) | |
| tree | a64d97777d74fe4936cfe9c98ae2a6ac8898d365 | |
| parent | d6c90d154b74107da325a1c45c7a2c4f35ea03c5 (diff) | |
| download | pyramid-93c94b9ea69d25da63604e494f89d8c619e7babb.tar.gz pyramid-93c94b9ea69d25da63604e494f89d8c619e7babb.tar.bz2 pyramid-93c94b9ea69d25da63604e494f89d8c619e7babb.zip | |
Add exception_view_config decorator.
| -rw-r--r-- | pyramid/tests/test_view.py | 46 | ||||
| -rw-r--r-- | pyramid/view.py | 51 |
2 files changed, 95 insertions, 2 deletions
diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index 2de44d579..d18c6eca4 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -132,7 +132,49 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase): self.assertEqual(settings[0]['view'], None) # comes from call_venusian self.assertEqual(settings[0]['attr'], 'view') self.assertEqual(settings[0]['_info'], 'codeinfo') - + +class Test_exception_view_config(BaseTest, unittest.TestCase): + def _makeOne(self, **kw): + from pyramid.view import exception_view_config + return exception_view_config(**kw) + + def test_ctor(self): + inst = self._makeOne(context=Exception, path_info='path_info') + self.assertEqual(inst.__dict__, + {'context':Exception, 'path_info':'path_info'}) + + def test_it_function(self): + def view(request): pass + decorator = self._makeOne(context=Exception, renderer='renderer') + venusian = DummyVenusian() + decorator.venusian = venusian + wrapped = decorator(view) + self.assertTrue(wrapped is view) + config = call_venusian(venusian) + settings = config.settings + self.assertEqual( + settings, + [{'venusian': venusian, 'context': Exception, + 'renderer': 'renderer', '_info': 'codeinfo', 'view': None}] + ) + + def test_it_class(self): + decorator = self._makeOne() + venusian = DummyVenusian() + decorator.venusian = venusian + decorator.venusian.info.scope = 'class' + class view(object): pass + wrapped = decorator(view) + self.assertTrue(wrapped is view) + config = call_venusian(venusian) + settings = config.settings + self.assertEqual(len(settings), 1) + self.assertEqual(len(settings[0]), 4) + self.assertEqual(settings[0]['venusian'], venusian) + self.assertEqual(settings[0]['view'], None) # comes from call_venusian + self.assertEqual(settings[0]['attr'], 'view') + self.assertEqual(settings[0]['_info'], 'codeinfo') + class RenderViewToResponseTests(BaseTest, unittest.TestCase): def _callFUT(self, *arg, **kw): from pyramid.view import render_view_to_response @@ -898,7 +940,7 @@ class DummyConfig(object): def add_view(self, **kw): self.settings.append(kw) - add_notfound_view = add_forbidden_view = add_view + add_notfound_view = add_forbidden_view = add_exception_view = add_view def with_package(self, pkg): self.pkg = pkg diff --git a/pyramid/view.py b/pyramid/view.py index 88c6397af..5a9f2a068 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -463,6 +463,57 @@ class forbidden_view_config(object): settings['_info'] = info.codeinfo # fbo "action_method" return wrapped +class exception_view_config(object): + """ + .. versionadded:: 1.8 + + An analogue of :class:`pyramid.view.view_config` which registers an + exception view. + + The exception_view_config constructor requires an exception context, and + additionally accepts most of the same argumenta as the constructor of + :class:`pyramid.view.view_config`. It can be used in the same places, + and behaves in largely the same way, except it always registers an exception + view instead of a 'normal' view. + + Example: + + .. code-block:: python + + from pyramid.view import exception_view_config + from pyramid.response import Response + + @exception_view_config(context=ValueError) + def error_view(request): + return Response('A value error ocurred') + + All arguments passed to this function have the same meaning as + :meth:`pyramid.view.view_config` and each predicate argument restricts + the set of circumstances under which this exception view will be invoked. + """ + + def __init__(self, **settings): + self.__dict__.update(settings) + + def __call__(self, wrapped): + settings = self.__dict__.copy() + + def callback(context, name, ob): + config = context.config.with_package(info.module) + config.add_exception_view(view=ob, **settings) + + info = self.venusian.attach(wrapped, callback, category='pyramid') + + if info.scope == 'class': + # if the decorator was attached to a method in a class, or + # otherwise executed at class scope, we need to set an + # 'attr' into the settings if one isn't already in there + if settings.get('attr') is None: + settings['attr'] = wrapped.__name__ + + settings['_info'] = info.codeinfo # fbo "action_method" + return wrapped + def _find_views( registry, request_iface, |
