False positive E202 and E251 inside f-string (Python 3.12)
AndrewUshakov opened this issue · comments
Hi!
For the code below:
a = 10
print(f'{a = }')
the pycodestyle.py version 2.11.0 generates 3 false positive errors:
tst.py:2:11: E251 unexpected spaces around keyword / parameter equals
tst.py:2:13: E202 whitespace before '}'
tst.py:2:13: E251 unexpected spaces around keyword / parameter equals
P.S. Python 3.12.0 (tags/v3.12.0:0fb18b0, Oct 2 2023, 13:03:39) [MSC v.1935 64 bit (AMD64)] on win32
Thank you in advance.
Andrew
I believe the intended syntax for this is f'{a=}'
which does not produce errors
Hi!
In the proposal python/cpython#80998, where discussed syntax was suggested, you can find example of the f-string with spaces around the = symbol.
In the section https://docs.python.org/3/reference/lexical_analysis.html#f-strings you can also find example of the f-string with more spaces than in my example:
>f"{ foo = }" # preserves whitespace
One of the new features In the Python 3.12 is: "More flexible f-string parsing , allowing many things previously disallowed (PEP 701)." In the PEP701 documentation the special section "Handling of f-string debug expressions" exists. The fragment of this section is below:
f-string debug expressions preserve whitespace in the expression, including spaces after the { and the = characters. This means that the raw string contents of the expression part of the f-string must be kept intact and not just the associated tokens.
As I understand, it means that:
f'{ foo = }'
is equivalent to
f' foo = {foo}'
and only expression itself without surrounding spaces need to be validated against PEP8.
Additionally, in the PEP701 documentation you can find examples of "usual" f-strings with spaces after { and before }. Your script generates E201 and E202 for such strings, while real warnings should look like "spaces after { and before } will disappear at the output". And, of course, E251 message is confusing, because meaning of = character is different here.
Best regards,
Andrew
yes but all of the canonical examples do not have spaces
By the way, I found one case (agree, very special) where the space after the { is required. Consider the valid Python 3.12 code below, which uses "usual" f-string:
a = 999
print(f'{ {a, 2, 3}}')
print(f'{{a, 2, 3}}')
which prints:
{2, 3, 999}
{a, 2, 3}
Process finished with exit code 0
Do you agree, that it is not PEP8 error/warning?
use parentheses
Result of
print(f'{({a, 2, 3})=}')
looks ugly:
({a, 2, 3})={2, 3, 999}
it looks ugly either way. nobody would write code like that
Ok. The last question. Will you accept pull request?
P.S. Yes, I understand, that patch will not be trivial, because in the function extraneous_whitespace tokens are unavailable.
no. I consider the current behavior to be correct. you can use noqa for your strawman cases
The spaces around =
in f-strings change the output.
foo = 42
print(f"{foo=}")
# foo=42
print(f"{foo =}")
# foo =42
print(f"{foo= }")
# foo= 42
print(f"(foo = }")
# foo = 42
What will be the effective way to produce foo = 42
without writing the variable name twice in the code? (i.e. f"foo = {foo}"
)
Generally E251 errors won't affect the behavior of the code, but this one forces to change the behavior.