Adds warning when invalid error codes are parsed for ignore or extend-ignore from config file

This commit is contained in:
Menno Liefstingh 2022-10-13 01:15:35 +02:00 committed by Anthony Sottile
parent 5eeee3fbc0
commit 1346ddefd3
6 changed files with 84 additions and 36 deletions

View file

@ -43,3 +43,5 @@ NOQA_INLINE_REGEXP = re.compile(
) )
NOQA_FILE = re.compile(r"\s*# flake8[:=]\s*noqa", re.I) NOQA_FILE = re.compile(r"\s*# flake8[:=]\s*noqa", re.I)
VALID_CODE_PREFIX = re.compile("^[A-Z]{1,3}[0-9]{0,3}$", re.ASCII)

View file

@ -7,6 +7,7 @@ import os.path
from typing import Any from typing import Any
from flake8 import exceptions from flake8 import exceptions
from flake8.defaults import VALID_CODE_PREFIX
from flake8.options.manager import OptionManager from flake8.options.manager import OptionManager
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -120,6 +121,16 @@ def parse_config(
LOG.debug('Option "%s" returned value: %r', option_name, value) LOG.debug('Option "%s" returned value: %r', option_name, value)
final_value = option.normalize(value, cfg_dir) final_value = option.normalize(value, cfg_dir)
if option_name in {"ignore", "extend-ignore"}:
for error_code in final_value:
if not VALID_CODE_PREFIX.match(error_code):
raise ValueError(
f"Error code {error_code!r} "
f"supplied to {option_name!r} option "
f"does not match {VALID_CODE_PREFIX.pattern!r}"
)
assert option.config_name is not None assert option.config_name is not None
config_dict[option.config_name] = final_value config_dict[option.config_name] = final_value

View file

@ -5,7 +5,6 @@ import configparser
import inspect import inspect
import itertools import itertools
import logging import logging
import re
import sys import sys
from typing import Any from typing import Any
from typing import Generator from typing import Generator
@ -14,13 +13,12 @@ from typing import NamedTuple
from flake8 import utils from flake8 import utils
from flake8._compat import importlib_metadata from flake8._compat import importlib_metadata
from flake8.defaults import VALID_CODE_PREFIX
from flake8.exceptions import ExecutionError from flake8.exceptions import ExecutionError
from flake8.exceptions import FailedToLoadPlugin from flake8.exceptions import FailedToLoadPlugin
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
VALID_CODE = re.compile("^[A-Z]{1,3}[0-9]{0,3}$", re.ASCII)
FLAKE8_GROUPS = frozenset(("flake8.extension", "flake8.report")) FLAKE8_GROUPS = frozenset(("flake8.extension", "flake8.report"))
BANNED_PLUGINS = { BANNED_PLUGINS = {
@ -337,10 +335,10 @@ def _classify_plugins(
raise NotImplementedError(f"what plugin type? {loaded}") raise NotImplementedError(f"what plugin type? {loaded}")
for loaded in itertools.chain(tree, logical_line, physical_line): for loaded in itertools.chain(tree, logical_line, physical_line):
if not VALID_CODE.match(loaded.entry_name): if not VALID_CODE_PREFIX.match(loaded.entry_name):
raise ExecutionError( raise ExecutionError(
f"plugin code for `{loaded.display_name}` does not match " f"plugin code for `{loaded.display_name}` does not match "
f"{VALID_CODE.pattern}" f"{VALID_CODE_PREFIX.pattern}"
) )
return Plugins( return Plugins(

View file

@ -31,37 +31,6 @@ def _loaded(plugin=None, obj=None, parameters=None):
return finder.LoadedPlugin(plugin, obj, parameters) return finder.LoadedPlugin(plugin, obj, parameters)
@pytest.mark.parametrize(
"s",
(
"E",
"E1",
"E123",
"ABC",
"ABC1",
"ABC123",
),
)
def test_valid_plugin_prefixes(s):
assert finder.VALID_CODE.match(s)
@pytest.mark.parametrize(
"s",
(
"",
"A1234",
"ABCD",
"abc",
"a-b",
"",
"A𝟗",
),
)
def test_invalid_plugin_prefixes(s):
assert finder.VALID_CODE.match(s) is None
def test_loaded_plugin_entry_name_vs_display_name(): def test_loaded_plugin_entry_name_vs_display_name():
loaded = _loaded(_plugin(package="package-name", ep=_ep(name="Q"))) loaded = _loaded(_plugin(package="package-name", ep=_ep(name="Q")))
assert loaded.entry_name == "Q" assert loaded.entry_name == "Q"

View file

@ -0,0 +1,36 @@
from __future__ import annotations
import pytest
from flake8.defaults import VALID_CODE_PREFIX
@pytest.mark.parametrize(
"s",
(
"E",
"E1",
"E123",
"ABC",
"ABC1",
"ABC123",
),
)
def test_valid_plugin_prefixes(s):
assert VALID_CODE_PREFIX.match(s)
@pytest.mark.parametrize(
"s",
(
"",
"A1234",
"ABCD",
"abc",
"a-b",
"",
"A𝟗",
),
)
def test_invalid_plugin_prefixes(s):
assert VALID_CODE_PREFIX.match(s) is None

View file

@ -220,3 +220,35 @@ def test_parse_config_ignores_unknowns(tmp_path, opt_manager, caplog):
def test_load_config_missing_file_raises_exception(capsys): def test_load_config_missing_file_raises_exception(capsys):
with pytest.raises(exceptions.ExecutionError): with pytest.raises(exceptions.ExecutionError):
config.load_config("foo.cfg", []) config.load_config("foo.cfg", [])
def test_invalid_ignore_codes_raise_error(tmpdir, opt_manager):
tmpdir.join("setup.cfg").write("[flake8]\nignore = E203, //comment")
with tmpdir.as_cwd():
cfg, _ = config.load_config("setup.cfg", [], isolated=False)
with pytest.raises(ValueError) as excinfo:
config.parse_config(opt_manager, cfg, tmpdir)
expected = (
"Error code '//comment' supplied to 'ignore' option "
"does not match '^[A-Z]{1,3}[0-9]{0,3}$'"
)
(msg,) = excinfo.value.args
assert msg == expected
def test_invalid_extend_ignore_codes_raise_error(tmpdir, opt_manager):
tmpdir.join("setup.cfg").write("[flake8]\nextend-ignore = E203, //comment")
with tmpdir.as_cwd():
cfg, _ = config.load_config("setup.cfg", [], isolated=False)
with pytest.raises(ValueError) as excinfo:
config.parse_config(opt_manager, cfg, tmpdir)
expected = (
"Error code '//comment' supplied to 'extend-ignore' option "
"does not match '^[A-Z]{1,3}[0-9]{0,3}$'"
)
(msg,) = excinfo.value.args
assert msg == expected