Skip to content

Commit

Permalink
Add support for chained exceptions (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
Delgan committed Jan 8, 2019
1 parent 4d6a9da commit 04f7e97
Show file tree
Hide file tree
Showing 15 changed files with 525 additions and 6 deletions.
38 changes: 32 additions & 6 deletions better_exceptions/formatter.py
Expand Up @@ -276,13 +276,39 @@ def format_traceback(self, tb=None):

return ''.join(lines), final_source

def format_exception(self, exc, value, tb):
formatted, colored_source = self.format_traceback(tb)
def _format_exception(self, value, tb, seen=None):
# Implemented from built-in traceback module:
# https://github.com/python/cpython/blob/a5b76167dedf4d15211a216c3ca7b98e3cec33b8/Lib/traceback.py#L468

exc_type, exc_value, exc_traceback = type(value), value, tb

if seen is None:
seen = set()

seen.add(id(exc_value))

if exc_value and PY3:
if exc_value.__cause__ is not None and id(exc_value.__cause__) not in seen:
for text in self._format_exception(exc_value.__cause__,exc_value.__cause__.__traceback__, seen=seen):
yield text
yield u"\nThe above exception was the direct cause of the following exception:\n\n"
elif exc_value.__context__ is not None and id(exc_value.__context__) not in seen and not exc_value.__suppress_context__:
for text in self._format_exception(exc_value.__context__, exc_value.__context__.__traceback__, seen=seen):
yield text
yield u"\nDuring handling of the above exception, another exception occurred:\n\n"

if not str(value) and exc is AssertionError:
if exc_traceback is not None:
yield u'Traceback (most recent call last):\n'

formatted, colored_source = self.format_traceback(exc_traceback)

yield formatted

if not str(value) and exc_type is AssertionError:
value.args = (colored_source,)
title = traceback.format_exception_only(exc, value)
title = traceback.format_exception_only(exc_type, value)

full_trace = u'Traceback (most recent call last):\n{}{}\n'.format(formatted, ''.join(title).strip())
yield u''.join(title).strip() + u'\n'

return full_trace
def format_exception(self, exc, value, tb):
return u''.join(formatted for formatted in self._format_exception(value, tb))
39 changes: 39 additions & 0 deletions test/output/python3-dumb-UTF-8-color.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
│ │ └ 0
│ └ 1
└ <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
│ └ 0
└ 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
│ │ └ 0
│ └ 1
└ <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError('Division error')
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
└ <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError('Cause error') from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-dumb-UTF-8-nocolor.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
│ │ └ 0
│ └ 1
└ <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
│ └ 0
└ 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
│ │ └ 0
│ └ 1
└ <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError("Division error")
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
└ <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError("Cause error") from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-dumb-ascii-color.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
| | -> 0
| -> 1
-> <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
| -> 0
-> 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
| | -> 0
| -> 1
-> <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError('Division error')
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
-> <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError('Cause error') from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-dumb-ascii-nocolor.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
| | -> 0
| -> 1
-> <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
| -> 0
-> 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
| | -> 0
| -> 1
-> <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError("Division error")
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
-> <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError("Cause error") from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-vt100-UTF-8-color.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
│ │ └ 0
│ └ 1
└ <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
│ └ 0
└ 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
│ │ └ 0
│ └ 1
└ <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError('Division error')
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
└ <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError('Cause error') from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-vt100-UTF-8-nocolor.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
│ │ └ 0
│ └ 1
└ <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
│ └ 0
└ 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
│ │ └ 0
│ └ 1
└ <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError("Division error")
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
└ <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError("Cause error") from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-vt100-ascii-color.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
| | -> 0
| -> 1
-> <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
| -> 0
-> 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
| | -> 0
| -> 1
-> <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError('Division error')
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
-> <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError('Cause error') from e
ValueError: Cause error



39 changes: 39 additions & 0 deletions test/output/python3-vt100-ascii-nocolor.out
Expand Up @@ -209,3 +209,42 @@ SyntaxError: invalid syntax



python3 test/test_chaining.py


Traceback (most recent call last):
File "test/test_chaining.py", line 11, in cause
div(x, y)
| | -> 0
| -> 1
-> <function div at 0xDEADBEEF>
File "test/test_chaining.py", line 7, in div
x / y
| -> 0
-> 1
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test/test_chaining.py", line 17, in context
cause(x, y)
| | -> 0
| -> 1
-> <function cause at 0xDEADBEEF>
File "test/test_chaining.py", line 13, in cause
raise ValueError("Division error")
ValueError: Division error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test/test_chaining.py", line 21, in <module>
context(1, 0)
-> <function context at 0xDEADBEEF>
File "test/test_chaining.py", line 19, in context
raise ValueError("Cause error") from e
ValueError: Cause error



0 comments on commit 04f7e97

Please sign in to comment.