diff options
| author | Michael Merickel <michael@merickel.org> | 2017-05-03 22:59:52 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2017-05-03 22:59:52 -0500 |
| commit | 3b886e6f39b1c89e78566bce2edacef9bee6d177 (patch) | |
| tree | 9e2da994ed18dd4f032c7673eb610bfa9c69c7ec | |
| parent | 3213e20f58d1a0b339e9d5bf9378ec54593624c7 (diff) | |
| download | pyramid-3b886e6f39b1c89e78566bce2edacef9bee6d177.tar.gz pyramid-3b886e6f39b1c89e78566bce2edacef9bee6d177.tar.bz2 pyramid-3b886e6f39b1c89e78566bce2edacef9bee6d177.zip | |
normalize excview tween to use ``request.invoke_exception_view``
``request.exception`` and ``request.exc_info`` are set to the
exception used to render the response but they are reset to their
original values if no response could be rendered
minor incompatibility in that ``request.response`` is restored after the
excview tween but should not be an issue because a response is returned
thus request.response should be ignored by anyone who cares.
| -rw-r--r-- | pyramid/tests/test_view.py | 6 | ||||
| -rw-r--r-- | pyramid/tweens.py | 47 | ||||
| -rw-r--r-- | pyramid/view.py | 21 |
3 files changed, 24 insertions, 50 deletions
diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index cab42cf48..2061515b3 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -778,11 +778,11 @@ class TestViewMethodsMixin(unittest.TestCase): orig_response = request.response = DummyResponse(b'foo') try: raise RuntimeError - except RuntimeError: + except RuntimeError as ex: 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.exception is ex) + self.assertTrue(request.exc_info[1] is ex) self.assertTrue(request.response is orig_response) else: # pragma: no cover self.fail() diff --git a/pyramid/tweens.py b/pyramid/tweens.py index 673429b06..c9b3bd4b8 100644 --- a/pyramid/tweens.py +++ b/pyramid/tweens.py @@ -1,55 +1,18 @@ import sys from pyramid.compat import reraise -from pyramid.exceptions import PredicateMismatch -from pyramid.interfaces import ( - IExceptionViewClassifier, - IRequest, - ) - -from zope.interface import providedBy -from pyramid.view import _call_view +from pyramid.httpexceptions import HTTPNotFound def _error_handler(request, exc): # NOTE: we do not need to delete exc_info because this function # should never be in the call stack of the exception exc_info = sys.exc_info() - attrs = request.__dict__ - attrs['exc_info'] = exc_info - attrs['exception'] = 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) - if 'response' in attrs: - del attrs['response'] - # we use .get instead of .__getitem__ below due to - # https://github.com/Pylons/pyramid/issues/700 - request_iface = attrs.get('request_iface', IRequest) - provides = providedBy(exc) try: - response = _call_view( - request.registry, - request, - exc, - provides, - '', - view_classifier=IExceptionViewClassifier, - request_iface=request_iface.combined - ) - - # if views matched but did not pass predicates then treat the - # same as not finding any matching views - except PredicateMismatch: - response = None - - # re-raise the original exception as no exception views were - # able to handle the error - if response is None: - if 'exception' in attrs: - del attrs['exception'] - if 'exc_info' in attrs: - del attrs['exc_info'] + response = request.invoke_exception_view(exc_info) + except HTTPNotFound: + # re-raise the original exception as no exception views were + # able to handle the error reraise(*exc_info) return response diff --git a/pyramid/view.py b/pyramid/view.py index 498bdde45..3ce984209 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -657,8 +657,14 @@ class ViewMethodsMixin(object): This method returns a :term:`response` object or raises :class:`pyramid.httpexceptions.HTTPNotFound` if a matching view cannot - be found.""" + be found. + If a response is generated then ``request.exception`` and + ``request.exc_info`` will be left at the values used to render the + response. Otherwise the previous values for ``request.exception`` and + ``request.exc_info`` will be restored. + + """ if request is None: request = self registry = getattr(request, 'registry', None) @@ -673,7 +679,7 @@ class ViewMethodsMixin(object): # 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'): + with hide_attrs(request, 'response', 'exc_info', 'exception'): attrs['exception'] = exc attrs['exc_info'] = exc_info # we use .get instead of .__getitem__ below due to @@ -690,6 +696,11 @@ class ViewMethodsMixin(object): secure=secure, request_iface=request_iface.combined, ) - if response is None: - raise HTTPNotFound - return response + + if response is None: + raise HTTPNotFound + + # successful response, overwrite exception/exc_info + attrs['exception'] = exc + attrs['exc_info'] = exc_info + return response |
