PyCQA / pycodestyle

Simple Python style checker in one Python file

Home Page:https://pycodestyle.pycqa.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.