Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.4k
bpo-40612: Fix SyntaxError edge cases in traceback formatting#20072
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from1 commit
87e78b5b951b0fea1c6f272e5b936df76621c7e6bb31641fff93a54cFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -554,36 +554,58 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, | ||||||||||||||||
| static void | ||||||||||||||||
| print_error_text(PyObject *f, int offset, PyObject *text_obj) | ||||||||||||||||
| { | ||||||||||||||||
| /* Convert text to a char pointer; return if error */ | ||||||||||||||||
| const char *text = PyUnicode_AsUTF8(text_obj); | ||||||||||||||||
| if (text == NULL) | ||||||||||||||||
| return; | ||||||||||||||||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Just fyi this code right here is the one that I mentioned inwe-like-parsers#121 (comment) Whereby a SyntaxError with an offset relative to the start of the file will end up pointing to the right place. I'm tempted to say we should eventually just remove it since the new parser will always provide line-relative offsets. MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Hm... Why would the offset in the SyntaxError object ever end up being file-relative? Do you know of any code that produces such SyntaxErrors? Member
| ||||||||||||||||
| err_ret->offset=col_offset!=-1 ?col_offset+1 : ((int)(tok->cur-tok->buf)); | |
| len=tok->inp-tok->buf; | |
| err_ret->text= (char*)PyObject_MALLOC(len+1); | |
| if (err_ret->text!=NULL) { | |
| if (len>0) | |
| strncpy(err_ret->text,tok->buf,len); | |
| err_ret->text[len]='\0'; |
tok->cur is the current read index of the tokenizer andtok->buf is thestart of the file. Also see how it copies the entire file up till the error into theSyntaxError.text field.
Try this out with the old parser as a quick example:
code="""\a =\\\\\\?"""try:compile(code,'<stdin>','exec')exceptSyntaxErrorase:print(e)print(e.lineno,e.offset)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Oh, you mean the opposite of file. :-) It occurs when it's not read from a file.
Also it doesn't occur all the time -- perhaps only when there's a continuation line? E.g. here all is good:
>>> try: compile("def f():\n 1+\n", "", "exec")... except SyntaxError as e: e... SyntaxError('invalid syntax', ('', 2, 4, ' 1+\n'))>>>
gvanrossumMay 15, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
FWIW, your example does show up weird in the old parser:
>>> code = """\a = \\ \\ \\?"""... ... ... >>> code'a = \\\n \\\n \\?'>>> try: compile(code, "", "exec")... except SyntaxError as e: e... SyntaxError('unexpected character after line continuation character', ('', 3, 19, 'a = \\\n \\\n \\?\n'))>>>The new parser seems to solve the dilemma by suppressing the source text (also the offset is set to zero, meaning unknown):
>>> code = """\a = \\ \\ \\?"""... ... ... >>> >>> try: compile(code, "", "exec")... except Exception as e: e; e.lineno, e.offset, e.text... SyntaxError('unexpected character after line continuation character')(3, 0, None)>>>There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Aah yes, it seems like it's just an issue with line continuations. I thought I had another example but it must have been a misunderstanding becausetok->buf gets advanced with newlines.
So I guess this code here inpythonrun.c is just for this one case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Okay, so I have a serious question here. Is there a regression due to this PR for people using-X oldparser? I have tried to research this and cannot find a regression. The C code in pythonrun.c still skips through newlines. The traceback.py code doesn't, but it never did.
Here is what I did for research. First Python 3.8:
>>> import traceback; traceback.print_exception(None, SyntaxError("msg", ("f.py", 3, 10, "aaa\nbbb\nccc\n")), None) File "f.py", line 3 aaabbbccc ^SyntaxError: msg>>> raise SyntaxError("msg", ("f.py", 3, 10, "aaa\nbbb\nccc\n"))Traceback (most recent call last): File "<stdin>", line 1, in <module> File "f.py", line 3 ccc ^SyntaxError: msg>>>Then the master branch:
>>> import traceback; traceback.print_exception(None, SyntaxError("msg", ("f.py", 3, 10, "aaa\nbbb\nccc\n")), None) File "f.py", line 3 aaabbbccc ^SyntaxError: msg>>> raise SyntaxError("msg", ("f.py", 3, 10, "aaa\nbbb\nccc\n"))Traceback (most recent call last): File "<stdin>", line 1, in <module> File "f.py", line 3 ccc ^SyntaxError: msg>>>To me that looks like in both versions, the C formatter (invoked byraise) does the right thing, while traceback.py messes up the output.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
gvanrossum marked this conversation as resolved. OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.