Skip to content

Commit 6eab536

Browse files
committed
refactor: move warning info into Config
Doing so, Terminal does not need to know anything about the configuration files.
1 parent 5ff1af4 commit 6eab536

File tree

5 files changed

+64
-25
lines changed

5 files changed

+64
-25
lines changed

src/_pytest/config/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,14 @@ def inipath(self) -> pathlib.Path | None:
11071107
"""
11081108
return self._inipath
11091109

1110+
@property
1111+
def should_warn(self) -> bool:
1112+
"""Whether a warning should be emitted for the configuration.
1113+
1114+
.. versionadded:: 8.6
1115+
"""
1116+
return self._should_warn
1117+
11101118
def add_cleanup(self, func: Callable[[], None]) -> None:
11111119
"""Add a function to be called when the config object gets out of
11121120
use (usually coinciding with pytest_unconfigure).
@@ -1242,14 +1250,15 @@ def _initini(self, args: Sequence[str]) -> None:
12421250
ns, unknown_args = self._parser.parse_known_and_unknown_args(
12431251
args, namespace=copy.copy(self.option)
12441252
)
1245-
rootpath, inipath, inicfg = determine_setup(
1253+
rootpath, inipath, inicfg, should_warn = determine_setup(
12461254
inifile=ns.inifilename,
12471255
args=ns.file_or_dir + unknown_args,
12481256
rootdir_cmd_arg=ns.rootdir or None,
12491257
invocation_dir=self.invocation_params.dir,
12501258
)
12511259
self._rootpath = rootpath
12521260
self._inipath = inipath
1261+
self._should_warn = should_warn
12531262
self.inicfg = inicfg
12541263
self._parser.extra_info["rootdir"] = str(self.rootpath)
12551264
self._parser.extra_info["inifile"] = str(self.inipath)

src/_pytest/config/findpaths.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def make_scalar(v: object) -> str | list[str]:
9191
def locate_config(
9292
invocation_dir: Path,
9393
args: Iterable[Path],
94-
) -> tuple[Path | None, Path | None, ConfigDict]:
94+
) -> tuple[Path | None, Path | None, ConfigDict, bool]:
9595
"""Search in the list of arguments for a valid ini-file for pytest,
9696
and return a tuple of (rootdir, inifile, cfg-dict)."""
9797
config_names = [
@@ -105,6 +105,7 @@ def locate_config(
105105
if not args:
106106
args = [invocation_dir]
107107
found_pyproject_toml: Path | None = None
108+
108109
for arg in args:
109110
argpath = absolutepath(arg)
110111
for base in (argpath, *argpath.parents):
@@ -115,10 +116,17 @@ def locate_config(
115116
found_pyproject_toml = p
116117
ini_config = load_config_dict_from_file(p)
117118
if ini_config is not None:
118-
return base, p, ini_config
119+
should_warn = False
120+
if p.name in ["pytest.ini", ".pytest.ini"]:
121+
pyproject = base / "pyproject.toml"
122+
if pyproject.is_file():
123+
should_warn = (
124+
load_config_dict_from_file(pyproject) is not None
125+
)
126+
return base, p, ini_config, should_warn
119127
if found_pyproject_toml is not None:
120-
return found_pyproject_toml.parent, found_pyproject_toml, {}
121-
return None, None, {}
128+
return found_pyproject_toml.parent, found_pyproject_toml, {}, False
129+
return None, None, {}, False
122130

123131

124132
def get_common_ancestor(
@@ -178,7 +186,7 @@ def determine_setup(
178186
args: Sequence[str],
179187
rootdir_cmd_arg: str | None,
180188
invocation_dir: Path,
181-
) -> tuple[Path, Path | None, ConfigDict]:
189+
) -> tuple[Path, Path | None, ConfigDict, bool]:
182190
"""Determine the rootdir, inifile and ini configuration values from the
183191
command line arguments.
184192
@@ -193,6 +201,7 @@ def determine_setup(
193201
"""
194202
rootdir = None
195203
dirs = get_dirs_from_args(args)
204+
should_warn = False
196205
if inifile:
197206
inipath_ = absolutepath(inifile)
198207
inipath: Path | None = inipath_
@@ -201,15 +210,17 @@ def determine_setup(
201210
rootdir = inipath_.parent
202211
else:
203212
ancestor = get_common_ancestor(invocation_dir, dirs)
204-
rootdir, inipath, inicfg = locate_config(invocation_dir, [ancestor])
213+
rootdir, inipath, inicfg, should_warn = locate_config(
214+
invocation_dir, [ancestor]
215+
)
205216
if rootdir is None and rootdir_cmd_arg is None:
206217
for possible_rootdir in (ancestor, *ancestor.parents):
207218
if (possible_rootdir / "setup.py").is_file():
208219
rootdir = possible_rootdir
209220
break
210221
else:
211222
if dirs != [ancestor]:
212-
rootdir, inipath, inicfg = locate_config(invocation_dir, dirs)
223+
rootdir, inipath, inicfg, _ = locate_config(invocation_dir, dirs)
213224
if rootdir is None:
214225
rootdir = get_common_ancestor(
215226
invocation_dir, [invocation_dir, ancestor]
@@ -223,7 +234,7 @@ def determine_setup(
223234
f"Directory '{rootdir}' not found. Check your '--rootdir' option."
224235
)
225236
assert rootdir is not None
226-
return rootdir, inipath, inicfg or {}
237+
return rootdir, inipath, inicfg or {}, should_warn
227238

228239

229240
def is_fs_root(p: Path) -> bool:

src/_pytest/terminal.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -880,10 +880,8 @@ def pytest_report_header(self, config: Config) -> list[str]:
880880

881881
if config.inipath:
882882
warning = ""
883-
if config.inipath.name in ["pytest.ini", ".pytest.ini"]:
884-
pyproject = config.rootpath / "pyproject.toml"
885-
if pyproject.exists():
886-
warning = " (WARNING: ignoring pytest config in pyproject.toml!)"
883+
if config.should_warn:
884+
warning = " (WARNING: ignoring pytest config in pyproject.toml!)"
887885
result.append(
888886
"configfile: " + bestrelpath(config.rootpath, config.inipath) + warning
889887
)

testing/test_config.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def test_getcfg_and_config(
5656
),
5757
encoding="utf-8",
5858
)
59-
_, _, cfg = locate_config(Path.cwd(), [sub])
59+
_, _, cfg, _ = locate_config(Path.cwd(), [sub])
6060
assert cfg["name"] == "value"
6161
config = pytester.parseconfigure(str(sub))
6262
assert config.inicfg["name"] == "value"
@@ -1635,15 +1635,15 @@ def test_with_ini(self, tmp_path: Path, name: str, contents: str) -> None:
16351635
b = a / "b"
16361636
b.mkdir()
16371637
for args in ([str(tmp_path)], [str(a)], [str(b)]):
1638-
rootpath, parsed_inipath, _ = determine_setup(
1638+
rootpath, parsed_inipath, *_ = determine_setup(
16391639
inifile=None,
16401640
args=args,
16411641
rootdir_cmd_arg=None,
16421642
invocation_dir=Path.cwd(),
16431643
)
16441644
assert rootpath == tmp_path
16451645
assert parsed_inipath == inipath
1646-
rootpath, parsed_inipath, ini_config = determine_setup(
1646+
rootpath, parsed_inipath, ini_config, _ = determine_setup(
16471647
inifile=None,
16481648
args=[str(b), str(a)],
16491649
rootdir_cmd_arg=None,
@@ -1660,7 +1660,7 @@ def test_pytestini_overrides_empty_other(self, tmp_path: Path, name: str) -> Non
16601660
a = tmp_path / "a"
16611661
a.mkdir()
16621662
(a / name).touch()
1663-
rootpath, parsed_inipath, _ = determine_setup(
1663+
rootpath, parsed_inipath, *_ = determine_setup(
16641664
inifile=None,
16651665
args=[str(a)],
16661666
rootdir_cmd_arg=None,
@@ -1674,7 +1674,7 @@ def test_setuppy_fallback(self, tmp_path: Path) -> None:
16741674
a.mkdir()
16751675
(a / "setup.cfg").touch()
16761676
(tmp_path / "setup.py").touch()
1677-
rootpath, inipath, inicfg = determine_setup(
1677+
rootpath, inipath, inicfg, _ = determine_setup(
16781678
inifile=None,
16791679
args=[str(a)],
16801680
rootdir_cmd_arg=None,
@@ -1686,7 +1686,7 @@ def test_setuppy_fallback(self, tmp_path: Path) -> None:
16861686

16871687
def test_nothing(self, tmp_path: Path, monkeypatch: MonkeyPatch) -> None:
16881688
monkeypatch.chdir(tmp_path)
1689-
rootpath, inipath, inicfg = determine_setup(
1689+
rootpath, inipath, inicfg, _ = determine_setup(
16901690
inifile=None,
16911691
args=[str(tmp_path)],
16921692
rootdir_cmd_arg=None,
@@ -1713,7 +1713,7 @@ def test_with_specific_inifile(
17131713
p = tmp_path / name
17141714
p.touch()
17151715
p.write_text(contents, encoding="utf-8")
1716-
rootpath, inipath, ini_config = determine_setup(
1716+
rootpath, inipath, ini_config, _ = determine_setup(
17171717
inifile=str(p),
17181718
args=[str(tmp_path)],
17191719
rootdir_cmd_arg=None,
@@ -1761,7 +1761,7 @@ def test_with_arg_outside_cwd_without_inifile(
17611761
a.mkdir()
17621762
b = tmp_path / "b"
17631763
b.mkdir()
1764-
rootpath, inifile, _ = determine_setup(
1764+
rootpath, inifile, *_ = determine_setup(
17651765
inifile=None,
17661766
args=[str(a), str(b)],
17671767
rootdir_cmd_arg=None,
@@ -1777,7 +1777,7 @@ def test_with_arg_outside_cwd_with_inifile(self, tmp_path: Path) -> None:
17771777
b.mkdir()
17781778
inipath = a / "pytest.ini"
17791779
inipath.touch()
1780-
rootpath, parsed_inipath, _ = determine_setup(
1780+
rootpath, parsed_inipath, *_ = determine_setup(
17811781
inifile=None,
17821782
args=[str(a), str(b)],
17831783
rootdir_cmd_arg=None,
@@ -1791,7 +1791,7 @@ def test_with_non_dir_arg(
17911791
self, dirs: Sequence[str], tmp_path: Path, monkeypatch: MonkeyPatch
17921792
) -> None:
17931793
monkeypatch.chdir(tmp_path)
1794-
rootpath, inipath, _ = determine_setup(
1794+
rootpath, inipath, *_ = determine_setup(
17951795
inifile=None,
17961796
args=dirs,
17971797
rootdir_cmd_arg=None,
@@ -1807,7 +1807,7 @@ def test_with_existing_file_in_subdir(
18071807
a.mkdir()
18081808
(a / "exists").touch()
18091809
monkeypatch.chdir(tmp_path)
1810-
rootpath, inipath, _ = determine_setup(
1810+
rootpath, inipath, *_ = determine_setup(
18111811
inifile=None,
18121812
args=["a/exist"],
18131813
rootdir_cmd_arg=None,
@@ -1826,7 +1826,7 @@ def test_with_config_also_in_parent_directory(
18261826
(tmp_path / "myproject" / "tests").mkdir()
18271827
monkeypatch.chdir(tmp_path / "myproject")
18281828

1829-
rootpath, inipath, _ = determine_setup(
1829+
rootpath, inipath, *_ = determine_setup(
18301830
inifile=None,
18311831
args=["tests/"],
18321832
rootdir_cmd_arg=None,

testing/test_terminal.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2914,6 +2914,27 @@ def test_warning_when_init_trumps_pyproject_toml(
29142914
)
29152915

29162916

2917+
def test_no_warning_when_init_but_pyproject_toml_has_no_entry(
2918+
pytester: Pytester, monkeypatch: MonkeyPatch
2919+
) -> None:
2920+
"""Regression test for #7814."""
2921+
tests = pytester.path.joinpath("tests")
2922+
tests.mkdir()
2923+
pytester.makepyprojecttoml(
2924+
f"""
2925+
[tool]
2926+
testpaths = ['{tests}']
2927+
"""
2928+
)
2929+
pytester.makefile(".ini", pytest="")
2930+
result = pytester.runpytest()
2931+
result.stdout.fnmatch_lines(
2932+
[
2933+
"configfile: pytest.ini",
2934+
]
2935+
)
2936+
2937+
29172938
def test_no_warning_on_terminal_with_a_single_config_file(
29182939
pytester: Pytester, monkeypatch: MonkeyPatch
29192940
) -> None:

0 commit comments

Comments
 (0)