summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.pre-commit-config.yaml2
-rw-r--r--src/flake8/checker.py17
-rw-r--r--tests/integration/test_main.py31
3 files changed, 46 insertions, 4 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b03ff3c..e1b34f3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,6 +2,8 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
+ - id: debug-statements
+ exclude: ^tests/fixtures/example-code/invalid-syntax.py$
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: ^tests/fixtures/diffs/
diff --git a/src/flake8/checker.py b/src/flake8/checker.py
index ea8b5d3..be1c7f7 100644
--- a/src/flake8/checker.py
+++ b/src/flake8/checker.py
@@ -564,9 +564,10 @@ class FileChecker(object):
parens = 0
statistics = self.statistics
file_processor = self.processor
+ prev_physical = ""
for token in file_processor.generate_tokens():
statistics["tokens"] += 1
- self.check_physical_eol(token)
+ self.check_physical_eol(token, prev_physical)
token_type, text = token[0:2]
processor.log_token(LOG, token)
if token_type == tokenize.OP:
@@ -574,6 +575,7 @@ class FileChecker(object):
elif parens == 0:
if processor.token_is_newline(token):
self.handle_newline(token_type)
+ prev_physical = token[4]
if file_processor.tokens:
# If any tokens are left over, process them
@@ -609,11 +611,18 @@ class FileChecker(object):
else:
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."""
+ # a newline token ends a single physical line.
if processor.is_eol_token(token):
- # Obviously, a newline token ends a single physical line.
- self.run_physical_checks(token[4])
+ # if the file does not end with a newline, the NEWLINE
+ # 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):
# Less obviously, a string that contains newlines is a
# multiline string, either triple-quoted or with internal
diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py
index ce8ad13..69cb12b 100644
--- a/tests/integration/test_main.py
+++ b/tests/integration/test_main.py
@@ -212,6 +212,37 @@ x = """
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):
"""Test that arguments are obtained from 'sys.argv'."""
with mock.patch('sys.argv', ['flake8', '--help']):