diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 16fa16b..c9c9e5d 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -5,6 +5,7 @@ import argparse import ast import contextlib import logging +import sys import tokenize from typing import Any from typing import Generator @@ -178,7 +179,7 @@ class FileProcessor: self.blank_lines = 0 self.tokens = [] - def build_logical_line_tokens(self) -> _Logical: + def build_logical_line_tokens(self) -> _Logical: # noqa: C901 """Build the mapping, comments, and logical line lists.""" logical = [] comments = [] @@ -195,6 +196,11 @@ class FileProcessor: continue if token_type == tokenize.STRING: text = mutate_string(text) + elif ( + sys.version_info >= (3, 12) + and token_type == tokenize.FSTRING_MIDDLE + ): + text = "x" * len(text) if previous_row: (start_row, start_column) = start if previous_row != start_row: diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py index edba048..b67e6d6 100644 --- a/tests/integration/test_plugins.py +++ b/tests/integration/test_plugins.py @@ -197,3 +197,35 @@ t.py:3:1: T001 '"""\\n' ''' out, err = capsys.readouterr() assert out == expected + + +def yields_logical_line(logical_line): + yield 0, f"T001 {logical_line!r}" + + +def test_logical_line_plugin(tmpdir, capsys): + cfg_s = f"""\ +[flake8] +extend-ignore = F +[flake8:local-plugins] +extension = + T = {yields_logical_line.__module__}:{yields_logical_line.__name__} +""" + + cfg = tmpdir.join("tox.ini") + cfg.write(cfg_s) + + src = """\ +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'" +""" + out, err = capsys.readouterr() + assert out == expected