Skip to content

Commit 31aca81

Browse files
Fixes duplicate-code check with ignore-imports (#9147) (#9176)
(cherry picked from commit 67f20bd) Co-authored-by: theirix <[email protected]>
1 parent 792da24 commit 31aca81

File tree

7 files changed

+42
-16
lines changed

7 files changed

+42
-16
lines changed

doc/whatsnew/fragments/8914.bugfix

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixes ignoring conditional imports with ``ignore-imports=y``.
2+
3+
Closes #8914

pylint/checkers/similar.py

+6-15
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from collections.abc import Callable, Generator, Iterable, Sequence
4242
from getopt import getopt
4343
from io import BufferedIOBase, BufferedReader, BytesIO
44-
from itertools import chain, groupby
44+
from itertools import chain
4545
from typing import (
4646
TYPE_CHECKING,
4747
Any,
@@ -598,17 +598,10 @@ def stripped_lines(
598598
if ignore_imports or ignore_signatures:
599599
tree = astroid.parse("".join(lines))
600600
if ignore_imports:
601-
node_is_import_by_lineno = (
602-
(node.lineno, isinstance(node, (nodes.Import, nodes.ImportFrom)))
603-
for node in tree.body
604-
)
605-
line_begins_import = {
606-
lineno: all(is_import for _, is_import in node_is_import_group)
607-
for lineno, node_is_import_group in groupby(
608-
node_is_import_by_lineno, key=lambda x: x[0]
609-
)
610-
}
611-
current_line_is_import = False
601+
import_lines = {}
602+
for node in tree.nodes_of_class((nodes.Import, nodes.ImportFrom)):
603+
for lineno in range(node.lineno, (node.end_lineno or node.lineno) + 1):
604+
import_lines[lineno] = True
612605
if ignore_signatures:
613606

614607
def _get_functions(
@@ -664,9 +657,7 @@ def _get_functions(
664657
docstring = None
665658
line = ""
666659
if ignore_imports:
667-
current_line_is_import = line_begins_import.get(
668-
lineno, current_line_is_import
669-
)
660+
current_line_is_import = import_lines.get(lineno, False)
670661
if current_line_is_import:
671662
line = ""
672663
if ignore_comments:

tests/checkers/unittest_similar.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pytest
1010

1111
from pylint.checkers import similar
12+
from pylint.constants import IS_PYPY, PY39_PLUS
1213
from pylint.lint import PyLinter
1314
from pylint.testutils import GenericTestReporter as Reporter
1415

@@ -130,6 +131,10 @@ def test_multiline_imports() -> None:
130131
)
131132

132133

134+
@pytest.mark.skipif(
135+
IS_PYPY and not PY39_PLUS,
136+
reason="Requires accurate 'end_lineno' value",
137+
)
133138
def test_ignore_multiline_imports() -> None:
134139
output = StringIO()
135140
with redirect_stdout(output), pytest.raises(SystemExit) as ex:
@@ -295,7 +300,7 @@ def test_no_hide_code_with_imports() -> None:
295300
with redirect_stdout(output), pytest.raises(SystemExit) as ex:
296301
similar.Run(["--ignore-imports"] + 2 * [HIDE_CODE_WITH_IMPORTS])
297302
assert ex.value.code == 0
298-
assert "TOTAL lines=32 duplicates=16 percent=50.00" in output.getvalue()
303+
assert "TOTAL lines=32 duplicates=0 percent=0.00" in output.getvalue()
299304

300305

301306
def test_ignore_nothing() -> None:

tests/regrtest_data/duplicate_code/ignore_conditional_imports/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import typing
2+
3+
x = 1
4+
if typing.TYPE_CHECKING:
5+
import os
6+
import sys
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import typing
2+
3+
x = 1
4+
if typing.TYPE_CHECKING:
5+
import os
6+
import sys

tests/test_similar.py

+15
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,18 @@ def test_useless_suppression() -> None:
264264
exit=False,
265265
)
266266
assert not runner.linter.stats.by_msg
267+
268+
def test_conditional_imports(self) -> None:
269+
"""Tests enabling ignore-imports with conditional imports works correctly."""
270+
path = join(DATA, "ignore_conditional_imports")
271+
expected_output = "==ignore_conditional_imports.file_one:[2:4]"
272+
self._test_output(
273+
[
274+
path,
275+
"-e=duplicate-code",
276+
"-d=unused-import,C",
277+
"--ignore-imports=y",
278+
"--min-similarity-lines=1",
279+
],
280+
expected_output=expected_output,
281+
)

0 commit comments

Comments
 (0)