mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-08 22:04:17 +00:00
Add tests for BaseFormatter
This commit is contained in:
parent
15043a4ab7
commit
ba2d94888c
2 changed files with 127 additions and 12 deletions
|
|
@ -55,7 +55,7 @@ class BaseFormatter(object):
|
||||||
def handle(self, error):
|
def handle(self, error):
|
||||||
"""Handle an error reported by Flake8.
|
"""Handle an error reported by Flake8.
|
||||||
|
|
||||||
This defaults to calling :meth:`format`, :meth:`format_source`, and
|
This defaults to calling :meth:`format`, :meth:`show_source`, and
|
||||||
then :meth:`write`. To extend how errors are handled, override this
|
then :meth:`write`. To extend how errors are handled, override this
|
||||||
method.
|
method.
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ class BaseFormatter(object):
|
||||||
flake8.style_guide.Error
|
flake8.style_guide.Error
|
||||||
"""
|
"""
|
||||||
line = self.format(error)
|
line = self.format(error)
|
||||||
source = self.format_source(error)
|
source = self.show_source(error)
|
||||||
self.write(line, source)
|
self.write(line, source)
|
||||||
|
|
||||||
def format(self, error):
|
def format(self, error):
|
||||||
|
|
@ -85,11 +85,19 @@ class BaseFormatter(object):
|
||||||
raise NotImplementedError('Subclass of BaseFormatter did not implement'
|
raise NotImplementedError('Subclass of BaseFormatter did not implement'
|
||||||
' format.')
|
' format.')
|
||||||
|
|
||||||
def format_source(self, error):
|
def show_benchmarks(self, benchmarks):
|
||||||
"""Format the physical line generating the error.
|
pass
|
||||||
|
|
||||||
|
def show_source(self, error):
|
||||||
|
"""Show the physical line generating the error.
|
||||||
|
|
||||||
|
This also adds an indicator for the particular part of the line that
|
||||||
|
is reported as generating the problem.
|
||||||
|
|
||||||
:param error:
|
:param error:
|
||||||
This will be an instance of :class:`~flake8.style_guide.Error`.
|
This will be an instance of :class:`~flake8.style_guide.Error`.
|
||||||
|
:type error:
|
||||||
|
flake8.style_guide.Error
|
||||||
:returns:
|
:returns:
|
||||||
The formatted error string if the user wants to show the source.
|
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
|
If the user does not want to show the source, this will return
|
||||||
|
|
@ -104,6 +112,13 @@ class BaseFormatter(object):
|
||||||
# one
|
# one
|
||||||
return error.physical_line + pointer
|
return error.physical_line + pointer
|
||||||
|
|
||||||
|
def _write(self, output):
|
||||||
|
"""Handle logic of whether to use an output file or print()."""
|
||||||
|
if self.output_fd is not None:
|
||||||
|
self.output_fd.write(output + self.newline)
|
||||||
|
else:
|
||||||
|
print(output)
|
||||||
|
|
||||||
def write(self, line, source):
|
def write(self, line, source):
|
||||||
"""Write the line either to the output file or stdout.
|
"""Write the line either to the output file or stdout.
|
||||||
|
|
||||||
|
|
@ -113,16 +128,13 @@ class BaseFormatter(object):
|
||||||
|
|
||||||
:param str line:
|
:param str line:
|
||||||
The formatted string to print or write.
|
The formatted string to print or write.
|
||||||
|
:param str source:
|
||||||
|
The source code that has been formatted and associated with the
|
||||||
|
line of output.
|
||||||
"""
|
"""
|
||||||
if self.output_fd is not None:
|
self._write(line)
|
||||||
write = self.output_fd.write
|
|
||||||
output_func = lambda line: write(line + self.newline)
|
|
||||||
else:
|
|
||||||
output_func = print
|
|
||||||
|
|
||||||
output_func(line)
|
|
||||||
if source:
|
if source:
|
||||||
output_func(source)
|
self._write(source)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Clean up after reporting is finished."""
|
"""Clean up after reporting is finished."""
|
||||||
|
|
|
||||||
103
tests/unit/test_base_formatter.py
Normal file
103
tests/unit/test_base_formatter.py
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
"""Tests for the BaseFormatter object."""
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from flake8.formatting import base
|
||||||
|
from flake8 import style_guide
|
||||||
|
|
||||||
|
|
||||||
|
def options(**kwargs):
|
||||||
|
"""Create an optparse.Values instance."""
|
||||||
|
kwargs.setdefault('output_file', None)
|
||||||
|
return optparse.Values(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('filename', [None, 'out.txt'])
|
||||||
|
def test_start(filename):
|
||||||
|
"""Verify we open a new file in the start method."""
|
||||||
|
mock_open = mock.mock_open()
|
||||||
|
formatter = base.BaseFormatter(options(output_file=filename))
|
||||||
|
with mock.patch('flake8.formatting.base.open', mock_open):
|
||||||
|
formatter.start()
|
||||||
|
|
||||||
|
if filename is None:
|
||||||
|
assert mock_open.called is False
|
||||||
|
else:
|
||||||
|
mock_open.assert_called_once_with(filename, 'w')
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop():
|
||||||
|
"""Verify we close open file objects."""
|
||||||
|
filemock = mock.Mock()
|
||||||
|
formatter = base.BaseFormatter(options())
|
||||||
|
formatter.output_fd = filemock
|
||||||
|
formatter.stop()
|
||||||
|
|
||||||
|
filemock.close.assert_called_once_with()
|
||||||
|
assert formatter.output_fd is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_format_needs_to_be_implemented():
|
||||||
|
"""Ensure BaseFormatter#format raises a NotImplementedError."""
|
||||||
|
formatter = base.BaseFormatter(options())
|
||||||
|
with pytest.raises(NotImplementedError):
|
||||||
|
formatter.format('foo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_show_source_returns_nothing_when_not_showing_source():
|
||||||
|
"""Ensure we return nothing when users want nothing."""
|
||||||
|
formatter = base.BaseFormatter(options(show_source=False))
|
||||||
|
assert formatter.show_source(
|
||||||
|
style_guide.Error('A000', 'file.py', 1, 1, 'error text', 'line')
|
||||||
|
) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('line, column', [
|
||||||
|
('x=1\n', 2),
|
||||||
|
(' x=(1\n +2)\n', 5),
|
||||||
|
# TODO(sigmavirus24): Add more examples
|
||||||
|
])
|
||||||
|
def test_show_source_updates_physical_line_appropriately(line, column):
|
||||||
|
"""Ensure the error column is appropriately indicated."""
|
||||||
|
formatter = base.BaseFormatter(options(show_source=True))
|
||||||
|
error = style_guide.Error('A000', 'file.py', 1, column, 'error', line)
|
||||||
|
output = formatter.show_source(error)
|
||||||
|
_, pointer = output.rsplit('\n', 1)
|
||||||
|
assert pointer.count(' ') == column
|
||||||
|
|
||||||
|
|
||||||
|
def test_write_uses_an_output_file():
|
||||||
|
"""Verify that we use the output file when it's present."""
|
||||||
|
line = 'Something to write'
|
||||||
|
source = 'source'
|
||||||
|
filemock = mock.Mock()
|
||||||
|
|
||||||
|
formatter = base.BaseFormatter(options())
|
||||||
|
formatter.output_fd = filemock
|
||||||
|
formatter.write(line, source)
|
||||||
|
|
||||||
|
assert filemock.write.called is True
|
||||||
|
assert filemock.write.call_count == 2
|
||||||
|
assert filemock.write.mock_calls == [
|
||||||
|
mock.call(line + formatter.newline),
|
||||||
|
mock.call(source + formatter.newline),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch('flake8.formatting.base.print')
|
||||||
|
def test_write_uses_print(print_function):
|
||||||
|
"""Verify that we use the print function without an output file."""
|
||||||
|
line = 'Something to write'
|
||||||
|
source = 'source'
|
||||||
|
|
||||||
|
formatter = base.BaseFormatter(options())
|
||||||
|
formatter.write(line, source)
|
||||||
|
|
||||||
|
assert print_function.called is True
|
||||||
|
assert print_function.call_count == 2
|
||||||
|
assert print_function.mock_calls == [
|
||||||
|
mock.call(line),
|
||||||
|
mock.call(source),
|
||||||
|
]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue