summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2017-05-03 22:59:52 -0500
committerMichael Merickel <michael@merickel.org>2017-05-03 22:59:52 -0500
commit3b886e6f39b1c89e78566bce2edacef9bee6d177 (patch)
tree9e2da994ed18dd4f032c7673eb610bfa9c69c7ec
parent3213e20f58d1a0b339e9d5bf9378ec54593624c7 (diff)
downloadpyramid-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.py6
-rw-r--r--pyramid/tweens.py47
-rw-r--r--pyramid/view.py21
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