diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 21a25e0f..29c5929c 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -203,9 +203,17 @@ def build_logical_line_tokens(self) -> _Logical: # noqa: C901 if token_type == tokenize.STRING: text = mutate_string(text) elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover - text = "x" * len(text) + # A curly brace in an FSTRING_MIDDLE token must be an escaped + # curly brace. Both 'text' and 'end' will account for the + # escaped version of the token (i.e. a single brace) rather + # than the raw double brace version, so we must counteract this + fstring_offset = 0 + if "{" in text or "}" in text: + fstring_offset = text.count("{") + text.count("}") + text = "x" * (len(text) + fstring_offset) + end = (end[0], end[1] + fstring_offset) if previous_row: - (start_row, start_column) = start + start_row, start_column = start if previous_row != start_row: row_index = previous_row - 1 column_index = previous_column - 1 @@ -219,7 +227,7 @@ def build_logical_line_tokens(self) -> _Logical: # noqa: C901 logical.append(text) length += len(text) mapping.append((length, end)) - (previous_row, previous_column) = end + previous_row, previous_column = end return comments, logical, mapping def build_ast(self) -> ast.AST: diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index d4c22b0b..1a331346 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -1,6 +1,8 @@ """Integration tests for plugin loading.""" from __future__ import annotations +import sys + import pytest from flake8.main.cli import main @@ -248,16 +250,20 @@ def test_logical_line_plugin(tmpdir, capsys): cfg.write(cfg_s) src = """\ -f'hello world' +f'{{"{hello}": "{world}"}}' """ t_py = tmpdir.join("t.py") t_py.write_binary(src.encode()) with tmpdir.as_cwd(): assert main(("t.py", "--config", str(cfg))) == 1 - - expected = """\ -t.py:1:1: T001 "f'xxxxxxxxxxx'" + if sys.version_info >= (3, 12): # pragma: >=3.12 cover + expected = """\ +t.py:1:1: T001 "f'xxx{hello}xxxx{world}xxx'" +""" + else: # pragma: <3.12 cover + expected = """\ +t.py:1:1: T001 "f'xxxxxxxxxxxxxxxxxxxxxxxx'" """ out, err = capsys.readouterr() assert out == expected