mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-04 12:16:53 +00:00
Add handling and decision making for select and ignore
This commit is contained in:
parent
0645ec3ef7
commit
eafc91ae6a
4 changed files with 249 additions and 6 deletions
|
|
@ -1,4 +1,30 @@
|
|||
"""Implementation of the StyleGuide used by Flake8."""
|
||||
import enum
|
||||
|
||||
__all__ = (
|
||||
'StyleGuide',
|
||||
)
|
||||
|
||||
|
||||
class Selected(enum.Enum):
|
||||
"""Enum representing an explicitly or implicitly selected code."""
|
||||
|
||||
Explicitly = 'explicitly selected'
|
||||
Implicitly = 'implicitly selected'
|
||||
|
||||
|
||||
class Ignored(enum.Enum):
|
||||
"""Enum representing an explicitly or implicitly ignored code."""
|
||||
|
||||
Explicitly = 'explicitly ignored'
|
||||
Implicitly = 'implicitly ignored'
|
||||
|
||||
|
||||
class Decision(enum.Enum):
|
||||
"""Enum representing whether a code should be ignored or selected."""
|
||||
|
||||
Ignored = 'ignored error'
|
||||
Selected = 'selected error'
|
||||
|
||||
|
||||
class StyleGuide(object):
|
||||
|
|
@ -10,7 +36,85 @@ class StyleGuide(object):
|
|||
|
||||
.. todo:: Add parameter documentation.
|
||||
"""
|
||||
pass
|
||||
self.options = options
|
||||
self.arguments = arguments
|
||||
self.checkers = checker_plugins
|
||||
self.listeners = listening_plugins
|
||||
self.formatters = formatting_plugins
|
||||
self._selected = tuple(options.select)
|
||||
self._ignored = tuple(options.ignore)
|
||||
self._decision_cache = {}
|
||||
|
||||
def is_user_selected(self, code):
|
||||
"""Determine if the code has been selected by the user.
|
||||
|
||||
:param str code:
|
||||
The code for the check that has been run.
|
||||
:returns:
|
||||
Selected.Implicitly if the selected list is empty,
|
||||
Selected.Explicitly if the selected list is not empty and a match
|
||||
was found,
|
||||
Ignored.Implicitly if the selected list is not empty but no match
|
||||
was found.
|
||||
"""
|
||||
if not self._selected:
|
||||
return Selected.Implicitly
|
||||
|
||||
if code.startswith(self._selected):
|
||||
return Selected.Explicitly
|
||||
|
||||
return Ignored.Implicitly
|
||||
|
||||
def is_user_ignored(self, code):
|
||||
"""Determine if the code has been ignored by the user.
|
||||
|
||||
:param str code:
|
||||
The code for the check that has been run.
|
||||
:returns:
|
||||
Selected.Implicitly if the ignored list is empty,
|
||||
Ignored.Explicitly if the ignored list is not empty and a match was
|
||||
found,
|
||||
Selected.Implicitly if the ignored list is not empty but no match
|
||||
was found.
|
||||
"""
|
||||
if self._ignored and code.startswith(self._ignored):
|
||||
return Ignored.Explicitly
|
||||
|
||||
return Selected.Implicitly
|
||||
|
||||
def _decision_for(self, code):
|
||||
startswith = code.startswith
|
||||
selected = sorted([s for s in self._selected if startswith(s)])[0]
|
||||
ignored = sorted([i for i in self._ignored if startswith(i)])[0]
|
||||
|
||||
if selected.startswith(ignored):
|
||||
return Decision.Selected
|
||||
return Decision.Ignored
|
||||
|
||||
def should_report_error(self, code):
|
||||
"""Determine if the error code should be reported or ignored.
|
||||
|
||||
:param str code:
|
||||
The code for the check that has been run.
|
||||
"""
|
||||
decision = self._decision_cache.get(code)
|
||||
if decision is None:
|
||||
selected = self.is_user_selected(code)
|
||||
ignored = self.is_user_ignored(code)
|
||||
|
||||
if ((selected is Selected.Explicitly or
|
||||
selected is Selected.Implicitly) and
|
||||
ignored is Selected.Implicitly):
|
||||
decision = Decision.Selected
|
||||
elif (selected is Selected.Explicitly and
|
||||
ignored is Ignored.Explicitly):
|
||||
decision = self._decision_for(code)
|
||||
elif (selected is Ignored.Implicitly or
|
||||
ignored is Ignored.Explicitly):
|
||||
decision = Decision.Ignored
|
||||
|
||||
self._decision_cache[code] = decision
|
||||
return decision
|
||||
|
||||
|
||||
# Should separate style guide logic from code that runs checks
|
||||
|
|
|
|||
|
|
@ -3,3 +3,7 @@ test=pytest
|
|||
|
||||
[bdist_wheel]
|
||||
universal=1
|
||||
|
||||
[metadata]
|
||||
requires-dist =
|
||||
enum34; python_version<"3.4"
|
||||
|
|
|
|||
17
setup.py
17
setup.py
|
|
@ -2,6 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import with_statement
|
||||
import setuptools
|
||||
import sys
|
||||
|
||||
import flake8
|
||||
|
||||
|
|
@ -25,6 +26,16 @@ if mock is None:
|
|||
tests_require += ['mock']
|
||||
|
||||
|
||||
requires = [
|
||||
"pyflakes >= 0.8.1, < 1.1",
|
||||
"pep8 >= 1.5.7, != 1.6.0, != 1.6.1, != 1.6.2",
|
||||
# "mccabe >= 0.2.1, < 0.4",
|
||||
]
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
requires.append("enum34")
|
||||
|
||||
|
||||
def get_long_description():
|
||||
"""Generate a long description from the README and CHANGES files."""
|
||||
descr = []
|
||||
|
|
@ -51,11 +62,7 @@ setuptools.setup(
|
|||
"flake8.options",
|
||||
"flake8.plugins",
|
||||
],
|
||||
install_requires=[
|
||||
"pyflakes >= 0.8.1, < 1.1",
|
||||
"pep8 >= 1.5.7, != 1.6.0, != 1.6.1, != 1.6.2",
|
||||
# "mccabe >= 0.2.1, < 0.4",
|
||||
],
|
||||
install_requires=requires,
|
||||
entry_points={
|
||||
'distutils.commands': ['flake8 = flake8.main:Flake8Command'],
|
||||
'console_scripts': ['flake8 = flake8.main.cli:main'],
|
||||
|
|
|
|||
128
tests/unit/test_style_guide.py
Normal file
128
tests/unit/test_style_guide.py
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
"""Tests for the flake8.style_guide.StyleGuide class."""
|
||||
import optparse
|
||||
|
||||
from flake8 import style_guide
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def create_options(**kwargs):
|
||||
"""Create and return an instance of optparse.Values."""
|
||||
kwargs.setdefault('select', [])
|
||||
kwargs.setdefault('ignore', [])
|
||||
return optparse.Values(kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ignore_list,error_code', [
|
||||
(['E111', 'E121'], 'E111'),
|
||||
(['E111', 'E121'], 'E121'),
|
||||
(['E11', 'E12'], 'E121'),
|
||||
(['E2', 'E12'], 'E121'),
|
||||
(['E2', 'E12'], 'E211'),
|
||||
])
|
||||
def test_is_user_ignored_ignores_errors(ignore_list, error_code):
|
||||
"""Verify we detect users explicitly ignoring an error."""
|
||||
guide = style_guide.StyleGuide(create_options(ignore=ignore_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert guide.is_user_ignored(error_code) is style_guide.Ignored.Explicitly
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ignore_list,error_code', [
|
||||
(['E111', 'E121'], 'E112'),
|
||||
(['E111', 'E121'], 'E122'),
|
||||
(['E11', 'E12'], 'W121'),
|
||||
(['E2', 'E12'], 'E112'),
|
||||
(['E2', 'E12'], 'E111'),
|
||||
])
|
||||
def test_is_user_ignored_implicitly_selects_errors(ignore_list, error_code):
|
||||
"""Verify we detect users does not explicitly ignore an error."""
|
||||
guide = style_guide.StyleGuide(create_options(ignore=ignore_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert guide.is_user_ignored(error_code) is style_guide.Selected.Implicitly
|
||||
|
||||
|
||||
@pytest.mark.parametrize('select_list,error_code', [
|
||||
(['E111', 'E121'], 'E111'),
|
||||
(['E111', 'E121'], 'E121'),
|
||||
(['E11', 'E12'], 'E121'),
|
||||
(['E2', 'E12'], 'E121'),
|
||||
(['E2', 'E12'], 'E211'),
|
||||
])
|
||||
def test_is_user_selected_selects_errors(select_list, error_code):
|
||||
"""Verify we detect users explicitly selecting an error."""
|
||||
guide = style_guide.StyleGuide(create_options(select=select_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert (guide.is_user_selected(error_code) is
|
||||
style_guide.Selected.Explicitly)
|
||||
|
||||
|
||||
def test_is_user_selected_implicitly_selects_errors():
|
||||
"""Verify we detect users implicitly selecting an error."""
|
||||
select_list = []
|
||||
error_code = 'E121'
|
||||
guide = style_guide.StyleGuide(create_options(select=select_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert (guide.is_user_selected(error_code) is
|
||||
style_guide.Selected.Implicitly)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('select_list,error_code', [
|
||||
(['E111', 'E121'], 'E112'),
|
||||
(['E111', 'E121'], 'E122'),
|
||||
(['E11', 'E12'], 'E132'),
|
||||
(['E2', 'E12'], 'E321'),
|
||||
(['E2', 'E12'], 'E410'),
|
||||
])
|
||||
def test_is_user_selected_excludes_errors(select_list, error_code):
|
||||
"""Verify we detect users implicitly excludes an error."""
|
||||
guide = style_guide.StyleGuide(create_options(select=select_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert guide.is_user_selected(error_code) is style_guide.Ignored.Implicitly
|
||||
|
||||
|
||||
@pytest.mark.parametrize('select_list,ignore_list,error_code,expected', [
|
||||
(['E111', 'E121'], [], 'E111', style_guide.Decision.Selected),
|
||||
(['E111', 'E121'], [], 'E112', style_guide.Decision.Ignored),
|
||||
(['E111', 'E121'], [], 'E121', style_guide.Decision.Selected),
|
||||
(['E111', 'E121'], [], 'E122', style_guide.Decision.Ignored),
|
||||
(['E11', 'E12'], [], 'E132', style_guide.Decision.Ignored),
|
||||
(['E2', 'E12'], [], 'E321', style_guide.Decision.Ignored),
|
||||
(['E2', 'E12'], [], 'E410', style_guide.Decision.Ignored),
|
||||
(['E11', 'E121'], ['E1'], 'E112', style_guide.Decision.Selected),
|
||||
(['E111', 'E121'], ['E2'], 'E122', style_guide.Decision.Ignored),
|
||||
(['E11', 'E12'], ['E13'], 'E132', style_guide.Decision.Ignored),
|
||||
(['E1', 'E3'], ['E32'], 'E321', style_guide.Decision.Ignored),
|
||||
([], ['E2', 'E12'], 'E410', style_guide.Decision.Selected),
|
||||
(['E4'], ['E2', 'E12', 'E41'], 'E410', style_guide.Decision.Ignored),
|
||||
(['E41'], ['E2', 'E12', 'E4'], 'E410', style_guide.Decision.Selected),
|
||||
])
|
||||
def test_should_report_error(select_list, ignore_list, error_code, expected):
|
||||
"""Verify we decide when to report an error."""
|
||||
guide = style_guide.StyleGuide(create_options(select=select_list,
|
||||
ignore=ignore_list),
|
||||
arguments=[],
|
||||
checker_plugins=None,
|
||||
listening_plugins=None,
|
||||
formatting_plugins=None)
|
||||
|
||||
assert guide.should_report_error(error_code) is expected
|
||||
Loading…
Add table
Add a link
Reference in a new issue