Merge branch 'form_feed_difference' into 'master'

split lines the same when read from stdin

Closes #270

See merge request pycqa/flake8!406
This commit is contained in:
Anthony Sottile 2020-01-16 22:10:39 +00:00
commit 64f90af5d9
4 changed files with 47 additions and 29 deletions

View file

@ -334,7 +334,7 @@ class FileProcessor(object):
def read_lines_from_stdin(self): def read_lines_from_stdin(self):
# type: () -> List[str] # type: () -> List[str]
"""Read the lines from standard in.""" """Read the lines from standard in."""
return utils.stdin_get_value().splitlines(True) return utils.stdin_get_lines()
def should_ignore_file(self): def should_ignore_file(self):
# type: () -> bool # type: () -> bool

View file

@ -13,6 +13,7 @@ from typing import Callable, Dict, Generator, List, Optional, Pattern
from typing import Sequence, Set, Tuple, Union from typing import Sequence, Set, Tuple, Union
from flake8 import exceptions from flake8 import exceptions
from flake8._compat import lru_cache
if False: # `typing.TYPE_CHECKING` was introduced in 3.5.2 if False: # `typing.TYPE_CHECKING` was introduced in 3.5.2
from flake8.plugins.manager import Plugin from flake8.plugins.manager import Plugin
@ -189,28 +190,31 @@ def normalize_path(path, parent=os.curdir):
return path.rstrip(separator + alternate_separator) return path.rstrip(separator + alternate_separator)
def _stdin_get_value_py3(): # type: () -> io.StringIO def _stdin_get_value_py3(): # type: () -> str
stdin_value = sys.stdin.buffer.read() stdin_value = sys.stdin.buffer.read()
fd = io.BytesIO(stdin_value) fd = io.BytesIO(stdin_value)
try: try:
(coding, lines) = tokenize.detect_encoding(fd.readline) coding, _ = tokenize.detect_encoding(fd.readline)
return io.StringIO(stdin_value.decode(coding)) return stdin_value.decode(coding)
except (LookupError, SyntaxError, UnicodeError): except (LookupError, SyntaxError, UnicodeError):
return io.StringIO(stdin_value.decode("utf-8")) return stdin_value.decode("utf-8")
def stdin_get_value(): @lru_cache(maxsize=1)
# type: () -> str def stdin_get_value(): # type: () -> str
"""Get and cache it so plugins can use it.""" """Get and cache it so plugins can use it."""
cached_value = getattr(stdin_get_value, "cached_stdin", None) if sys.version_info < (3,):
if cached_value is None: return sys.stdin.read()
if sys.version_info < (3, 0): else:
stdin_value = io.BytesIO(sys.stdin.read()) return _stdin_get_value_py3()
else:
stdin_value = _stdin_get_value_py3()
stdin_get_value.cached_stdin = stdin_value # type: ignore def stdin_get_lines(): # type: () -> List[str]
cached_value = stdin_get_value.cached_stdin # type: ignore """Return lines of stdin split according to file splitting."""
return cached_value.getvalue() if sys.version_info < (3,):
return list(io.BytesIO(stdin_get_value()))
else:
return list(io.StringIO(stdin_get_value()))
def parse_unified_diff(diff=None): def parse_unified_diff(diff=None):

View file

@ -51,6 +51,29 @@ index d64ac39..7d943de 100644
assert err == '' assert err == ''
def test_form_feed_line_split(tmpdir, capsys):
"""Test that form feed is treated the same for stdin."""
src = 'x=1\n\f\ny=1\n'
expected_out = '''\
t.py:1:2: E225 missing whitespace around operator
t.py:3:2: E225 missing whitespace around operator
'''
with tmpdir.as_cwd():
tmpdir.join('t.py').write(src)
with mock.patch.object(utils, 'stdin_get_value', return_value=src):
_call_main(['-', '--stdin-display-name=t.py'], retv=1)
out, err = capsys.readouterr()
assert out == expected_out
assert err == ''
_call_main(['t.py'], retv=1)
out, err = capsys.readouterr()
assert out == expected_out
assert err == ''
def test_e101_indent_char_does_not_reset(tmpdir, capsys): def test_e101_indent_char_does_not_reset(tmpdir, capsys):
"""Ensure that E101 with an existing indent_char does not reset it.""" """Ensure that E101 with an existing indent_char does not reset it."""
t_py_contents = """\ t_py_contents = """\

View file

@ -89,20 +89,15 @@ def test_should_ignore_file_to_handle_disable_noqa(default_options):
@mock.patch('flake8.utils.stdin_get_value') @mock.patch('flake8.utils.stdin_get_value')
def test_read_lines_from_stdin(stdin_get_value, default_options): def test_read_lines_from_stdin(stdin_get_value, default_options):
"""Verify that we use our own utility function to retrieve stdin.""" """Verify that we use our own utility function to retrieve stdin."""
stdin_value = mock.Mock() stdin_get_value.return_value = ''
stdin_value.splitlines.return_value = []
stdin_get_value.return_value = stdin_value
processor.FileProcessor('-', default_options) processor.FileProcessor('-', default_options)
stdin_get_value.assert_called_once_with() stdin_get_value.assert_called_once_with()
stdin_value.splitlines.assert_called_once_with(True)
@mock.patch('flake8.utils.stdin_get_value') @mock.patch('flake8.utils.stdin_get_value')
def test_stdin_filename_attribute(stdin_get_value, default_options): def test_stdin_filename_attribute(stdin_get_value, default_options):
"""Verify that we update the filename attribute.""" """Verify that we update the filename attribute."""
stdin_value = mock.Mock() stdin_get_value.return_value = ''
stdin_value.splitlines.return_value = []
stdin_get_value.return_value = stdin_value
file_processor = processor.FileProcessor('-', default_options) file_processor = processor.FileProcessor('-', default_options)
assert file_processor.filename == 'stdin' assert file_processor.filename == 'stdin'
@ -111,9 +106,7 @@ def test_stdin_filename_attribute(stdin_get_value, default_options):
def test_read_lines_uses_display_name(stdin_get_value, default_options): def test_read_lines_uses_display_name(stdin_get_value, default_options):
"""Verify that when processing stdin we use a display name if present.""" """Verify that when processing stdin we use a display name if present."""
default_options.stdin_display_name = 'display_name.py' default_options.stdin_display_name = 'display_name.py'
stdin_value = mock.Mock() stdin_get_value.return_value = ''
stdin_value.splitlines.return_value = []
stdin_get_value.return_value = stdin_value
file_processor = processor.FileProcessor('-', default_options) file_processor = processor.FileProcessor('-', default_options)
assert file_processor.filename == 'display_name.py' assert file_processor.filename == 'display_name.py'
@ -123,9 +116,7 @@ def test_read_lines_ignores_empty_display_name(
stdin_get_value, default_options, stdin_get_value, default_options,
): ):
"""Verify that when processing stdin we use a display name if present.""" """Verify that when processing stdin we use a display name if present."""
stdin_value = mock.Mock() stdin_get_value.return_value = ''
stdin_value.splitlines.return_value = []
stdin_get_value.return_value = stdin_value
default_options.stdin_display_name = '' default_options.stdin_display_name = ''
file_processor = processor.FileProcessor('-', default_options) file_processor = processor.FileProcessor('-', default_options)
assert file_processor.filename == 'stdin' assert file_processor.filename == 'stdin'