Skip to content

Commit

Permalink
PEP 678: new API for add_note()
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD committed Feb 25, 2022
1 parent c8876fd commit 1e95fbc
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 15 deletions.
19 changes: 17 additions & 2 deletions src/exceptiongroup/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,22 @@ def __init__(self, __message: str, __exceptions: Sequence[EBase], *args: Any):
super().__init__(__message, __exceptions, *args)
self._message = __message
self._exceptions = __exceptions
self.__note__ = None
self._notes = []

def add_note(self, note: str):
if not isinstance(note, str):
raise TypeError(
f"Expected a string, got note={note!r} (type {type(note).__name__})"
)
self._notes.append(note)

@property
def __notes__(self):
return tuple(self._notes)

@__notes__.deleter
def _clear_notes(self):
self._notes.clear()

@property
def message(self) -> str:
Expand Down Expand Up @@ -151,7 +166,7 @@ def split(

def derive(self: T, __excs: Sequence[EBase]) -> T:
eg = BaseExceptionGroup(self.message, __excs)
eg.__note__ = self.__note__
eg._notes = self._notes
return eg

def __str__(self) -> str:
Expand Down
12 changes: 7 additions & 5 deletions src/exceptiongroup/_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def traceback_exception_init(
_seen=_seen,
**kwargs,
)
self.__note__ = getattr(exc_value, "__note__", None) if exc_value else None
self.__notes__ = getattr(exc_value, "__notes__", ()) if exc_value else ()

seen_was_none = _seen is None

Expand Down Expand Up @@ -135,8 +135,9 @@ def traceback_exception_format(self, *, chain=True, _ctx=None):
yield from _ctx.emit("Traceback (most recent call last):\n")
yield from _ctx.emit(exc.stack.format())
yield from _ctx.emit(exc.format_exception_only())
if isinstance(exc.__note__, str):
yield from _ctx.emit(line + "\n" for line in exc.__note__.split("\n"))
for note in self.__notes__:
if isinstance(note, str):
yield from _ctx.emit(note + "\n")
elif _ctx.exception_group_depth > max_group_depth:
# exception group, but depth exceeds limit
yield from _ctx.emit(f"... (max_group_depth is {max_group_depth})\n")
Expand All @@ -154,8 +155,9 @@ def traceback_exception_format(self, *, chain=True, _ctx=None):
yield from _ctx.emit(exc.stack.format())

yield from _ctx.emit(exc.format_exception_only())
if isinstance(exc.__note__, str):
yield from _ctx.emit(line + "\n" for line in exc.__note__.split("\n"))
for note in self.__notes__:
if isinstance(note, str):
yield from _ctx.emit(note + "\n")
num_excs = len(exc.exceptions)
if num_excs <= max_group_width:
n = num_excs
Expand Down
12 changes: 6 additions & 6 deletions tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ def test_fields_are_readonly(self):
with self.assertRaises(AttributeError):
eg.exceptions = [OSError("xyz")]

def test_note_exists_and_is_string_or_none(self):
def test_note_exists_and_is_tuple_of_strings(self):
eg = create_simple_eg()

note = "This is a happy note for the exception group"
self.assertIs(eg.__note__, None)
eg.__note__ = note
self.assertIs(eg.__note__, note)
self.assertEqual(eg.__notes__, ())
eg.add_note(note)
self.assertIs(eg.__notes__, (note,))


class ExceptionGroupTestBase(unittest.TestCase):
Expand Down Expand Up @@ -497,7 +497,7 @@ def leaves(exc):
self.assertIs(eg.__cause__, part.__cause__)
self.assertIs(eg.__context__, part.__context__)
self.assertIs(eg.__traceback__, part.__traceback__)
self.assertIs(eg.__note__, part.__note__)
self.assertEqual(eg.__notes__, part.__notes__)

def tbs_for_leaf(leaf, eg):
for e, tbs in leaf_generator(eg):
Expand Down Expand Up @@ -561,7 +561,7 @@ def level3(i):
try:
nested_group()
except ExceptionGroup as e:
e.__note__ = f"the note: {id(e)}"
e.add_note(f"the note: {id(e)}")
eg = e

eg_template = [
Expand Down
4 changes: 2 additions & 2 deletions tests/test_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ def test_formatting(capsys):
try:
raise RuntimeError("bar")
except RuntimeError as exc:
exc.__note__ = "Note from bar handler"
exc.add_note("Note from bar handler")
exceptions.append(exc)

try:
raise ExceptionGroup("test message", exceptions)
except ExceptionGroup as exc:
exc.__note__ = "Displays notes attached to the group too"
exc.add_note("Displays notes attached to the group too")
sys.excepthook(type(exc), exc, exc.__traceback__)

lineno = test_formatting.__code__.co_firstlineno
Expand Down

0 comments on commit 1e95fbc

Please sign in to comment.