Skip to content

Commit 9c2fe99

Browse files
matusvaloPierre-SassoulasDanielNoord
committed
Respect ignore configuration options when --recursive=y. (#6528)
* Ignore specified files/directories in recursive mode Co-authored-by: Pierre Sassoulas <[email protected]> Co-authored-by: Daniël van Noord <[email protected]>
1 parent 33f3fcf commit 9c2fe99

File tree

6 files changed

+181
-10
lines changed

6 files changed

+181
-10
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ What's New in Pylint 2.13.9?
2121
Release date: TBA
2222

2323

24+
* Respect ignore configuration options with ``--recursive=y``.
25+
26+
Closes #6471
27+
2428
* Fix false positives for ``no-name-in-module`` and ``import-error`` for ``numpy.distutils`` and ``pydantic``.
2529

2630
Closes #6497

pylint/lint/expand_modules.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ def _is_in_ignore_list_re(element: str, ignore_list_re: List[Pattern]) -> bool:
4343
return any(file_pattern.match(element) for file_pattern in ignore_list_re)
4444

4545

46+
def _is_ignored_file(
47+
element: str,
48+
ignore_list: list[str],
49+
ignore_list_re: list[Pattern[str]],
50+
ignore_list_paths_re: list[Pattern[str]],
51+
) -> bool:
52+
basename = os.path.basename(element)
53+
return (
54+
basename in ignore_list
55+
or _is_in_ignore_list_re(basename, ignore_list_re)
56+
or _is_in_ignore_list_re(element, ignore_list_paths_re)
57+
)
58+
59+
4660
def expand_modules(
4761
files_or_modules: List[str],
4862
ignore_list: List[str],
@@ -58,10 +72,8 @@ def expand_modules(
5872

5973
for something in files_or_modules:
6074
basename = os.path.basename(something)
61-
if (
62-
basename in ignore_list
63-
or _is_in_ignore_list_re(os.path.basename(something), ignore_list_re)
64-
or _is_in_ignore_list_re(something, ignore_list_paths_re)
75+
if _is_ignored_file(
76+
something, ignore_list, ignore_list_re, ignore_list_paths_re
6577
):
6678
continue
6779
module_path = get_python_path(something)

pylint/lint/pylinter.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
MSG_TYPES_LONG,
4141
MSG_TYPES_STATUS,
4242
)
43-
from pylint.lint.expand_modules import expand_modules
43+
from pylint.lint.expand_modules import _is_ignored_file, expand_modules
4444
from pylint.lint.parallel import check_parallel
4545
from pylint.lint.report_functions import (
4646
report_messages_by_module_stats,
@@ -1013,9 +1013,8 @@ def initialize(self):
10131013
if not msg.may_be_emitted():
10141014
self._msgs_state[msg.msgid] = False
10151015

1016-
@staticmethod
1017-
def _discover_files(files_or_modules: Sequence[str]) -> Iterator[str]:
1018-
"""Discover python modules and packages in subdirectory.
1016+
def _discover_files(self, files_or_modules: Sequence[str]) -> Iterator[str]:
1017+
"""Discover python modules and packages in sub-directory.
10191018
10201019
Returns iterator of paths to discovered modules and packages.
10211020
"""
@@ -1028,6 +1027,16 @@ def _discover_files(files_or_modules: Sequence[str]) -> Iterator[str]:
10281027
if any(root.startswith(s) for s in skip_subtrees):
10291028
# Skip subtree of already discovered package.
10301029
continue
1030+
1031+
if _is_ignored_file(
1032+
root,
1033+
self.config.ignore,
1034+
self.config.ignore_patterns,
1035+
self.config.ignore_paths,
1036+
):
1037+
skip_subtrees.append(root)
1038+
continue
1039+
10311040
if "__init__.py" in files:
10321041
skip_subtrees.append(root)
10331042
yield root

tests/lint/unittest_lint.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from io import StringIO
1414
from os import chdir, getcwd
1515
from os.path import abspath, basename, dirname, isdir, join, sep
16+
from pathlib import Path
1617
from shutil import rmtree
1718
from typing import Iterable, Iterator, List, Optional, Tuple
1819

@@ -29,7 +30,13 @@
2930
OLD_DEFAULT_PYLINT_HOME,
3031
)
3132
from pylint.exceptions import InvalidMessageError
32-
from pylint.lint import ArgumentPreprocessingError, PyLinter, Run, preprocess_options
33+
from pylint.lint import (
34+
ArgumentPreprocessingError,
35+
PyLinter,
36+
Run,
37+
fix_import_path,
38+
preprocess_options,
39+
)
3340
from pylint.message import Message
3441
from pylint.reporters import text
3542
from pylint.typing import MessageLocationTuple
@@ -868,3 +875,67 @@ def test_by_module_statement_value(initialized_linter: PyLinter) -> None:
868875
# Check that the by_module "statement" is equal to the global "statement"
869876
# computed for that module
870877
assert module_stats["statement"] == linter2.stats.statement
878+
879+
880+
@pytest.mark.parametrize(
881+
"ignore_parameter,ignore_parameter_value",
882+
[
883+
("--ignore", "failing.py"),
884+
("--ignore", "ignored_subdirectory"),
885+
("--ignore-patterns", "failing.*"),
886+
("--ignore-patterns", "ignored_*"),
887+
("--ignore-paths", ".*directory/ignored.*"),
888+
("--ignore-paths", ".*ignored.*/failing.*"),
889+
],
890+
)
891+
def test_recursive_ignore(ignore_parameter, ignore_parameter_value) -> None:
892+
run = Run(
893+
[
894+
"--recursive",
895+
"y",
896+
ignore_parameter,
897+
ignore_parameter_value,
898+
join(REGRTEST_DATA_DIR, "directory"),
899+
],
900+
exit=False,
901+
)
902+
903+
linted_files = run.linter._iterate_file_descrs(
904+
tuple(run.linter._discover_files([join(REGRTEST_DATA_DIR, "directory")]))
905+
)
906+
linted_file_paths = [file_item.filepath for file_item in linted_files]
907+
908+
ignored_file = os.path.abspath(
909+
join(REGRTEST_DATA_DIR, "directory", "ignored_subdirectory", "failing.py")
910+
)
911+
assert ignored_file not in linted_file_paths
912+
913+
for regrtest_data_module in (
914+
("directory", "subdirectory", "subsubdirectory", "module.py"),
915+
("directory", "subdirectory", "module.py"),
916+
("directory", "package", "module.py"),
917+
("directory", "package", "subpackage", "module.py"),
918+
):
919+
module = os.path.abspath(join(REGRTEST_DATA_DIR, *regrtest_data_module))
920+
assert module in linted_file_paths
921+
922+
923+
def test_import_sibling_module_from_namespace(initialized_linter: PyLinter) -> None:
924+
"""If the parent directory above `namespace` is on sys.path, ensure that
925+
modules under `namespace` can import each other without raising `import-error`."""
926+
linter = initialized_linter
927+
with tempdir() as tmpdir:
928+
create_files(["namespace/submodule1.py", "namespace/submodule2.py"])
929+
second_path = Path("namespace/submodule2.py")
930+
with open(second_path, "w", encoding="utf-8") as f:
931+
f.write(
932+
"""\"\"\"This module imports submodule1.\"\"\"
933+
import submodule1
934+
print(submodule1)
935+
"""
936+
)
937+
os.chdir("namespace")
938+
# Add the parent directory to sys.path
939+
with fix_import_path([tmpdir]):
940+
linter.check(["submodule2.py"])
941+
assert not linter.stats.by_msg
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import re

tests/test_self.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1276,17 +1276,91 @@ def test_max_inferred_for_complicated_class_hierarchy() -> None:
12761276
assert not ex.value.code % 2
12771277

12781278
def test_regression_recursive(self):
1279+
"""Tests if error is raised when linter is executed over directory not using --recursive=y"""
12791280
self._test_output(
12801281
[join(HERE, "regrtest_data", "directory", "subdirectory"), "--recursive=n"],
12811282
expected_output="No such file or directory",
12821283
)
12831284

12841285
def test_recursive(self):
1286+
"""Tests if running linter over directory using --recursive=y"""
12851287
self._runtest(
12861288
[join(HERE, "regrtest_data", "directory", "subdirectory"), "--recursive=y"],
12871289
code=0,
12881290
)
12891291

1292+
def test_ignore_recursive(self):
1293+
"""Tests recursive run of linter ignoring directory using --ignore parameter.
1294+
1295+
Ignored directory contains files yielding lint errors. If directory is not ignored
1296+
test would fail due these errors.
1297+
"""
1298+
self._runtest(
1299+
[
1300+
join(HERE, "regrtest_data", "directory"),
1301+
"--recursive=y",
1302+
"--ignore=ignored_subdirectory",
1303+
],
1304+
code=0,
1305+
)
1306+
1307+
self._runtest(
1308+
[
1309+
join(HERE, "regrtest_data", "directory"),
1310+
"--recursive=y",
1311+
"--ignore=failing.py",
1312+
],
1313+
code=0,
1314+
)
1315+
1316+
def test_ignore_pattern_recursive(self):
1317+
"""Tests recursive run of linter ignoring directory using --ignore-parameter parameter.
1318+
1319+
Ignored directory contains files yielding lint errors. If directory is not ignored
1320+
test would fail due these errors.
1321+
"""
1322+
self._runtest(
1323+
[
1324+
join(HERE, "regrtest_data", "directory"),
1325+
"--recursive=y",
1326+
"--ignore-pattern=ignored_.*",
1327+
],
1328+
code=0,
1329+
)
1330+
1331+
self._runtest(
1332+
[
1333+
join(HERE, "regrtest_data", "directory"),
1334+
"--recursive=y",
1335+
"--ignore-pattern=failing.*",
1336+
],
1337+
code=0,
1338+
)
1339+
1340+
def test_ignore_path_recursive(self):
1341+
"""Tests recursive run of linter ignoring directory using --ignore-path parameter.
1342+
1343+
Ignored directory contains files yielding lint errors. If directory is not ignored
1344+
test would fail due these errors.
1345+
"""
1346+
self._runtest(
1347+
[
1348+
join(HERE, "regrtest_data", "directory"),
1349+
"--recursive=y",
1350+
"--ignore-path=.*ignored.*",
1351+
],
1352+
code=0,
1353+
)
1354+
1355+
self._runtest(
1356+
[
1357+
join(HERE, "regrtest_data", "directory"),
1358+
"--recursive=y",
1359+
"--ignore-path=.*failing.*",
1360+
],
1361+
code=0,
1362+
)
1363+
12901364
def test_recursive_current_dir(self):
12911365
with _test_sys_path():
12921366
# pytest is including directory HERE/regrtest_data to sys.path which causes
@@ -1297,7 +1371,7 @@ def test_recursive_current_dir(self):
12971371
if not os.path.basename(path) == "regrtest_data"
12981372
]
12991373
with _test_cwd():
1300-
os.chdir(join(HERE, "regrtest_data", "directory"))
1374+
os.chdir(join(HERE, "regrtest_data", "directory", "subdirectory"))
13011375
self._runtest(
13021376
[".", "--recursive=y"],
13031377
code=0,

0 commit comments

Comments
 (0)