diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2022-04-19 11:21:02 -0400 |
---|---|---|
committer | Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> | 2022-04-20 09:29:18 +0200 |
commit | 664049cef8aadbc2ff531d71b04eee61abe0d8ea (patch) | |
tree | d0635cf33ee6075e85c5f9b9695cb5dd87b5a19f | |
parent | cca0d02a369d02451e19312e3c53aa3445ab4633 (diff) | |
download | pylint-git-664049cef8aadbc2ff531d71b04eee61abe0d8ea.tar.gz |
Fix `AstroidError` in similarity checker with imports/signatures ignored (#6357)
Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | doc/whatsnew/2.13.rst | 5 | ||||
-rw-r--r-- | pylint/checkers/similar.py | 52 | ||||
-rw-r--r-- | tests/test_similar.py | 12 |
4 files changed, 52 insertions, 23 deletions
@@ -26,6 +26,12 @@ Release date: TBA Closes #5815 Closes #5406 +* Fixed an ``AstroidError`` in 2.13.0 raised by the ``duplicate-code`` checker with + ``ignore-imports`` or ``ignore-signatures`` enabled. + + Closes #6301 + + What's New in Pylint 2.13.5? ============================ Release date: 2022-04-06 diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index 3479baf6f..ce92017b5 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -205,6 +205,11 @@ Other Changes Closes #5815 Closes #5406 +* Fixed an ``AstroidError`` in 2.13.0 raised by the ```duplicate-code``` checker with + ``ignore-imports`` or ``ignore-signatures`` enabled. + + Closes #6301 + * Use the ``tomli`` package instead of ``toml`` to parse ``.toml`` files. Closes #5885 diff --git a/pylint/checkers/similar.py b/pylint/checkers/similar.py index 69b401fa4..e85bac558 100644 --- a/pylint/checkers/similar.py +++ b/pylint/checkers/similar.py @@ -30,6 +30,7 @@ from itertools import chain, groupby from typing import ( TYPE_CHECKING, Any, + Callable, Dict, FrozenSet, Generator, @@ -359,28 +360,25 @@ class Similar: readlines = decoding_stream(stream, encoding).readlines else: readlines = stream.readlines # type: ignore[assignment] # hint parameter is incorrectly typed as non-optional + try: - active_lines: List[str] = [] - if hasattr(self, "linter"): - # Remove those lines that should be ignored because of disables - for index, line in enumerate(readlines()): - if self.linter._is_one_message_enabled("R0801", index + 1): # type: ignore[attr-defined] - active_lines.append(line) - else: - active_lines = readlines() - - self.linesets.append( - LineSet( - streamid, - active_lines, - self.ignore_comments, - self.ignore_docstrings, - self.ignore_imports, - self.ignore_signatures, - ) - ) + lines = readlines() except UnicodeDecodeError: - pass + lines = [] + + self.linesets.append( + LineSet( + streamid, + lines, + self.ignore_comments, + self.ignore_docstrings, + self.ignore_imports, + self.ignore_signatures, + line_enabled_callback=self.linter._is_one_message_enabled # type: ignore[attr-defined] + if hasattr(self, "linter") + else None, + ) + ) def run(self) -> None: """Start looking for similarities and display results on stdout.""" @@ -552,6 +550,7 @@ def stripped_lines( ignore_docstrings: bool, ignore_imports: bool, ignore_signatures: bool, + line_enabled_callback: Union[Callable[[str, int], bool], None] = None, ) -> List[LineSpecifs]: """Return tuples of line/line number/line type with leading/trailing whitespace and any ignored code features removed. @@ -560,6 +559,7 @@ def stripped_lines( :param ignore_docstrings: if true, any line that is a docstring is removed from the result :param ignore_imports: if true, any line that is an import is removed from the result :param ignore_signatures: if true, any line that is part of a function signature is removed from the result + :param line_enabled_callback: If called with "R0801" and a line number, a return value of False will disregard the line :return: the collection of line/line number/line type tuples """ if ignore_imports or ignore_signatures: @@ -611,6 +611,10 @@ def stripped_lines( strippedlines = [] docstring = None for lineno, line in enumerate(lines, start=1): + if line_enabled_callback is not None and not line_enabled_callback( + "R0801", lineno + ): + continue line = line.strip() if ignore_docstrings: if not docstring: @@ -657,11 +661,17 @@ class LineSet: ignore_docstrings: bool = False, ignore_imports: bool = False, ignore_signatures: bool = False, + line_enabled_callback: Union[Callable[[str, int], bool], None] = None, ) -> None: self.name = name self._real_lines = lines self._stripped_lines = stripped_lines( - lines, ignore_comments, ignore_docstrings, ignore_imports, ignore_signatures + lines, + ignore_comments, + ignore_docstrings, + ignore_imports, + ignore_signatures, + line_enabled_callback=line_enabled_callback, ) def __str__(self): diff --git a/tests/test_similar.py b/tests/test_similar.py index f595102bc..06c50fa62 100644 --- a/tests/test_similar.py +++ b/tests/test_similar.py @@ -44,7 +44,13 @@ class TestSimilarCodeChecker: @staticmethod def _run_pylint(args: List[str], out: TextIO) -> int: """Runs pylint with a patched output.""" - args = args + ["--persistent=no"] + args = args + [ + "--persistent=no", + "--enable=astroid-error", + # Enable functionality that will build another ast + "--ignore-imports=y", + "--ignore-signatures=y", + ] with _patch_streams(out): with pytest.raises(SystemExit) as cm: with warnings.catch_warnings(): @@ -63,8 +69,10 @@ class TestSimilarCodeChecker: out = StringIO() self._run_pylint(args, out=out) actual_output = self._clean_paths(out.getvalue()) + actual_output_stripped = actual_output.strip() expected_output = self._clean_paths(expected_output) - assert expected_output.strip() in actual_output.strip() + assert expected_output.strip() in actual_output_stripped + assert "Fatal error" not in actual_output_stripped def test_duplicate_code_raw_strings_all(self) -> None: """Test similar lines in 3 similar files.""" |