Add --tee option to split report output stream.

The --tee option allows the linter report to be written to stdout, even
though it is being redirected to a file with the --output-file option.
This is useful if I want to store the report in a separate file for later
analysis but also be able to print the output on screen (e.g when running
in a CI environment).
This commit is contained in:
Martin Domke 2016-07-26 15:57:13 +02:00
parent f82b5d62d0
commit c782060a06
5 changed files with 43 additions and 7 deletions

View file

@ -125,6 +125,7 @@ And you should see something like:
available to use. (Default: auto) available to use. (Default: auto)
--output-file=OUTPUT_FILE --output-file=OUTPUT_FILE
Redirect report to a file. Redirect report to a file.
--tee Write to stdout and output-file.
--append-config=APPEND_CONFIG --append-config=APPEND_CONFIG
Provide extra config files to parse in addition to the Provide extra config files to parse in addition to the
files found by Flake8 by default. These files are the files found by Flake8 by default. These files are the

View file

@ -563,6 +563,26 @@
output_file = output.txt output_file = output.txt
.. option:: --tee
Also print output to stdout if output-file has ben configured.
Command-line example:
.. prompt:: bash
flake8 --tee --output-file=output.txt dir/
This **can** be specified in config files.
Example config file usage:
.. code-block:: ini
output-file = output.txt
tee = True
.. option:: --append-config=<config> .. option:: --append-config=<config>
Provide extra config files to parse in after and in addition to the files Provide extra config files to parse in after and in addition to the files

View file

@ -148,7 +148,7 @@ class BaseFormatter(object):
"""Handle logic of whether to use an output file or print().""" """Handle logic of whether to use an output file or print()."""
if self.output_fd is not None: if self.output_fd is not None:
self.output_fd.write(output + self.newline) self.output_fd.write(output + self.newline)
else: if self.output_fd is None or self.options.tee:
print(output) print(output)
def write(self, line, source): def write(self, line, source):

View file

@ -26,6 +26,7 @@ def register_default_options(option_manager):
- ``--exit-zero`` - ``--exit-zero``
- ``-j``/``--jobs`` - ``-j``/``--jobs``
- ``--output-file`` - ``--output-file``
- ``--tee``
- ``--append-config`` - ``--append-config``
- ``--config`` - ``--config``
- ``--isolated`` - ``--isolated``
@ -171,6 +172,11 @@ def register_default_options(option_manager):
help='Redirect report to a file.', help='Redirect report to a file.',
) )
add_option(
'--tee', default=False, parse_from_config=True, action='store_true',
help='Write to stdout and output-file.',
)
# Config file options # Config file options
add_option( add_option(

View file

@ -1,4 +1,5 @@
"""Tests for the BaseFormatter object.""" """Tests for the BaseFormatter object."""
import io
import optparse import optparse
import mock import mock
@ -11,6 +12,7 @@ from flake8.formatting import base
def options(**kwargs): def options(**kwargs):
"""Create an optparse.Values instance.""" """Create an optparse.Values instance."""
kwargs.setdefault('output_file', None) kwargs.setdefault('output_file', None)
kwargs.setdefault('tee', False)
return optparse.Values(kwargs) return optparse.Values(kwargs)
@ -76,15 +78,22 @@ def test_show_source_updates_physical_line_appropriately(line, column):
assert pointer.count(' ') == column assert pointer.count(' ') == column
def test_write_uses_an_output_file(): @pytest.mark.parametrize('tee', [False, True])
def test_write_uses_an_output_file(tee):
"""Verify that we use the output file when it's present.""" """Verify that we use the output file when it's present."""
line = 'Something to write' line = u'Something to write'
source = 'source' source = u'source'
filemock = mock.Mock() filemock = mock.Mock()
formatter = base.BaseFormatter(options()) with mock.patch('sys.stdout', new_callable=io.StringIO) as stdout:
formatter = base.BaseFormatter(options(tee=tee))
formatter.output_fd = filemock formatter.output_fd = filemock
formatter.write(line, source) formatter.write(line, source)
if tee:
output = line + formatter.newline + source + formatter.newline
else:
output = ''
assert stdout.getvalue() == output
assert filemock.write.called is True assert filemock.write.called is True
assert filemock.write.call_count == 2 assert filemock.write.call_count == 2