mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-15 16:49:52 +00:00
Add checking for inline #noqa comments
This also supports ignoring only specified codes
This commit is contained in:
parent
a9a939cbbc
commit
f4b18229a0
2 changed files with 53 additions and 3 deletions
|
|
@ -1,9 +1,13 @@
|
||||||
"""Implementation of the StyleGuide used by Flake8."""
|
"""Implementation of the StyleGuide used by Flake8."""
|
||||||
import collections
|
import collections
|
||||||
|
import linecache
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
|
from flake8 import utils
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'StyleGuide',
|
'StyleGuide',
|
||||||
)
|
)
|
||||||
|
|
@ -43,6 +47,20 @@ Error = collections.namedtuple('Error', ['code',
|
||||||
class StyleGuide(object):
|
class StyleGuide(object):
|
||||||
"""Manage a Flake8 user's style guide."""
|
"""Manage a Flake8 user's style guide."""
|
||||||
|
|
||||||
|
NOQA_INLINE_REGEXP = re.compile(
|
||||||
|
# We're looking for items that look like this:
|
||||||
|
# ``# noqa``
|
||||||
|
# ``# noqa: E123``
|
||||||
|
# ``# noqa: E123,W451,F921``
|
||||||
|
# ``# NoQA: E123,W451,F921``
|
||||||
|
# ``# NOQA: E123,W451,F921``
|
||||||
|
# We do not care about the ``: `` that follows ``noqa``
|
||||||
|
# We do not care about the casing of ``noqa``
|
||||||
|
# We want a comma-separated list of errors
|
||||||
|
'# noqa(?:: )?(?P<codes>[A-Z0-9,]+)?$',
|
||||||
|
re.IGNORECASE
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, options, arguments, listener_trie, formatter):
|
def __init__(self, options, arguments, listener_trie, formatter):
|
||||||
"""Initialize our StyleGuide.
|
"""Initialize our StyleGuide.
|
||||||
|
|
||||||
|
|
@ -109,6 +127,12 @@ class StyleGuide(object):
|
||||||
# type: (Error) -> Decision
|
# type: (Error) -> Decision
|
||||||
"""Determine if the error code should be reported or ignored.
|
"""Determine if the error code should be reported or ignored.
|
||||||
|
|
||||||
|
This method only cares about the select and ignore rules as specified
|
||||||
|
by the user in their configuration files and command-line flags.
|
||||||
|
|
||||||
|
This method does not look at whether the specific line is being
|
||||||
|
ignored in the file itself.
|
||||||
|
|
||||||
:param str code:
|
:param str code:
|
||||||
The code for the check that has been run.
|
The code for the check that has been run.
|
||||||
"""
|
"""
|
||||||
|
|
@ -135,11 +159,35 @@ class StyleGuide(object):
|
||||||
LOG.debug('"%s" will be "%s"', code, decision)
|
LOG.debug('"%s" will be "%s"', code, decision)
|
||||||
return decision
|
return decision
|
||||||
|
|
||||||
|
def is_inline_ignored(self, error):
|
||||||
|
"""Determine if an comment has been added to ignore this line."""
|
||||||
|
physical_line = linecache.getline(error.filename, error.line_number)
|
||||||
|
noqa_match = self.NOQA_INLINE_REGEXP.search(physical_line)
|
||||||
|
if noqa_match is None:
|
||||||
|
LOG.debug('%r is not inline ignored', error)
|
||||||
|
return False
|
||||||
|
|
||||||
|
codes_str = noqa_match.groupdict()['codes']
|
||||||
|
if codes_str is None:
|
||||||
|
LOG.debug('%r is ignored by a blanket ``# noqa``', error)
|
||||||
|
return True
|
||||||
|
|
||||||
|
codes = set(utils.parse_comma_separated_list(codes_str))
|
||||||
|
if error.code in codes:
|
||||||
|
LOG.debug('%r is ignored specifically inline with ``# noqa: %s``',
|
||||||
|
error, codes_str)
|
||||||
|
return True
|
||||||
|
|
||||||
|
LOG.debug('%r is not ignored inline with ``# noqa: %s``',
|
||||||
|
error, codes_str)
|
||||||
|
return False
|
||||||
|
|
||||||
def handle_error(self, code, filename, line_number, column_number, text):
|
def handle_error(self, code, filename, line_number, column_number, text):
|
||||||
# type: (str, str, int, int, str) -> NoneType
|
# type: (str, str, int, int, str) -> NoneType
|
||||||
"""Handle an error reported by a check."""
|
"""Handle an error reported by a check."""
|
||||||
error = Error(code, filename, line_number, column_number, text)
|
error = Error(code, filename, line_number, column_number, text)
|
||||||
if self.should_report_error(error.code) is Decision.Selected:
|
if (self.should_report_error(error.code) is Decision.Selected and
|
||||||
|
self.is_inline_ignored(error) is False):
|
||||||
self.formatter.handle(error)
|
self.formatter.handle(error)
|
||||||
self.listener.notify(error.code, error)
|
self.listener.notify(error.code, error)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,8 @@ def test_handle_error_notifies_listeners(select_list, ignore_list, error_code):
|
||||||
listener_trie=listener_trie,
|
listener_trie=listener_trie,
|
||||||
formatter=formatter)
|
formatter=formatter)
|
||||||
|
|
||||||
guide.handle_error(error_code, 'stdin', 1, 1, 'error found')
|
with mock.patch('linecache.getline', return_value=''):
|
||||||
|
guide.handle_error(error_code, 'stdin', 1, 1, 'error found')
|
||||||
error = style_guide.Error(error_code, 'stdin', 1, 1, 'error found')
|
error = style_guide.Error(error_code, 'stdin', 1, 1, 'error found')
|
||||||
listener_trie.notify.assert_called_once_with(error_code, error)
|
listener_trie.notify.assert_called_once_with(error_code, error)
|
||||||
formatter.handle.assert_called_once_with(error)
|
formatter.handle.assert_called_once_with(error)
|
||||||
|
|
@ -170,6 +171,7 @@ def test_handle_error_does_not_notify_listeners(select_list, ignore_list,
|
||||||
listener_trie=listener_trie,
|
listener_trie=listener_trie,
|
||||||
formatter=formatter)
|
formatter=formatter)
|
||||||
|
|
||||||
guide.handle_error(error_code, 'stdin', 1, 1, 'error found')
|
with mock.patch('linecache.getline', return_value=''):
|
||||||
|
guide.handle_error(error_code, 'stdin', 1, 1, 'error found')
|
||||||
assert listener_trie.notify.called is False
|
assert listener_trie.notify.called is False
|
||||||
assert formatter.handle.called is False
|
assert formatter.handle.called is False
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue