Skip to content

Commit

Permalink
Merge pull request #1374 from PyCQA/bug/1372
Browse files Browse the repository at this point in the history
Handle new SyntaxError tuple on 3.10
  • Loading branch information
asottile authored Aug 15, 2021
2 parents d25cc10 + 85c2be3 commit 281f3f8
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/flake8/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,26 @@ def _extract_syntax_information(exception: Exception) -> Tuple[int, int]:
token = ()
row, column = (1, 0)

if column > 0 and token and isinstance(exception, SyntaxError):
if (
column > 0
and token
and isinstance(exception, SyntaxError)
and len(token) == 4 # Python 3.9 or earlier
):
# NOTE(sigmavirus24): SyntaxErrors report 1-indexed column
# numbers. We need to decrement the column number by 1 at
# least.
column_offset = 1
row_offset = 0
# See also: https://github.com/pycqa/flake8/issues/169
physical_line = token[-1]
# See also: https://github.com/pycqa/flake8/issues/169,
# https://github.com/PyCQA/flake8/issues/1372
# On Python 3.9 and earlier, token will be a 4-item tuple with the
# last item being the string. Starting with 3.10, they added to
# the tuple so now instead of it ending with the code that failed
# to parse, it ends with the end of the section of code that
# failed to parse. Luckily the absolute position in the tuple is
# stable across versions so we can use that here
physical_line = token[3]

# NOTE(sigmavirus24): Not all "tokens" have a string as the last
# argument. In this event, let's skip trying to find the correct
Expand Down
24 changes: 24 additions & 0 deletions tests/integration/test_checker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Integration tests for the checker submodule."""
import sys
from unittest import mock

import pytest
Expand Down Expand Up @@ -336,3 +337,26 @@ def test_acquire_when_multiprocessing_pool_can_not_initialize():

pool.assert_called_once_with(2, checker._pool_init)
assert result is None


def test_handling_syntaxerrors_across_pythons():
"""Verify we properly handle exception argument tuples.
Python 3.10 added more information to the SyntaxError parse token tuple.
We need to handle that correctly to avoid crashing.
https://github.com/PyCQA/flake8/issues/1372
"""
if sys.version_info < (3, 10): # pragma: no cover (<3.10)
# Python 3.9 or older
err = SyntaxError(
"invalid syntax", ("<unknown>", 2, 5, "bad python:\n")
)
expected = (2, 4)
else: # pragma: no cover (3.10+)
err = SyntaxError(
"invalid syntax", ("<unknown>", 2, 1, "bad python:\n", 2, 11)
)
expected = (2, 1)
file_checker = checker.FileChecker("-", {}, mock.MagicMock())
actual = file_checker._extract_syntax_information(err)
assert actual == expected

0 comments on commit 281f3f8

Please sign in to comment.