On Tue, May 18, 2021 at 2:49 PM Pablo Galindo Salgado
* It actually doesn't have more advantages. The current solution in the PEP can do exactly the same as this solution if you allow reparsing when displaying tracebacks. This is because with the start line, end line, start offset and end offset and the original file, you can extract the source that is associated with the instruction, parse it (and this is much faster because you just need to parse the tiny fragment) and then you get an AST node that you can use for whatever you want.
Excellent point! Do you know how reliable this is in practice, i.e. what proportion of bytecode source spans are something you can successfully pass to ast.parse? If it works it's obviously nicer, but I can't tell how often it works. E.g. anything including return/break/continue/yield/await will fail, since those require an enclosing context to be legal. I doubt return/break/continue will raise exceptions often, but yield/await do all the time. You could kluge it by wrapping the source span in a dummy 'async def' before parsing, since that makes yield/await legal, but OTOH it makes 'yield from' and 'from X import *' illegal. I guess you could have a helper that attempts passing the string to ast.parse, and if that fails tries wrapping it in a loop/sync def/async def/etc. until one of them succeeds. Maybe that would be a useful utility to add to the traceback module? Or add a PyCF_YOLO flag that tries to make sense of an arbitrary out-of-context string. (Are there any other bits of syntax that require specific contexts that I'm not thinking of? If __enter__/__exit__ raise an exception, then what's the corresponding span? The entire 'with' block, or just the 'with' line itself?) -n PS: this is completely orthogonal to PEP 657, but if you're excited about making tracebacks more readable, another piece of low-hanging fruit would be to print method __qualname__s instead of __name__s in the traceback output. The reason we don't do that now is that __qualname__ lives on the function object, but in a traceback, we can't get the function object. The traceback only has access to the code object, and the code object doesn't have __qualname__, just __name__. Probably the cleanest way to do this would be to make the traceback or code object have a pointer back to the function object. See also https://bugs.python.org/issue12857. -- Nathaniel J. Smith -- https://vorpus.org