diff options
-rw-r--r-- | pecan/core.py | 25 | ||||
-rw-r--r-- | pecan/tests/test_base.py | 15 |
2 files changed, 34 insertions, 6 deletions
diff --git a/pecan/core.py b/pecan/core.py index a6525ca..14b9ad3 100644 --- a/pecan/core.py +++ b/pecan/core.py @@ -8,6 +8,7 @@ from mimetypes import guess_type, add_type from os.path import splitext import logging import operator +import sys import types import six @@ -123,12 +124,24 @@ def abort(status_code=None, detail='', headers=None, comment=None, **kw): :param comment: A comment to include in the response. ''' - raise exc.status_map[status_code]( - detail=detail, - headers=headers, - comment=comment, - **kw - ) + # If there is a traceback, we need to catch it for a re-raise + try: + _, _, traceback = sys.exc_info() + webob_exception = exc.status_map[status_code]( + detail=detail, + headers=headers, + comment=comment, + **kw + ) + + if six.PY3: + raise webob_exception.with_traceback(traceback) + else: + # Using exec to avoid python 3 parsers from crashing + exec('raise webob_exception, None, traceback') + finally: + # Per the suggestion of the Python docs, delete the traceback object + del traceback def redirect(location=None, internal=False, code=None, headers={}, diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py index e6adf0e..785b522 100644 --- a/pecan/tests/test_base.py +++ b/pecan/tests/test_base.py @@ -3,6 +3,7 @@ import sys import os import json +import traceback import warnings import webob @@ -1121,6 +1122,20 @@ class TestAbort(PecanTestCase): r = app.get('/', status=401) assert r.status_int == 401 + def test_abort_keeps_traceback(self): + last_exc, last_traceback = None, None + + try: + try: + raise Exception('Bottom Exception') + except: + abort(404) + except Exception: + last_exc, _, last_traceback = sys.exc_info() + + assert last_exc is HTTPNotFound + assert 'Bottom Exception' in traceback.format_tb(last_traceback)[-1] + class TestScriptName(PecanTestCase): |