summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-07-31 03:57:06 -0400
committerChris McDonough <chrism@plope.com>2011-07-31 03:57:06 -0400
commit95a3791409f4a936c47e7018e75f14fc3b701380 (patch)
tree326a676a5ecce049dbda625cb7f033248efb2c4c
parentdc27f6ccd181f553da1c2ef0debb5ecc355012a9 (diff)
downloadpyramid-95a3791409f4a936c47e7018e75f14fc3b701380.tar.gz
pyramid-95a3791409f4a936c47e7018e75f14fc3b701380.tar.bz2
pyramid-95a3791409f4a936c47e7018e75f14fc3b701380.zip
- A new attribute is available on request objects: ``exc_info``. Its value
will be ``None`` until an exception is caught by the Pyramid router, after which it will be the result of ``sys.exc_info()``.
-rw-r--r--CHANGES.txt4
-rw-r--r--TODO.txt2
-rw-r--r--docs/api/request.rst11
-rw-r--r--pyramid/request.py1
-rw-r--r--pyramid/router.py4
-rw-r--r--pyramid/tests/test_router.py3
6 files changed, 22 insertions, 3 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 1f6da0d8b..c94ecb800 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -76,6 +76,10 @@ Features
normal logging channels. The logger name of the debug logger will be the
package name of the *caller* of the Configurator's constructor.
+- A new attribute is available on request objects: ``exc_info``. Its value
+ will be ``None`` until an exception is caught by the Pyramid router, after
+ which it will be the result of ``sys.exc_info()``.
+
Deprecations
------------
diff --git a/TODO.txt b/TODO.txt
index ffa40ade1..fda59d7b4 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -4,8 +4,6 @@ Pyramid TODOs
Should-Have
-----------
-- Add request.exc_info during an exception.
-
- Merge https://github.com/Pylons/pyramid/pull/242 (IPython update; requires
test fixes and additional test coverage).
diff --git a/docs/api/request.rst b/docs/api/request.rst
index 404825d1b..2ab3977d5 100644
--- a/docs/api/request.rst
+++ b/docs/api/request.rst
@@ -85,6 +85,17 @@
of ``request.exception`` will be ``None`` within response and
finished callbacks.
+ .. attribute:: exc_info
+
+ If an exception was raised by a :term:`root factory` or a :term:`view
+ callable`, or at various other points where :app:`Pyramid` executes
+ user-defined code during the processing of a request, result of
+ ``sys.exc_info()`` will be available as the ``exc_info`` attribute of
+ the request within a :term:`exception view`, a :term:`response callback`
+ or a :term:`finished callback`. If no exception occurred, the value of
+ ``request.exc_info`` will be ``None`` within response and finished
+ callbacks.
+
.. attribute:: response
This attribute is actually a "reified" property which returns an
diff --git a/pyramid/request.py b/pyramid/request.py
index 8df204681..2a654d218 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -204,6 +204,7 @@ class Request(BaseRequest, DeprecatedRequestMethods):
response_callbacks = ()
finished_callbacks = ()
exception = None
+ exc_info = None
matchdict = None
matched_route = None
diff --git a/pyramid/router.py b/pyramid/router.py
index efbf0b326..aa9e4a1ba 100644
--- a/pyramid/router.py
+++ b/pyramid/router.py
@@ -1,3 +1,5 @@
+import sys
+
from zope.interface import implements
from zope.interface import providedBy
@@ -166,6 +168,7 @@ class Router(object):
# handle exceptions raised during root finding and view-exec
except Exception, why:
+ exc_info = sys.exc_info()
# 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)
@@ -173,6 +176,7 @@ class Router(object):
del attrs['response']
attrs['exception'] = why
+ attrs['exc_info'] = exc_info
for_ = (IExceptionViewClassifier,
request_iface.combined,
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index 4d44de5c0..e44465992 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -808,7 +808,8 @@ class TestRouter(unittest.TestCase):
# ``exception`` must be attached to request even if a suitable
# exception view cannot be found
self.assertEqual(request.exception.__class__, RuntimeError)
-
+ self.assertEqual(request.exc_info[0], RuntimeError)
+
def test_call_view_raises_exception_view(self):
from pyramid.interfaces import IViewClassifier
from pyramid.interfaces import IExceptionViewClassifier