Permalink
Browse files

- 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
  #1223.

Closes #1223.
  • Loading branch information...
1 parent d867f09 commit 579a5f47523ada48497994f0c70152f617d6af2a @mcdonc mcdonc committed Feb 8, 2014
Showing with 26 additions and 12 deletions.
  1. +11 −0 CHANGES.txt
  2. +7 −4 pyramid/tests/test_router.py
  3. +8 −8 pyramid/tweens.py
View
@@ -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)
==================
@@ -830,7 +830,8 @@ def rfactory(environ):
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 @@ def exception_view(context, request):
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
View
@@ -20,8 +20,14 @@ def excview_tween(request):
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(request):
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

0 comments on commit 579a5f4

Please sign in to comment.