Skip to content

Commit 4038752

Browse files
committed
Ensure Config.inifile is available during pytest_cmdline_main
Fix pytest-dev#9396
1 parent 1860140 commit 4038752

File tree

4 files changed

+54
-34
lines changed

4 files changed

+54
-34
lines changed

changelog/9396.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensure :attr:`pytest.Config.inifile` is available during the :func:`pytest_cmdline_main <_pytest.hookspec.pytest_cmdline_main>` hook (regression during ``7.0.0rc1``).

src/_pytest/legacypath.py

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -403,60 +403,61 @@ def Node_fspath_set(self: Node, value: LEGACY_PATH) -> None:
403403
self.path = Path(value)
404404

405405

406-
@hookimpl
407-
def pytest_configure(config: Config) -> None:
408-
import pytest
409-
410-
mp = pytest.MonkeyPatch()
411-
config.add_cleanup(mp.undo)
412-
413-
if config.pluginmanager.has_plugin("tmpdir"):
414-
# Create TmpdirFactory and attach it to the config object.
415-
#
416-
# This is to comply with existing plugins which expect the handler to be
417-
# available at pytest_configure time, but ideally should be moved entirely
418-
# to the tmpdir_factory session fixture.
419-
try:
420-
tmp_path_factory = config._tmp_path_factory # type: ignore[attr-defined]
421-
except AttributeError:
422-
# tmpdir plugin is blocked.
423-
pass
424-
else:
425-
_tmpdirhandler = TempdirFactory(tmp_path_factory, _ispytest=True)
426-
mp.setattr(config, "_tmpdirhandler", _tmpdirhandler, raising=False)
427-
428-
config.pluginmanager.register(LegacyTmpdirPlugin, "legacypath-tmpdir")
406+
@hookimpl(tryfirst=True)
407+
def pytest_load_initial_conftests(early_config: Config) -> None:
408+
"""Monkeypatch legacy path attributes in several classes, as early as possible."""
409+
mp = MonkeyPatch()
410+
early_config.add_cleanup(mp.undo)
429411

430412
# Add Cache.makedir().
431-
mp.setattr(pytest.Cache, "makedir", Cache_makedir, raising=False)
413+
mp.setattr(Cache, "makedir", Cache_makedir, raising=False)
432414

433415
# Add FixtureRequest.fspath property.
434-
mp.setattr(
435-
pytest.FixtureRequest, "fspath", property(FixtureRequest_fspath), raising=False
436-
)
416+
mp.setattr(FixtureRequest, "fspath", property(FixtureRequest_fspath), raising=False)
437417

438418
# Add TerminalReporter.startdir property.
439419
mp.setattr(
440420
TerminalReporter, "startdir", property(TerminalReporter_startdir), raising=False
441421
)
442422

443423
# Add Config.{invocation_dir,rootdir,inifile} properties.
444-
mp.setattr(
445-
pytest.Config, "invocation_dir", property(Config_invocation_dir), raising=False
446-
)
447-
mp.setattr(pytest.Config, "rootdir", property(Config_rootdir), raising=False)
448-
mp.setattr(pytest.Config, "inifile", property(Config_inifile), raising=False)
424+
mp.setattr(Config, "invocation_dir", property(Config_invocation_dir), raising=False)
425+
mp.setattr(Config, "rootdir", property(Config_rootdir), raising=False)
426+
mp.setattr(Config, "inifile", property(Config_inifile), raising=False)
449427

450428
# Add Session.startdir property.
451-
mp.setattr(pytest.Session, "startdir", property(Session_stardir), raising=False)
429+
mp.setattr(Session, "startdir", property(Session_stardir), raising=False)
452430

453431
# Add pathlist configuration type.
454-
mp.setattr(pytest.Config, "_getini_unknown_type", Config__getini_unknown_type)
432+
mp.setattr(Config, "_getini_unknown_type", Config__getini_unknown_type)
455433

456434
# Add Node.fspath property.
457435
mp.setattr(Node, "fspath", property(Node_fspath, Node_fspath_set), raising=False)
458436

459437

438+
@hookimpl
439+
def pytest_configure(config: Config) -> None:
440+
"""Installs the LegacyTmpdirPlugin if the ``tmpdir`` plugin is also installed."""
441+
if config.pluginmanager.has_plugin("tmpdir"):
442+
mp = MonkeyPatch()
443+
config.add_cleanup(mp.undo)
444+
# Create TmpdirFactory and attach it to the config object.
445+
#
446+
# This is to comply with existing plugins which expect the handler to be
447+
# available at pytest_configure time, but ideally should be moved entirely
448+
# to the tmpdir_factory session fixture.
449+
try:
450+
tmp_path_factory = config._tmp_path_factory # type: ignore[attr-defined]
451+
except AttributeError:
452+
# tmpdir plugin is blocked.
453+
pass
454+
else:
455+
_tmpdirhandler = TempdirFactory(tmp_path_factory, _ispytest=True)
456+
mp.setattr(config, "_tmpdirhandler", _tmpdirhandler, raising=False)
457+
458+
config.pluginmanager.register(LegacyTmpdirPlugin, "legacypath-tmpdir")
459+
460+
460461
@hookimpl
461462
def pytest_plugin_registered(plugin: object, manager: PytestPluginManager) -> None:
462463
# pytester is not loaded by default and is commonly loaded from a conftest,

testing/test_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ def pytest_load_initial_conftests(self):
12681268
expected = [
12691269
"_pytest.config",
12701270
m.__module__,
1271+
"_pytest.legacypath",
12711272
"_pytest.pythonpath",
12721273
"_pytest.capture",
12731274
"_pytest.warnings",

testing/test_legacypath.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,20 @@ def test_overriden(pytestconfig):
161161
)
162162
result = pytester.runpytest("--override-ini", "paths=foo/bar1.py foo/bar2.py", "-s")
163163
result.stdout.fnmatch_lines(["user_path:bar1.py", "user_path:bar2.py"])
164+
165+
166+
def test_inifile_from_cmdline_main_hook(pytester: pytest.Pytester) -> None:
167+
"""Ensure Config.inifile is available during pytest_cmdline_main (#9396)."""
168+
p = pytester.makeini(
169+
"""
170+
[pytest]
171+
"""
172+
)
173+
pytester.makeconftest(
174+
"""
175+
def pytest_cmdline_main(config):
176+
print("pytest_cmdline_main inifile =", config.inifile)
177+
"""
178+
)
179+
result = pytester.runpytest_subprocess("-s")
180+
result.stdout.fnmatch_lines(f"*pytest_cmdline_main inifile = {p}")

0 commit comments

Comments
 (0)