diff --git a/CHANGELOG.md b/CHANGELOG.md index b4fbaf01c..dee41ba2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Fixed issue where CFG edges from loop body to loop condition block was ignored during augmenting edge z3 constraints - Fixed issue in `one-iteration-checker` where the message was not correctly reported for `while` loops when `z3` option is on - Fixed crash when z3-solver is not installed +- Fixed crash when an inline comment had no spaces after the `#` ### 🔧 Internal changes diff --git a/examples/custom_checkers/e9989_pycodestyle/e262_error.py b/examples/custom_checkers/e9989_pycodestyle/e262_error.py index ee83980e8..ef50be99a 100644 --- a/examples/custom_checkers/e9989_pycodestyle/e262_error.py +++ b/examples/custom_checkers/e9989_pycodestyle/e262_error.py @@ -1 +1,2 @@ a = 1 # this is a comment +b = 1 #this is a comment with no leading space diff --git a/python_ta/reporters/node_printers.py b/python_ta/reporters/node_printers.py index 26baf60c2..be3079830 100644 --- a/python_ta/reporters/node_printers.py +++ b/python_ta/reporters/node_printers.py @@ -440,11 +440,11 @@ def render_pep8_errors_e262(msg, _node, source_lines=None): res = re.search(r"column (\d+)", msg.msg) col = int(res.group().split()[-1]) - keyword = source_lines[line - 1][col:].split()[1] - keyword_idx = source_lines[line - 1][col:].index(keyword) + col + source_line = source_lines[line - 1] + keyword_idx = len(source_line) - len(source_line[col:].lstrip("# \t")) yield from render_context(line - 2, line, source_lines) - yield (line, slice(col, keyword_idx), LineType.ERROR, source_lines[line - 1]) + yield (line, slice(col, keyword_idx), LineType.ERROR, source_line) yield from render_context(line + 1, line + 3, source_lines) diff --git a/tests/test_custom_checkers/test_pycodestyle_checker.py b/tests/test_custom_checkers/test_pycodestyle_checker.py index 4ed2bdfca..2cec02092 100644 --- a/tests/test_custom_checkers/test_pycodestyle_checker.py +++ b/tests/test_custom_checkers/test_pycodestyle_checker.py @@ -12,27 +12,33 @@ # Define parameter sets for different error and no-error tests error_params = [ - ("E115", 2, 0, "expected an indented block (comment)"), - ("E122", 2, 0, "continuation line missing indentation or outdented"), - ("E123", 3, 4, "closing bracket does not match indentation of opening bracket's line"), - ("E125", 2, 4, "continuation line with same indent as next logical line"), - ("E127", 2, 19, "continuation line over-indented for visual indent"), - ("E129", 4, 4, "visually indented line with same indent as next logical line"), - ("E131", 4, 8, "continuation line unaligned for hanging indent"), - ("E203", 1, 30, "whitespace before ':'"), - ("E222", 1, 3, "multiple spaces after operator"), - ("E223", 1, 1, "tab before operator"), - ("E224", 1, 3, "tab after operator"), - ("E226", 1, 5, "missing whitespace around arithmetic operator"), - ("E227", 1, 5, "missing whitespace around bitwise or shift operator"), - ("E228", 1, 5, "missing whitespace around modulo operator"), - ("E262", 1, 7, "inline comment should start with '# '"), - ("E265", 1, 0, "block comment should start with '# '"), - ("E266", 1, 0, "too many leading '#' for block comment"), - ("E275", 1, 16, "missing whitespace after keyword"), - ("E301", 5, 4, "expected 1 blank line, found 0"), - ("E303", 6, 0, "too many blank lines (3)"), - ("E304", 12, 0, "blank lines found after function decorator"), + ("E115", [(2, 0, "expected an indented block (comment)")]), + ("E122", [(2, 0, "continuation line missing indentation or outdented")]), + ("E123", [(3, 4, "closing bracket does not match indentation of opening bracket's line")]), + ("E125", [(2, 4, "continuation line with same indent as next logical line")]), + ("E127", [(2, 19, "continuation line over-indented for visual indent")]), + ("E129", [(4, 4, "visually indented line with same indent as next logical line")]), + ("E131", [(4, 8, "continuation line unaligned for hanging indent")]), + ("E203", [(1, 30, "whitespace before ':'")]), + ("E222", [(1, 3, "multiple spaces after operator")]), + ("E223", [(1, 1, "tab before operator")]), + ("E224", [(1, 3, "tab after operator")]), + ("E226", [(1, 5, "missing whitespace around arithmetic operator")]), + ("E227", [(1, 5, "missing whitespace around bitwise or shift operator")]), + ("E228", [(1, 5, "missing whitespace around modulo operator")]), + ( + "E262", + [ + (1, 7, "inline comment should start with '# '"), + (2, 7, "inline comment should start with '# '"), + ], + ), + ("E265", [(1, 0, "block comment should start with '# '")]), + ("E266", [(1, 0, "too many leading '#' for block comment")]), + ("E275", [(1, 16, "missing whitespace after keyword")]), + ("E301", [(5, 4, "expected 1 blank line, found 0")]), + ("E303", [(6, 0, "too many blank lines (3)")]), + ("E304", [(12, 0, "blank lines found after function decorator")]), ] @@ -40,16 +46,19 @@ class TestPycodestyleChecker(pylint.testutils.CheckerTestCase): CHECKER_CLASS = PycodestyleChecker CONFIG = {"pycodestyle_ignore": ["E24"]} - @pytest.mark.parametrize("msg_id, line, col, desc", error_params) - def test_error_cases(self, msg_id, line, col, desc): + @pytest.mark.parametrize("msg_id, args", error_params) + def test_error_cases(self, msg_id, args): """Parameterized test that confirms various PEP8 errors are triggered""" mod = MANAGER.ast_from_file(os.path.join(DIR_PATH, msg_id.lower() + "_error.py")) with self.assertAddsMessages( - pylint.testutils.MessageTest( - msg_id="pep8-errors", - line=line, - args=(msg_id, f"line {line}, column {col}: {desc}"), - ), + *[ + pylint.testutils.MessageTest( + msg_id="pep8-errors", + line=line, + args=(msg_id, f"line {line}, column {col}: {desc}"), + ) + for line, col, desc in args + ], ignore_position=True, ): self.checker.process_module(mod)