summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt11
-rw-r--r--pyramid/tests/test_router.py11
-rw-r--r--pyramid/tweens.py16
3 files changed, 26 insertions, 12 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index d82b3b641..ed70d7036 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,14 @@
+Next release
+============
+
+Features
+--------
+
+- We no longer eagerly clear ``request.exception`` and ``request.exc_info`` in
+ the exception view tween. This makes it possible to inspect exception
+ information within a finished callback. See
+ https://github.com/Pylons/pyramid/issues/1223.
+
1.5a4 (2014-01-28)
==================
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index b836d7d72..838e52db0 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -830,7 +830,8 @@ class TestRouter(unittest.TestCase):
self._registerTraverserFactory(context, subpath=[''])
response = DummyResponse()
response.app_iter = ['OK']
- view = DummyView(response, raise_exception=RuntimeError)
+ error = RuntimeError()
+ view = DummyView(response, raise_exception=error)
environ = self._makeEnviron()
def exception_view(context, request):
self.assertEqual(request.exc_info[0], RuntimeError)
@@ -842,9 +843,11 @@ class TestRouter(unittest.TestCase):
start_response = DummyStartResponse()
result = router(environ, start_response)
self.assertEqual(result, ['OK'])
- # we clean up the exc_info and exception after the request
- self.assertEqual(request.exception, None)
- self.assertEqual(request.exc_info, None)
+ # exc_info and exception should still be around on the request after
+ # the excview tween has run (see
+ # https://github.com/Pylons/pyramid/issues/1223)
+ self.assertEqual(request.exception, error)
+ self.assertEqual(request.exc_info[:2], (RuntimeError, error,))
def test_call_view_raises_exception_view(self):
from pyramid.interfaces import IViewClassifier
diff --git a/pyramid/tweens.py b/pyramid/tweens.py
index cf2238deb..831de8481 100644
--- a/pyramid/tweens.py
+++ b/pyramid/tweens.py
@@ -20,8 +20,14 @@ def excview_tween_factory(handler, registry):
try:
response = handler(request)
except Exception as exc:
- # WARNING: do not assign the result of sys.exc_info() to a
- # local var here, doing so will cause a leak
+ # WARNING: do not assign the result of sys.exc_info() to a local
+ # var here, doing so will cause a leak. We used to actually
+ # explicitly delete both "exception" and "exc_info" from ``attrs``
+ # in a ``finally:`` clause below, but now we do not because these
+ # attributes are useful to upstream tweens. This actually still
+ # apparently causes a reference cycle, but it is broken
+ # successfully by the garbage collector (see
+ # https://github.com/Pylons/pyramid/issues/1223).
attrs['exc_info'] = sys.exc_info()
attrs['exception'] = exc
# clear old generated request.response, if any; it may
@@ -38,12 +44,6 @@ def excview_tween_factory(handler, registry):
if view_callable is None:
raise
response = view_callable(exc, request)
- finally:
- # prevent leakage (wrt exc_info)
- if 'exc_info' in attrs:
- del attrs['exc_info']
- if 'exception' in attrs:
- del attrs['exception']
return response