◐ Shell
clean mode source ↗

gh-103895: Improve how invalid `Exception.__notes__` are displayed by pR0Ps · Pull Request #103897 · python/cpython

@Carreau

[PEP 678](https://peps.python.org/pep-0678/) introduced the ability to
add notes to exception objects. This has been [released in Python
3.11](https://docs.python.org/3/library/exceptions.html#BaseException.add_note)
and is currently not implemented in IPython. These changes are fully
compatible with older Python versions that don't include PEP 678.

Here's a sample test that shows the consistency in Python's stdlib
traceback module (test 1) and the difference between Python and
IPython's runtimes (test 2):
```python
import traceback

print('--- test 1 ---')
try:
    raise Exception('Testing notes')
except Exception as e:
    e.add_note('Does this work?')
    e.add_note('Yes!')
    traceback.print_exc()

print('\n--- test 2 ---')
try:
    raise Exception('Testing notes')
except Exception as e:
    e.add_note('Does this work?')
    e.add_note('No!')
    raise
```

When executed with Python 3.11, both notes are displayed in both
tracebacks:
```
$ python test.py 
--- test 1 ---
Traceback (most recent call last):
  File "/app/test.py", line 5, in <module>
    raise Exception('Testing notes')
Exception: Testing notes
Does this work?
Yes!

--- test 2 ---
Traceback (most recent call last):
  File "/app/test.py", line 13, in <module>
    raise Exception('Testing notes')
Exception: Testing notes
Does this work?
No!
```

In IPython's VerboseTB does not yet handle exception notes:
```
$ ipython test.py 
--- test 1 ---
Traceback (most recent call last):
  File "/app/test.py", line 5, in <module>
    raise Exception('Testing notes')
Exception: Testing notes
Does this work?
Yes!

--- test 2 ---
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
File /app/test.py:13
     11 print('\n--- test 2 ---')
     12 try:
---> 13     raise Exception('Testing notes')
     14 except Exception as e:
     15     e.add_note('Does this work?')

Exception: Testing notes
```

The changes I am suggesting are inspired from implementation of
[Lib/traceback.py](https://github.com/python/cpython/blob/main/Lib/traceback.py)
(search for `__notes__`) and improvements for dealing with edge cases
more nicely in
[cpython#103897](python/cpython#103897).

Although notes are meant to be strings only, I kept some inspiration
from the existing exception handling to ensure that the notes are
uncolored and bytes decoded, if there are any. I am definitely open to
using a different color if deemed better. For context, `bpython` keeps
the notes uncolored, and [Python's
tutorial](https://docs.python.org/3/tutorial/errors.html#enriching-exceptions-with-notes)
puts them in light gray, like the line numbers.

Here's how the test 2 looks like after these changes:

![image](https://user-images.githubusercontent.com/16963011/234723689-6bbfe0ff-94d4-4a90-9da6-acfe1c8e5edf.png)

## 🐍 🤹‍♂️