Skip to content

Commit 939ea3d

Browse files
authored
Merge pull request #1949 from stephenfin/issue-1948
Handle escaped braces in f-strings
2 parents 2a811cc + bdcd5c2 commit 939ea3d

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/flake8/processor.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,13 @@ def build_logical_line_tokens(self) -> _Logical: # noqa: C901
203203
if token_type == tokenize.STRING:
204204
text = mutate_string(text)
205205
elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover
206-
text = "x" * len(text)
206+
# A curly brace in an FSTRING_MIDDLE token must be an escaped
207+
# curly brace. Both 'text' and 'end' will account for the
208+
# escaped version of the token (i.e. a single brace) rather
209+
# than the raw double brace version, so we must counteract this
210+
brace_offset = text.count("{") + text.count("}")
211+
text = "x" * (len(text) + brace_offset)
212+
end = (end[0], end[1] + brace_offset)
207213
if previous_row:
208214
(start_row, start_column) = start
209215
if previous_row != start_row:

tests/integration/test_plugins.py

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Integration tests for plugin loading."""
22
from __future__ import annotations
33

4+
import sys
5+
46
import pytest
57

68
from flake8.main.cli import main
@@ -261,3 +263,36 @@ def test_logical_line_plugin(tmpdir, capsys):
261263
"""
262264
out, err = capsys.readouterr()
263265
assert out == expected
266+
267+
268+
def test_escaping_of_fstrings_in_string_redacter(tmpdir, capsys):
269+
cfg_s = f"""\
270+
[flake8]
271+
extend-ignore = F
272+
[flake8:local-plugins]
273+
extension =
274+
T = {yields_logical_line.__module__}:{yields_logical_line.__name__}
275+
"""
276+
277+
cfg = tmpdir.join("tox.ini")
278+
cfg.write(cfg_s)
279+
280+
src = """\
281+
f'{{"{hello}": "{world}"}}'
282+
"""
283+
t_py = tmpdir.join("t.py")
284+
t_py.write_binary(src.encode())
285+
286+
with tmpdir.as_cwd():
287+
assert main(("t.py", "--config", str(cfg))) == 1
288+
289+
if sys.version_info >= (3, 12): # pragma: >=3.12 cover
290+
expected = """\
291+
t.py:1:1: T001 "f'xxx{hello}xxxx{world}xxx'"
292+
"""
293+
else: # pragma: <3.12 cover
294+
expected = """\
295+
t.py:1:1: T001 "f'xxxxxxxxxxxxxxxxxxxxxxxx'"
296+
"""
297+
out, err = capsys.readouterr()
298+
assert out == expected

0 commit comments

Comments
 (0)