mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-13 08:04:18 +00:00
Adds warning when invalid error codes are parsed for ignore or extend-ignore from config file
This commit is contained in:
parent
5eeee3fbc0
commit
1346ddefd3
6 changed files with 84 additions and 36 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
36
tests/unit/test_defaults.py
Normal file
36
tests/unit/test_defaults.py
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue