Skip to content

Commit

Permalink
Merge pull request PyCQA#1713 from mennoliefstingh/1689-warn-invalid-…
Browse files Browse the repository at this point in the history
…error-code

Adds error when incorrect error codes are parsed from config file
  • Loading branch information
asottile authored Nov 7, 2022
2 parents 5eeee3f + 1346dde commit ad1006e
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/flake8/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@
)

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)
11 changes: 11 additions & 0 deletions src/flake8/options/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Any

from flake8 import exceptions
from flake8.defaults import VALID_CODE_PREFIX
from flake8.options.manager import OptionManager

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -120,6 +121,16 @@ def parse_config(
LOG.debug('Option "%s" returned value: %r', option_name, value)

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
config_dict[option.config_name] = final_value

Expand Down
8 changes: 3 additions & 5 deletions src/flake8/plugins/finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import inspect
import itertools
import logging
import re
import sys
from typing import Any
from typing import Generator
Expand All @@ -14,13 +13,12 @@

from flake8 import utils
from flake8._compat import importlib_metadata
from flake8.defaults import VALID_CODE_PREFIX
from flake8.exceptions import ExecutionError
from flake8.exceptions import FailedToLoadPlugin

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"))

BANNED_PLUGINS = {
Expand Down Expand Up @@ -337,10 +335,10 @@ def _classify_plugins(
raise NotImplementedError(f"what plugin type? {loaded}")

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(
f"plugin code for `{loaded.display_name}` does not match "
f"{VALID_CODE.pattern}"
f"{VALID_CODE_PREFIX.pattern}"
)

return Plugins(
Expand Down
31 changes: 0 additions & 31 deletions tests/unit/plugins/finder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,37 +31,6 @@ def _loaded(plugin=None, obj=None, parameters=None):
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():
loaded = _loaded(_plugin(package="package-name", ep=_ep(name="Q")))
assert loaded.entry_name == "Q"
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/test_defaults.py
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions tests/unit/test_options_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,35 @@ def test_parse_config_ignores_unknowns(tmp_path, opt_manager, caplog):
def test_load_config_missing_file_raises_exception(capsys):
with pytest.raises(exceptions.ExecutionError):
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

0 comments on commit ad1006e

Please sign in to comment.