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

TracebackException subclass #4

Open
asmeurer opened this issue Feb 14, 2020 · 7 comments
Open

TracebackException subclass #4

asmeurer opened this issue Feb 14, 2020 · 7 comments

Comments

@asmeurer
Copy link

It would be useful to have a TracebackException subclass that added column information, perhaps also with a default format override. That way existing code that uses the traceback module could easily swap it out for something that shows column information. It might also be useful to have versions of the various functions in the traceback module that used this.

@alexmojaki
Copy link
Owner

  1. Column information can exist for every frame, not just the 'last' one, so this information would probably be on FrameSummary.
  2. The node being executed can easily span multiple lines, so just a single start column and end column is not appropriate, and the traceback module isn't really equipped to handle multiple lines per frame.
  3. A lot went into designing and documenting the current API, so I'm not in a hurry to add another one. In general I'd like to know if there's anything about the current API that's deficient, and what use cases would motivate adding a traceback-like API.

@asmeurer
Copy link
Author

Yes. I think really what I want is an API compatible version of the standard library traceback module that makes use of column information. I took a look at the code and it isn't all entirely amenable to subclassing, so a lot of it will have to be copy-pasted (e.g., if you subclass TracebackException and want to use a custom subclass of FrameSummary, you have to rewrite the entire __init__ method).

My use-case is I have existing code that uses the traceback module to format exceptions, and I would love to have a drop-in replacement that shows tracebacks with additional column formatting.

Is anything in the existing API focused on formatting and printing output? All the examples in the README show manual formatting, which is lower level than what I want. I don't see anything that can print a traceback, for instance, but I may have missed it.

@alexmojaki
Copy link
Owner

No, there's nothing to format for you because there's no obviously correct way to format a traceback, especially when there's so much data available. For example IPython has one style, stackprinter has another, and traceback has another. Many libraries format tracebacks in HTML.

The traceback module has it easy because there's a single standard format for tracebacks in Python so it just has to provide exactly that. And it displays so little information that no one needs to vary it anyway.

I would love to have a drop-in replacement that shows tracebacks with additional column formatting.

What would the output look like?

I honestly think you should take the code in ipython/ipython#11827 (comment), tweak it to your preferences, and use that.

@asmeurer
Copy link
Author

The traceback module gives you the API necessary if you want to modify how the tracebacks look. So for instance if you want to show more than one line of context, you can do that. The API is not the greatest for that once you really want to get picky on how things look.

Most people don't want to rewrite the entire traceback formatting from scratch like you've done at ipython/ipython#11827 (comment). If something has reasonable defaults they will want to use that. You can have different styles, like standard Python style, IPython style, HTML, and so on. You can make it extensible so that people can change how it looks, but defaults are important.

What would the output look like?

I would suggest for the default output to look as similar to the default tracebacks as possible. For instance, say you had something like

def test():
    return 1/0

print(test())

which normally gives

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    print(test())
  File "test.py", line 2, in test
    return 1/0
ZeroDivisionError: division by zero

A reasonable extension of that would be

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    print(test())
          ^^^^^^
  File "test.py", line 2, in test
    return 1/0
           ^^^
ZeroDivisionError: division by zero

For cases where the columns are not on the printed line it could either only show the parts that are on the given line, or show multiple lines (either would be a reasonable default IMO).

Ultimately, if you want people to use this, you need higher level tools that they can use as drop-in replacements for existing tooling.

@alexmojaki
Copy link
Owner

OK, I guess you're right. I've started an implementation in the formatting branch. It still needs testing and docs but it should be roughly right and I'd love it if you could give me some early feedback. Here's some usage code:

import json

import stack_data

formatter = stack_data.Formatter(
    options=stack_data.Options(before=0, after=0),
    show_linenos=False,
    current_line_indicator=False,
)

try:
    json.loads(" s s")
except:
    formatter.print_exception()

@asmeurer
Copy link
Author

Nice, it looks good. I'll need to try playing with the API a to see if I can integrate it into my existing uses.

One suggestion so far, is to use current_line_indicator='' instead of current_line_indicator=False. I thought from reading your example that it was a boolean flag and then got an error when I set it to True.

@aroberge
Copy link
Contributor

https://www.python.org/dev/peps/pep-0657/ (targeted for Python 3.11) might contain some interesting information.

The latest beta (3.10.0b1) does have some extended highlighting for SyntaxErrors. The exception argument can have two additional elements (end_lineno and end_offset).

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

No branches or pull requests

3 participants