mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-04 04:06:54 +00:00
Refactor Error formatting and handling
This allows us to handle --show-source in our formatters by default. This also adds the physical line information to the Error class instead of passing it to is_inline_ignored. This allows us to avoid using linecache in our formatters.
This commit is contained in:
parent
8300e0f97c
commit
467672fc5c
3 changed files with 54 additions and 17 deletions
|
|
@ -55,8 +55,9 @@ class BaseFormatter(object):
|
|||
def handle(self, error):
|
||||
"""Handle an error reported by Flake8.
|
||||
|
||||
This defaults to calling :meth:`format` and then :meth:`write`. To
|
||||
extend how errors are handled, override this method.
|
||||
This defaults to calling :meth:`format`, :meth:`format_source`, and
|
||||
then :meth:`write`. To extend how errors are handled, override this
|
||||
method.
|
||||
|
||||
:param error:
|
||||
This will be an instance of :class:`~flake8.style_guide.Error`.
|
||||
|
|
@ -64,7 +65,8 @@ class BaseFormatter(object):
|
|||
flake8.style_guide.Error
|
||||
"""
|
||||
line = self.format(error)
|
||||
self.write(line)
|
||||
source = self.format_source(error)
|
||||
self.write(line, source)
|
||||
|
||||
def format(self, error):
|
||||
"""Format an error reported by Flake8.
|
||||
|
|
@ -83,7 +85,26 @@ class BaseFormatter(object):
|
|||
raise NotImplementedError('Subclass of BaseFormatter did not implement'
|
||||
' format.')
|
||||
|
||||
def write(self, line):
|
||||
def format_source(self, error):
|
||||
"""Format the physical line generating the error.
|
||||
|
||||
:param error:
|
||||
This will be an instance of :class:`~flake8.style_guide.Error`.
|
||||
:returns:
|
||||
The formatted error string if the user wants to show the source.
|
||||
If the user does not want to show the source, this will return
|
||||
``None``.
|
||||
:rtype:
|
||||
str
|
||||
"""
|
||||
if not self.options.show_source:
|
||||
return None
|
||||
pointer = (' ' * error.column_number) + '^'
|
||||
# Physical lines have a newline at the end, no need to add an extra
|
||||
# one
|
||||
return error.physical_line + pointer
|
||||
|
||||
def write(self, line, source):
|
||||
"""Write the line either to the output file or stdout.
|
||||
|
||||
This handles deciding whether to write to a file or print to standard
|
||||
|
|
@ -94,9 +115,14 @@ class BaseFormatter(object):
|
|||
The formatted string to print or write.
|
||||
"""
|
||||
if self.output_fd is not None:
|
||||
self.output_fd.write(line + self.newline)
|
||||
write = self.output_fd.write
|
||||
output_func = lambda line: write(line + self.newline)
|
||||
else:
|
||||
print(line)
|
||||
output_func = print
|
||||
|
||||
output_func(line)
|
||||
if source:
|
||||
output_func(source)
|
||||
|
||||
def stop(self):
|
||||
"""Clean up after reporting is finished."""
|
||||
|
|
|
|||
|
|
@ -36,11 +36,17 @@ class Decision(enum.Enum):
|
|||
Selected = 'selected error'
|
||||
|
||||
|
||||
Error = collections.namedtuple('Error', ['code',
|
||||
'filename',
|
||||
'line_number',
|
||||
'column_number',
|
||||
'text'])
|
||||
Error = collections.namedtuple(
|
||||
'Error',
|
||||
[
|
||||
'code',
|
||||
'filename',
|
||||
'line_number',
|
||||
'column_number',
|
||||
'text',
|
||||
'physical_line',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class StyleGuide(object):
|
||||
|
|
@ -157,9 +163,10 @@ class StyleGuide(object):
|
|||
LOG.debug('"%s" will be "%s"', code, decision)
|
||||
return decision
|
||||
|
||||
def is_inline_ignored(self, error, physical_line=None):
|
||||
def is_inline_ignored(self, error):
|
||||
# type: (Error) -> bool
|
||||
"""Determine if an comment has been added to ignore this line."""
|
||||
physical_line = error.physical_line
|
||||
# TODO(sigmavirus24): Determine how to handle stdin with linecache
|
||||
if self.options.disable_noqa:
|
||||
return False
|
||||
|
|
@ -191,9 +198,10 @@ class StyleGuide(object):
|
|||
physical_line=None):
|
||||
# type: (str, str, int, int, str) -> NoneType
|
||||
"""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,
|
||||
physical_line)
|
||||
if (self.should_report_error(error.code) is Decision.Selected and
|
||||
self.is_inline_ignored(error, physical_line) is False):
|
||||
self.is_inline_ignored(error) is False):
|
||||
self.formatter.handle(error)
|
||||
self.listener.notify(error.code, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ def test_is_inline_ignored(error_code, physical_line, expected_result):
|
|||
guide = style_guide.StyleGuide(create_options(select=['E', 'W', 'F']),
|
||||
listener_trie=None,
|
||||
formatter=None)
|
||||
error = style_guide.Error(error_code, 'filename.py', 1, 1, 'error text')
|
||||
error = style_guide.Error(error_code, 'filename.py', 1, 1, 'error text',
|
||||
physical_line)
|
||||
|
||||
with mock.patch('linecache.getline', return_value=physical_line):
|
||||
assert guide.is_inline_ignored(error) is expected_result
|
||||
|
|
@ -145,7 +146,8 @@ def test_disable_is_inline_ignored():
|
|||
guide = style_guide.StyleGuide(create_options(disable_noqa=True),
|
||||
listener_trie=None,
|
||||
formatter=None)
|
||||
error = style_guide.Error('E121', 'filename.py', 1, 1, 'error text')
|
||||
error = style_guide.Error('E121', 'filename.py', 1, 1, 'error text',
|
||||
'line')
|
||||
|
||||
with mock.patch('linecache.getline') as getline:
|
||||
assert guide.is_inline_ignored(error) is False
|
||||
|
|
@ -171,7 +173,8 @@ def test_handle_error_notifies_listeners(select_list, ignore_list, error_code):
|
|||
|
||||
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',
|
||||
None)
|
||||
listener_trie.notify.assert_called_once_with(error_code, error)
|
||||
formatter.handle.assert_called_once_with(error)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue