Chris McDonough
2014-02-08 579a5f47523ada48497994f0c70152f617d6af2a
- 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.

Closes #1223.
3 files modified
38 ■■■■■ changed files
CHANGES.txt 11 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_router.py 11 ●●●●● patch | view | raw | blame | history
pyramid/tweens.py 16 ●●●● patch | view | raw | blame | history
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)
==================
pyramid/tests/test_router.py
@@ -830,7 +830,8 @@
        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 @@
        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
pyramid/tweens.py
@@ -20,8 +20,14 @@
        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 @@
            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