diff --git a/src/flake8/violation.py b/src/flake8/violation.py index 8535178..c9c240e 100644 --- a/src/flake8/violation.py +++ b/src/flake8/violation.py @@ -2,8 +2,10 @@ from __future__ import annotations import functools +import io import linecache import logging +import tokenize from re import Match from typing import NamedTuple @@ -16,7 +18,20 @@ LOG = logging.getLogger(__name__) @functools.lru_cache(maxsize=512) def _find_noqa(physical_line: str) -> Match[str] | None: - return defaults.NOQA_INLINE_REGEXP.search(physical_line) + comment_tokens = [] + try: + tokens = tokenize.generate_tokens(io.StringIO(physical_line).readline) + for token in tokens: + if token.type == tokenize.COMMENT: + comment_tokens.append(token.string) + except tokenize.TokenError: + pass + + for comment in comment_tokens: + match = defaults.NOQA_INLINE_REGEXP.search(comment) + if match is not None: + return match + return None class Violation(NamedTuple): diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py index 0ca5b63..e5ac7d4 100644 --- a/tests/integration/test_main.py +++ b/tests/integration/test_main.py @@ -259,6 +259,25 @@ x = """ assert out == err == "" +def test_noqa_in_string_is_not_ignored(tmpdir, capsys): + """See https://github.com/pycqa/flake8/issues/1321.""" + t_py_src = '''\ +def f(): + x = '# noqa' +''' + + with tmpdir.as_cwd(): + tmpdir.join("t.py").write(t_py_src) + assert cli.main(["t.py"]) == 1 + + expected = """\ +t.py:2:5: F841 local variable 'x' is assigned to but never used +""" + out, err = capsys.readouterr() + assert out == expected + assert err == "" + + def test_physical_line_file_not_ending_in_newline(tmpdir, capsys): """See https://github.com/PyCQA/pycodestyle/issues/960.""" t_py_src = "def f():\n\tpass" diff --git a/tests/unit/test_violation.py b/tests/unit/test_violation.py index 1b4852b..b5f1dfd 100644 --- a/tests/unit/test_violation.py +++ b/tests/unit/test_violation.py @@ -28,6 +28,7 @@ from flake8.violation import Violation ("E111", "a = 1 # noqa - We do not care", True), ("E111", "a = 1 # noqa: We do not care", True), ("E111", "a = 1 # noqa:We do not care", True), + ("E111", "a = '# noqa'", False), ("ABC123", "a = 1 # noqa: ABC123", True), ("E111", "a = 1 # noqa: ABC123", False), ("ABC123", "a = 1 # noqa: ABC124", False),