Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQUEST] rich.traceback should handle ExceptionGroup and __notes__ #2238

Closed
Zac-HD opened this issue Apr 30, 2022 · 3 comments
Closed

[REQUEST] rich.traceback should handle ExceptionGroup and __notes__ #2238

Zac-HD opened this issue Apr 30, 2022 · 3 comments

Comments

@Zac-HD
Copy link

Zac-HD commented Apr 30, 2022

I'm pretty excited to start using PEP-654 ExceptionGroup and PEP-678 annotated exceptions in all my code (via the exceptiongroup backport, for now).

The only downside is that tools like rich.traceback (and Pytest) don't yet understand how to display these attributes - hence this feature request! I'd love to for the ecosystem to implement these new features, so that most people will have annotated-exceptiongroup-aware tooling installed by the time Python 3.11 final is released in October 😁

Repro script and output comparison between Rich and native tracebacks
from exceptiongroup import ExceptionGroup  # backport; this is builtin from Python 3.11.0b1

def f():
    raise ValueError("From f()")

def g():
    raise RuntimeError("From g()")

def main():
    excs = []
    for callback in [f, g]:
        try:
            callback()
        except Exception as err:
            err.__notes__ = ["Added a note"]
            excs.append(err)
    if excs:
        raise ExceptionGroup("Oops", excs)

def test():
    try:
        main()
    except Exception as err:
        err.__notes__ = ["Added a note"]
        raise

if __name__ == "__main__":
    from rich.console import Console

    console = Console()
    try:
        test()
    except Exception:
        console.print_exception(show_locals=True)

    print("\n\n" + "=" * 70 + "\n\n")
    test()  # Show the native exception display
$ python repro.py 
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│                                                                                                  │
│ /mnt/c/Users/zacha/Documents/GitHub/hypothesis/repro.py:38 in <module>                           │
│                                                                                                  │
│   35 │   console = Console()                                                                     │
│   36 │                                                                                           │
│   37 │   try:                                                                                    │
│ ❱ 38 │   │   test()                                                                              │
│   39 │   except Exception:                                                                       │
│   40 │   │   console.print_exception(show_locals=True)                                           │
│   41                                                                                             │
│                                                                                                  │
│ ╭───────────────────────────────────────── locals ─────────────────────────────────────────╮     │
│ │ __annotations__ = {}                                                                     │     │
│ │    __builtins__ = <module 'builtins' (built-in)>                                         │     │
│ │      __cached__ = None                                                                   │     │
│ │         __doc__ = None                                                                   │     │
│ │        __file__ = 'repro.py'                                                             │     │
│ │      __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fdb0c6744c0> │     │
│ │        __name__ = '__main__'                                                             │     │
│ │     __package__ = None                                                                   │     │
│ │        __spec__ = None                                                                   │     │
│ │         Console = <class 'rich.console.Console'>                                         │     │
│ │         console = <console width=138 ColorSystem.EIGHT_BIT>                              │     │
│ │  ExceptionGroup = <class 'exceptiongroup.ExceptionGroup'>                                │     │
│ │               f = <function f at 0x7fdb0bccd9d0>                                         │     │
│ │               g = <function g at 0x7fdb0bccda60>                                         │     │
│ │            main = <function main at 0x7fdb0bccdb80>                                      │     │
│ │            test = <function test at 0x7fdb0bc83790>                                      │     │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯     │
│ /mnt/c/Users/zacha/Documents/GitHub/hypothesis/repro.py:26 in test                               │
│                                                                                                  │
│   23                                                                                             │
│   24 def test():                                                                                 │
│   25 │   try:                                                                                    │
│ ❱ 26 │   │   main()                                                                              │
│   27 │   except Exception as err:                                                                │
│   28 │   │   err.__notes__ = ["Added a note"]                                                    │
│   29 │   │   raise                                                                               │
│                                                                                                  │
│ /mnt/c/Users/zacha/Documents/GitHub/hypothesis/repro.py:21 in main                               │
│                                                                                                  │
│   18 │   │   │   err.__notes__ = ["Added a note"]                                                │
│   19 │   │   │   excs.append(err)                                                                │
│   20 │   if excs:                                                                                │
│ ❱ 21 │   │   raise ExceptionGroup("Oops", excs)                                                  │
│   22                                                                                             │
│   23                                                                                             │
│   24 def test():                                                                                 │
│                                                                                                  │
│ ╭─────────────────────────── locals ────────────────────────────╮                                │
│ │ callback = <function g at 0x7fdb0bccda60>                     │                                │
│ │     excs = [ValueError('From f()'), RuntimeError('From g()')] │                                │
│ ╰───────────────────────────────────────────────────────────────╯                                │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ExceptionGroup: Oops (2 sub-exceptions)


======================================================================


  + Exception Group Traceback (most recent call last):
  |   File "repro.py", line 43, in <module>
  |     test()
  |   File "repro.py", line 26, in test
  |     main()
  |   File "repro.py", line 21, in main
  |     raise ExceptionGroup("Oops", excs)
  | exceptiongroup.ExceptionGroup: Oops (2 sub-exceptions)
  | Added a note
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "repro.py", line 16, in main
    |     callback()
    |   File "repro.py", line 5, in f
    |     raise ValueError("From f()")
    | ValueError: From f()
    | Added a note
    +---------------- 2 ----------------
    | Traceback (most recent call last):
    |   File "repro.py", line 16, in main
    |     callback()
    |   File "repro.py", line 9, in g
    |     raise RuntimeError("From g()")
    | RuntimeError: From g()
    | Added a note
    +------------------------------------
@flying-sheep
Copy link

3.11 is out, so this is now very relevant.

@AndreasBackx
Copy link

Let's perhaps track this in #1859 as this is a duplicate? The proposal for support has been accepted there already.

@Zac-HD Zac-HD closed this as completed Jul 10, 2023
@github-actions
Copy link

I hope we solved your problem.

If you like using Rich, you might also enjoy Textual

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants