Merge branch 'per-file-ignores-parse-on-load' into 'master'

WIP: Normalize 'per-file-ignores' file paths

Closes #517

See merge request pycqa/flake8!351
This commit is contained in:
Eric N. Vander Weele 2019-09-01 23:05:04 +00:00
commit 46211a8301
5 changed files with 33 additions and 23 deletions

View file

@ -1,11 +1,25 @@
"""Contains the logic for all of the default options for Flake8.""" """Contains the logic for all of the default options for Flake8."""
import argparse
import functools import functools
from typing import List, Tuple
from flake8 import defaults from flake8 import defaults
from flake8 import exceptions
from flake8 import utils
from flake8.main import debug from flake8.main import debug
from flake8.main import vcs from flake8.main import vcs
def _convert_per_file_ignores(value):
# type: (str) -> List[Tuple[str, List[str]]]
try:
mappings = utils.parse_files_to_codes_mapping(value)
except exceptions.ExecutionError as e:
raise argparse.ArgumentTypeError(e)
return [(utils.normalize_path(path), codes) for path, codes in mappings]
def register_default_options(option_manager): def register_default_options(option_manager):
"""Register the default options on our OptionManager. """Register the default options on our OptionManager.
@ -159,6 +173,7 @@ def register_default_options(option_manager):
add_option( add_option(
"--per-file-ignores", "--per-file-ignores",
type=_convert_per_file_ignores,
default="", default="",
parse_from_config=True, parse_from_config=True,
help="A pairing of filenames and violation codes that defines which " help="A pairing of filenames and violation codes that defines which "

View file

@ -347,7 +347,7 @@ class StyleGuideManager(object):
"""Generate style guides from the per-file-ignores option. """Generate style guides from the per-file-ignores option.
:param options: :param options:
The original options parsed from the CLI and config file. The normalized options parsed from the CLI and config file.
:type options: :type options:
:class:`~argparse.Namespace` :class:`~argparse.Namespace`
:returns: :returns:
@ -355,10 +355,7 @@ class StyleGuideManager(object):
:rtype: :rtype:
:class:`~flake8.style_guide.StyleGuide` :class:`~flake8.style_guide.StyleGuide`
""" """
per_file = utils.parse_files_to_codes_mapping( for filename, violations in options.per_file_ignores:
options.per_file_ignores
)
for filename, violations in per_file:
yield self.default_style_guide.copy( yield self.default_style_guide.copy(
filename=filename, extend_ignore_with=violations filename=filename, extend_ignore_with=violations
) )

View file

@ -116,11 +116,9 @@ def parse_files_to_codes_mapping(value_): # noqa: C901
return " " + s.strip().replace("\n", "\n ") return " " + s.strip().replace("\n", "\n ")
return exceptions.ExecutionError( return exceptions.ExecutionError(
"Expected `per-file-ignores` to be a mapping from file exclude " "Expected a mapping from file exclude patterns to ignore "
"patterns to ignore codes.\n\n" "codes.\n\n"
"Configured `per-file-ignores` setting:\n\n{}".format( "Found:\n\n{}".format(_indent(value))
_indent(value)
)
) )
for token in _tokenize_files_to_codes_mapping(value): for token in _tokenize_files_to_codes_mapping(value):

View file

@ -94,14 +94,14 @@ per-file-ignores =
with tmpdir.as_cwd(): with tmpdir.as_cwd():
tmpdir.join('setup.cfg').write(setup_cfg) tmpdir.join('setup.cfg').write(setup_cfg)
_call_main(['.'], retv=1) _call_main(['.'], retv=2)
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert out == '''\ assert err == '''\
There was a critical error during execution of Flake8: usage: flake8 [options] file file ...
Expected `per-file-ignores` to be a mapping from file exclude patterns to ignore codes. flake8: error: argument --per-file-ignores: Expected a mapping from file exclude patterns to ignore codes.
Configured `per-file-ignores` setting: Found:
incorrect/* incorrect/*
values/* values/*

View file

@ -45,11 +45,11 @@ def test_style_guide_manager():
assert len(guide.style_guides) == 1 assert len(guide.style_guides) == 1
PER_FILE_IGNORES_UNPARSED = [ PER_FILE_IGNORES_PARSED = [
"first_file.py:W9", ("first_file.py", ["W9"]),
"second_file.py:F4,F9", ("second_file.py", ["F4", "F9"]),
"third_file.py:E3", ("third_file.py", ["E3"]),
"sub_dir/*:F4", ("sub_dir/*", ["F4"]),
] ]
@ -75,7 +75,7 @@ def test_style_guide_applies_to(style_guide_file, filename, expected):
def test_style_guide_manager_pre_file_ignores_parsing(): def test_style_guide_manager_pre_file_ignores_parsing():
"""Verify how the StyleGuideManager creates a default style guide.""" """Verify how the StyleGuideManager creates a default style guide."""
formatter = mock.create_autospec(base.BaseFormatter, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True)
options = create_options(per_file_ignores=PER_FILE_IGNORES_UNPARSED) options = create_options(per_file_ignores=PER_FILE_IGNORES_PARSED)
guide = style_guide.StyleGuideManager(options, formatter=formatter) guide = style_guide.StyleGuideManager(options, formatter=formatter)
assert len(guide.style_guides) == 5 assert len(guide.style_guides) == 5
assert list(map(utils.normalize_path, assert list(map(utils.normalize_path,
@ -98,7 +98,7 @@ def test_style_guide_manager_pre_file_ignores(ignores, violation, filename,
formatter = mock.create_autospec(base.BaseFormatter, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True)
options = create_options(ignore=ignores, options = create_options(ignore=ignores,
select=['E', 'F', 'W'], select=['E', 'F', 'W'],
per_file_ignores=PER_FILE_IGNORES_UNPARSED) per_file_ignores=PER_FILE_IGNORES_PARSED)
guide = style_guide.StyleGuideManager(options, formatter=formatter) guide = style_guide.StyleGuideManager(options, formatter=formatter)
assert (guide.handle_error(violation, filename, 1, 1, "Fake text") assert (guide.handle_error(violation, filename, 1, 1, "Fake text")
== handle_error_return) == handle_error_return)
@ -115,7 +115,7 @@ def test_style_guide_manager_pre_file_ignores(ignores, violation, filename,
def test_style_guide_manager_style_guide_for(filename, expected): def test_style_guide_manager_style_guide_for(filename, expected):
"""Verify the style guide selection function.""" """Verify the style guide selection function."""
formatter = mock.create_autospec(base.BaseFormatter, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True)
options = create_options(per_file_ignores=PER_FILE_IGNORES_UNPARSED) options = create_options(per_file_ignores=PER_FILE_IGNORES_PARSED)
guide = style_guide.StyleGuideManager(options, formatter=formatter) guide = style_guide.StyleGuideManager(options, formatter=formatter)
file_guide = guide.style_guide_for(filename) file_guide = guide.style_guide_for(filename)