This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Misleading SyntaxError on f-string
Type: behavior Stage: resolved
Components: Parser Versions: Python 3.10
process
Status: closed Resolution: later
Dependencies: Superseder:
Assigned To: Nosy List: Delengowski, eric.smith, lys.nikolaou, pablogsal, williamnavaraj
Priority: normal Keywords:

Created on 2022-01-04 20:31 by Delengowski, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg409709 - (view) Author: Matt Delengowski (Delengowski) Date: 2022-01-04 20:31
Example code


```
foo = 1
f"blank (open paren {foo )"
```

Error report

  File "<stdin>", line 1
    f"blank (open paren {foo )"
                               ^
SyntaxError: f-string: unmatched ')'

The problem is due to unmatched '}' however.
msg409723 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-01-04 23:17
Simpler reproducer:

>>> f"{foo)"
  File "<stdin>", line 1
    f"{foo)"
            ^
SyntaxError: f-string: unmatched ')'

I assume this is the same error as:

>>> foo)
  File "<stdin>", line 1
    foo)
       ^
SyntaxError: unmatched ')'

But I don't yet understand why it's choosing to parse that expression fragment. I'm working on it.
msg409752 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-01-05 11:29
In fstring_find_expr, the code[0] that's checking for parens, braces, and brackets detects the closing paren without a matching open paren.

The error message isn't incorrect: if you added a matching open paren the code would compile:
>>> foo=lambda:0
>>> f'{foo()}'
'0'

So while the error might not be intuitive, it's not wrong.

0: https://github.com/python/cpython/blob/cae55542d23e606dde9819d5dadd7430085fcc77/Parser/string_parser.c#L664d
msg409762 - (view) Author: Matt Delengowski (Delengowski) Date: 2022-01-05 13:09
Hi Eric,

I see what are you referring to. Like you said unintuitive but still correct. Do you think it would be worthwhile to change the order of the checking such that '}' is always first? Or could the same edge case still appear but just the other way around?

Either way, thanks for looking into this and sorry for the trouble.
msg409764 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-01-05 13:23
No trouble. I'm glad to know it wasn't actually the same error as plain "foo)" (although the error message is the same). That would have concerned me.

Changing the code so that it doesn't error out on the first problem it sees, but keeps looking for a different type of error and then maybe backtracks or re-parses would be a lot of work, and I think we'd just end up with a different class of errors.

I'm going to close this. Maybe when/if we move f-strings to the real parser we can look at this issue again.
msg409784 - (view) Author: William Navaraj (williamnavaraj) * Date: 2022-01-05 16:43
@Eric Smith,Thanks for explaining the intuition behind this statement. I agree. Just to avoid ambiguity we could add

"f-string: unmatched '%c' - no matching open parenthesis or missing '}'"

The only possibility at nested_depth==0 line 665 is either of those because of the check in line 559 i.e. assert(**str == '{')
https://github.com/python/cpython/blob/cae55542d23e606dde9819d5dadd7430085fcc77/Parser/string_parser.c#L559

Will help folks to look backwards (close to open as well) than forwards (open to close) as in Matt's case which is also a valid interpretation where there is an opening paren outside the f-string.  

or simply

"f-string: unmatched '%c' or missing '}'" will also do.
History
Date User Action Args
2022-04-11 14:59:54adminsetgithub: 90418
2022-01-05 16:43:18williamnavarajsetnosy: + williamnavaraj
messages: + msg409784
2022-01-05 13:23:29eric.smithsetstatus: open -> closed
resolution: later
messages: + msg409764

stage: resolved
2022-01-05 13:09:23Delengowskisetmessages: + msg409762
2022-01-05 11:29:25eric.smithsetmessages: + msg409752
2022-01-04 23:17:51eric.smithsetmessages: + msg409723
2022-01-04 21:09:21pablogsalsetnosy: + eric.smith
2022-01-04 20:31:12Delengowskicreate