fix skipping of physical checks when file does not end in newline

This commit is contained in:
Anthony Sottile 2020-09-12 11:56:37 -07:00
parent 2c64d3ec5a
commit ee9c2874a9
3 changed files with 46 additions and 4 deletions

View file

@ -2,6 +2,8 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0 rev: v2.3.0
hooks: hooks:
- id: debug-statements
exclude: ^tests/fixtures/example-code/invalid-syntax.py$
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
exclude: ^tests/fixtures/diffs/ exclude: ^tests/fixtures/diffs/

View file

@ -564,9 +564,10 @@ class FileChecker(object):
parens = 0 parens = 0
statistics = self.statistics statistics = self.statistics
file_processor = self.processor file_processor = self.processor
prev_physical = ""
for token in file_processor.generate_tokens(): for token in file_processor.generate_tokens():
statistics["tokens"] += 1 statistics["tokens"] += 1
self.check_physical_eol(token) self.check_physical_eol(token, prev_physical)
token_type, text = token[0:2] token_type, text = token[0:2]
processor.log_token(LOG, token) processor.log_token(LOG, token)
if token_type == tokenize.OP: if token_type == tokenize.OP:
@ -574,6 +575,7 @@ class FileChecker(object):
elif parens == 0: elif parens == 0:
if processor.token_is_newline(token): if processor.token_is_newline(token):
self.handle_newline(token_type) self.handle_newline(token_type)
prev_physical = token[4]
if file_processor.tokens: if file_processor.tokens:
# If any tokens are left over, process them # If any tokens are left over, process them
@ -609,11 +611,18 @@ class FileChecker(object):
else: else:
self.run_logical_checks() self.run_logical_checks()
def check_physical_eol(self, token): def check_physical_eol(self, token, prev_physical):
# type: (processor._Token, str) -> None
"""Run physical checks if and only if it is at the end of the line.""" """Run physical checks if and only if it is at the end of the line."""
# a newline token ends a single physical line.
if processor.is_eol_token(token): if processor.is_eol_token(token):
# Obviously, a newline token ends a single physical line. # if the file does not end with a newline, the NEWLINE
self.run_physical_checks(token[4]) # token is inserted by the parser, but it does not contain
# the previous physical line in `token[4]`
if token[4] == "":
self.run_physical_checks(prev_physical)
else:
self.run_physical_checks(token[4])
elif processor.is_multiline_string(token): elif processor.is_multiline_string(token):
# Less obviously, a string that contains newlines is a # Less obviously, a string that contains newlines is a
# multiline string, either triple-quoted or with internal # multiline string, either triple-quoted or with internal

View file

@ -212,6 +212,37 @@ x = """
assert out == err == '' assert out == err == ''
def test_physical_line_file_not_ending_in_newline(tmpdir, capsys):
"""See https://github.com/PyCQA/pycodestyle/issues/960."""
t_py_src = 'def f():\n\tpass'
with tmpdir.as_cwd():
tmpdir.join('t.py').write(t_py_src)
_call_main(['t.py'], retv=1)
out, err = capsys.readouterr()
assert out == '''\
t.py:2:1: W191 indentation contains tabs
t.py:2:6: W292 no newline at end of file
'''
@pytest.mark.xfail(strict=True) # currently awaiting fix in pycodestyle
def test_physical_line_file_not_ending_in_newline_trailing_ws(tmpdir, capsys):
"""See https://github.com/PyCQA/pycodestyle/issues/960."""
t_py_src = 'x = 1 '
with tmpdir.as_cwd():
tmpdir.join('t.py').write(t_py_src)
_call_main(['t.py'], retv=1)
out, err = capsys.readouterr()
assert out == '''\
t.py:1:6: W291 trailing whitespace
t.py:1:10: W292 no newline at end of file
'''
def test_obtaining_args_from_sys_argv_when_not_explicity_provided(capsys): def test_obtaining_args_from_sys_argv_when_not_explicity_provided(capsys):
"""Test that arguments are obtained from 'sys.argv'.""" """Test that arguments are obtained from 'sys.argv'."""
with mock.patch('sys.argv', ['flake8', '--help']): with mock.patch('sys.argv', ['flake8', '--help']):