Skip to content

Commit 61e3ea9

Browse files
author
Aleksey Petryankin
committed
Add tests for different configs in different directories
1 parent 182bddd commit 61e3ea9

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

tests/config/test_per_directory_config.py

+141
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
33
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
44

5+
from __future__ import annotations
6+
7+
import os
8+
import os.path
59
from pathlib import Path
610

11+
import pytest
12+
from pytest import CaptureFixture
13+
14+
from pylint.lint import Run as LintRun
715
from pylint.testutils._run import _Run as Run
816

917

@@ -21,3 +29,136 @@ def test_fall_back_on_base_config(tmp_path: Path) -> None:
2129
f.write("1")
2230
Run([str(test_file)], exit=False)
2331
assert id(runner.linter.config) == id(runner.linter._base_config)
32+
33+
34+
@pytest.fixture
35+
def _create_subconfig_test_fs(tmp_path: Path) -> tuple[Path, Path, Path, Path]:
36+
level1_dir = tmp_path / "level1_dir"
37+
level1_init = level1_dir / "__init__.py"
38+
conf_file1 = level1_dir / "pylintrc"
39+
test_file1 = level1_dir / "a.py"
40+
test_file3 = level1_dir / "z.py"
41+
subdir = level1_dir / "sub"
42+
level2_init = subdir / "__init__.py"
43+
conf_file2 = subdir / "pylintrc"
44+
test_file2 = subdir / "b.py"
45+
os.makedirs(subdir)
46+
level1_init.touch()
47+
level2_init.touch()
48+
test_file_text = "#LEVEL1\n#LEVEL2\n#ALL_LEVELS\n#TODO\n"
49+
test_file1.write_text(test_file_text)
50+
test_file2.write_text(test_file_text)
51+
test_file3.write_text(test_file_text)
52+
conf1 = "[MISCELLANEOUS]\nnotes=LEVEL1,ALL_LEVELS"
53+
conf2 = "[MISCELLANEOUS]\nnotes=LEVEL2,ALL_LEVELS"
54+
conf_file1.write_text(conf1)
55+
conf_file2.write_text(conf2)
56+
return level1_dir, test_file1, test_file2, test_file3
57+
58+
59+
# check that use-parent-configs doesn't break anything
60+
@pytest.mark.parametrize(
61+
"local_config_args",
62+
[["--use-local-configs=y"], ["--use-local-configs=y", "--use-parent-configs=y"]],
63+
)
64+
# check files and configs from top-level package or subpackage
65+
@pytest.mark.parametrize("test_file_index", [0, 1, 2])
66+
# check cases when cwd contains pylintrc or not
67+
@pytest.mark.parametrize("start_dir_modificator", [".", ".."])
68+
def test_subconfig_vs_root_config(
69+
_create_subconfig_test_fs: tuple[Path, ...],
70+
capsys: CaptureFixture,
71+
test_file_index: int,
72+
local_config_args: list[str],
73+
start_dir_modificator: str,
74+
) -> None:
75+
"""Test that each checked file or module uses config
76+
from its own directory.
77+
"""
78+
level1_dir, *tmp_files = _create_subconfig_test_fs
79+
test_file = tmp_files[test_file_index]
80+
start_dir = (level1_dir / start_dir_modificator).resolve()
81+
82+
orig_cwd = os.getcwd()
83+
output = [f"{start_dir = }, {test_file = }"]
84+
os.chdir(start_dir)
85+
for _ in range(2):
86+
# _Run adds --rcfile, which overrides config from cwd, so we need original Run here
87+
LintRun([*local_config_args, str(test_file)], exit=False)
88+
output.append(capsys.readouterr().out.replace("\\n", "\n"))
89+
90+
test_file = test_file.parent
91+
os.chdir(orig_cwd)
92+
93+
expected_note = f"LEVEL{(test_file_index%2)+1}"
94+
assert (
95+
expected_note in output[1]
96+
), f"readable debug output:\n{output[0]}\n{output[1]}"
97+
assert (
98+
expected_note in output[2]
99+
), f"readable debug output:\n{output[0]}\n{output[2]}"
100+
101+
if test_file_index == 0:
102+
# 'pylint level1_dir/' should use config from subpackage when checking level1_dir/sub/b.py
103+
assert (
104+
"LEVEL2" in output[2]
105+
), f"readable debug output:\n{output[0]}\n{output[2]}"
106+
if test_file_index == 1:
107+
# 'pylint level1_dir/sub/b.py' and 'pylint level1_dir/sub/' should use
108+
# level1_dir/sub/pylintrc, not level1_dir/pylintrc
109+
assert (
110+
"LEVEL1" not in output[1]
111+
), f"readable debug output:\n{output[0]}\n{output[1]}"
112+
assert (
113+
"LEVEL1" not in output[2]
114+
), f"readable debug output:\n{output[0]}\n{output[2]}"
115+
116+
117+
@pytest.mark.parametrize("test_file_index", [0, 1])
118+
def test_subconfig_vs_cli_arg(
119+
_create_subconfig_test_fs: tuple[Path, ...],
120+
capsys: CaptureFixture,
121+
test_file_index: int,
122+
) -> None:
123+
"""Test that cli args have priority over subconfigs."""
124+
test_root, *tmp_files = _create_subconfig_test_fs
125+
test_file = tmp_files[test_file_index]
126+
orig_cwd = os.getcwd()
127+
os.chdir(test_root)
128+
LintRun(["--notes=FIXME", "--use-local-configs=y", str(test_file)], exit=False)
129+
output = capsys.readouterr().out.replace("\\n", "\n")
130+
os.chdir(orig_cwd)
131+
132+
# check that cli arg overrides default value
133+
assert "TODO" not in output
134+
# notes=FIXME in cli should override all pylintrc configs
135+
assert "ALL_LEVELS" not in output
136+
137+
138+
def _create_parent_subconfig_fs(tmp_path: Path) -> Path:
139+
level1_dir = tmp_path / "package"
140+
conf_file = level1_dir / "pylintrc"
141+
subdir = level1_dir / "sub"
142+
test_file = subdir / "b.py"
143+
os.makedirs(subdir)
144+
test_file_text = "#LEVEL1\n#LEVEL2\n#TODO\n"
145+
test_file.write_text(test_file_text)
146+
conf = "[MISCELLANEOUS]\nnotes=LEVEL1,LEVEL2"
147+
conf_file.write_text(conf)
148+
return test_file
149+
150+
151+
def test_subconfig_in_parent(tmp_path: Path, capsys: CaptureFixture) -> None:
152+
"""Test that searching local configs in parent directories works."""
153+
test_file = _create_parent_subconfig_fs(tmp_path)
154+
orig_cwd = os.getcwd()
155+
os.chdir(tmp_path)
156+
LintRun(
157+
["--use-parent-configs=y", "--use-local-configs=y", str(test_file)], exit=False
158+
)
159+
output1 = capsys.readouterr().out.replace("\\n", "\n")
160+
os.chdir(orig_cwd)
161+
162+
# check that file is linted with config from ../, which is not a cwd
163+
assert "TODO" not in output1
164+
assert "LEVEL1" in output1

0 commit comments

Comments
 (0)