Skip to content

Commit b2186e2

Browse files
authored
Merge pull request #11268 from bluetech/conftest-load
config: split `_getconftestmodules` and `_loadconftestmodules`
2 parents 18bc6c9 + 01ac13a commit b2186e2

File tree

5 files changed

+50
-84
lines changed

5 files changed

+50
-84
lines changed

src/_pytest/config/__init__.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -581,26 +581,25 @@ def _is_in_confcutdir(self, path: Path) -> bool:
581581
def _try_load_conftest(
582582
self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path
583583
) -> None:
584-
self._getconftestmodules(anchor, importmode, rootpath)
584+
self._loadconftestmodules(anchor, importmode, rootpath)
585585
# let's also consider test* subdirs
586586
if anchor.is_dir():
587587
for x in anchor.glob("test*"):
588588
if x.is_dir():
589-
self._getconftestmodules(x, importmode, rootpath)
589+
self._loadconftestmodules(x, importmode, rootpath)
590590

591-
def _getconftestmodules(
591+
def _loadconftestmodules(
592592
self, path: Path, importmode: Union[str, ImportMode], rootpath: Path
593-
) -> Sequence[types.ModuleType]:
593+
) -> None:
594594
if self._noconftest:
595-
return []
595+
return
596596

597597
directory = self._get_directory(path)
598598

599599
# Optimization: avoid repeated searches in the same directory.
600600
# Assumes always called with same importmode and rootpath.
601-
existing_clist = self._dirpath2confmods.get(directory)
602-
if existing_clist is not None:
603-
return existing_clist
601+
if directory in self._dirpath2confmods:
602+
return
604603

605604
# XXX these days we may rather want to use config.rootpath
606605
# and allow users to opt into looking into the rootdir parent
@@ -613,16 +612,17 @@ def _getconftestmodules(
613612
mod = self._importconftest(conftestpath, importmode, rootpath)
614613
clist.append(mod)
615614
self._dirpath2confmods[directory] = clist
616-
return clist
615+
616+
def _getconftestmodules(self, path: Path) -> Sequence[types.ModuleType]:
617+
directory = self._get_directory(path)
618+
return self._dirpath2confmods.get(directory, ())
617619

618620
def _rget_with_confmod(
619621
self,
620622
name: str,
621623
path: Path,
622-
importmode: Union[str, ImportMode],
623-
rootpath: Path,
624624
) -> Tuple[types.ModuleType, Any]:
625-
modules = self._getconftestmodules(path, importmode, rootpath=rootpath)
625+
modules = self._getconftestmodules(path)
626626
for mod in reversed(modules):
627627
try:
628628
return mod, getattr(mod, name)
@@ -1562,13 +1562,9 @@ def _getini(self, name: str):
15621562
else:
15631563
return self._getini_unknown_type(name, type, value)
15641564

1565-
def _getconftest_pathlist(
1566-
self, name: str, path: Path, rootpath: Path
1567-
) -> Optional[List[Path]]:
1565+
def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]:
15681566
try:
1569-
mod, relroots = self.pluginmanager._rget_with_confmod(
1570-
name, path, self.getoption("importmode"), rootpath
1571-
)
1567+
mod, relroots = self.pluginmanager._rget_with_confmod(name, path)
15721568
except KeyError:
15731569
return None
15741570
assert mod.__file__ is not None

src/_pytest/main.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ def _in_venv(path: Path) -> bool:
376376

377377
def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[bool]:
378378
ignore_paths = config._getconftest_pathlist(
379-
"collect_ignore", path=collection_path.parent, rootpath=config.rootpath
379+
"collect_ignore", path=collection_path.parent
380380
)
381381
ignore_paths = ignore_paths or []
382382
excludeopt = config.getoption("ignore")
@@ -387,7 +387,7 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo
387387
return True
388388

389389
ignore_globs = config._getconftest_pathlist(
390-
"collect_ignore_glob", path=collection_path.parent, rootpath=config.rootpath
390+
"collect_ignore_glob", path=collection_path.parent
391391
)
392392
ignore_globs = ignore_globs or []
393393
excludeglobopt = config.getoption("ignore_glob")
@@ -551,11 +551,16 @@ def gethookproxy(self, fspath: "os.PathLike[str]"):
551551
pm = self.config.pluginmanager
552552
# Check if we have the common case of running
553553
# hooks with all conftest.py files.
554-
my_conftestmodules = pm._getconftestmodules(
554+
#
555+
# TODO: pytest relies on this call to load non-initial conftests. This
556+
# is incidental. It will be better to load conftests at a more
557+
# well-defined place.
558+
pm._loadconftestmodules(
555559
path,
556560
self.config.getoption("importmode"),
557561
rootpath=self.config.rootpath,
558562
)
563+
my_conftestmodules = pm._getconftestmodules(path)
559564
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
560565
if remove_mods:
561566
# One or more conftests are not in use at this fspath.

testing/python/fixtures.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,9 +2103,7 @@ def test_2(self):
21032103
reprec = pytester.inline_run("-v", "-s", "--confcutdir", pytester.path)
21042104
reprec.assertoutcome(passed=8)
21052105
config = reprec.getcalls("pytest_unconfigure")[0].config
2106-
values = config.pluginmanager._getconftestmodules(
2107-
p, importmode="prepend", rootpath=pytester.path
2108-
)[0].values
2106+
values = config.pluginmanager._getconftestmodules(p)[0].values
21092107
assert values == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
21102108

21112109
def test_scope_ordering(self, pytester: Pytester) -> None:

testing/test_config.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -642,18 +642,11 @@ def test_getconftest_pathlist(self, pytester: Pytester, tmp_path: Path) -> None:
642642
p = tmp_path.joinpath("conftest.py")
643643
p.write_text(f"mylist = {['.', str(somepath)]}", encoding="utf-8")
644644
config = pytester.parseconfigure(p)
645-
assert (
646-
config._getconftest_pathlist("notexist", path=tmp_path, rootpath=tmp_path)
647-
is None
648-
)
649-
pl = (
650-
config._getconftest_pathlist("mylist", path=tmp_path, rootpath=tmp_path)
651-
or []
652-
)
653-
print(pl)
654-
assert len(pl) == 2
655-
assert pl[0] == tmp_path
656-
assert pl[1] == somepath
645+
assert config._getconftest_pathlist("notexist", path=tmp_path) is None
646+
assert config._getconftest_pathlist("mylist", path=tmp_path) == [
647+
tmp_path,
648+
somepath,
649+
]
657650

658651
@pytest.mark.parametrize("maybe_type", ["not passed", "None", '"string"'])
659652
def test_addini(self, pytester: Pytester, maybe_type: str) -> None:

testing/test_conftest.py

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -62,62 +62,46 @@ def basedir(
6262
def test_basic_init(self, basedir: Path) -> None:
6363
conftest = PytestPluginManager()
6464
p = basedir / "adir"
65-
assert (
66-
conftest._rget_with_confmod("a", p, importmode="prepend", rootpath=basedir)[
67-
1
68-
]
69-
== 1
70-
)
65+
conftest._loadconftestmodules(p, importmode="prepend", rootpath=basedir)
66+
assert conftest._rget_with_confmod("a", p)[1] == 1
7167

7268
def test_immediate_initialiation_and_incremental_are_the_same(
7369
self, basedir: Path
7470
) -> None:
7571
conftest = PytestPluginManager()
7672
assert not len(conftest._dirpath2confmods)
77-
conftest._getconftestmodules(
78-
basedir, importmode="prepend", rootpath=Path(basedir)
79-
)
73+
conftest._loadconftestmodules(basedir, importmode="prepend", rootpath=basedir)
8074
snap1 = len(conftest._dirpath2confmods)
8175
assert snap1 == 1
82-
conftest._getconftestmodules(
76+
conftest._loadconftestmodules(
8377
basedir / "adir", importmode="prepend", rootpath=basedir
8478
)
8579
assert len(conftest._dirpath2confmods) == snap1 + 1
86-
conftest._getconftestmodules(
80+
conftest._loadconftestmodules(
8781
basedir / "b", importmode="prepend", rootpath=basedir
8882
)
8983
assert len(conftest._dirpath2confmods) == snap1 + 2
9084

9185
def test_value_access_not_existing(self, basedir: Path) -> None:
9286
conftest = ConftestWithSetinitial(basedir)
9387
with pytest.raises(KeyError):
94-
conftest._rget_with_confmod(
95-
"a", basedir, importmode="prepend", rootpath=Path(basedir)
96-
)
88+
conftest._rget_with_confmod("a", basedir)
9789

9890
def test_value_access_by_path(self, basedir: Path) -> None:
9991
conftest = ConftestWithSetinitial(basedir)
10092
adir = basedir / "adir"
101-
assert (
102-
conftest._rget_with_confmod(
103-
"a", adir, importmode="prepend", rootpath=basedir
104-
)[1]
105-
== 1
106-
)
107-
assert (
108-
conftest._rget_with_confmod(
109-
"a", adir / "b", importmode="prepend", rootpath=basedir
110-
)[1]
111-
== 1.5
93+
conftest._loadconftestmodules(adir, importmode="prepend", rootpath=basedir)
94+
assert conftest._rget_with_confmod("a", adir)[1] == 1
95+
conftest._loadconftestmodules(
96+
adir / "b", importmode="prepend", rootpath=basedir
11297
)
98+
assert conftest._rget_with_confmod("a", adir / "b")[1] == 1.5
11399

114100
def test_value_access_with_confmod(self, basedir: Path) -> None:
115101
startdir = basedir / "adir" / "b"
116102
startdir.joinpath("xx").mkdir()
117103
conftest = ConftestWithSetinitial(startdir)
118-
mod, value = conftest._rget_with_confmod(
119-
"a", startdir, importmode="prepend", rootpath=Path(basedir)
120-
)
104+
mod, value = conftest._rget_with_confmod("a", startdir)
121105
assert value == 1.5
122106
assert mod.__file__ is not None
123107
path = Path(mod.__file__)
@@ -143,9 +127,7 @@ def test_doubledash_considered(pytester: Pytester) -> None:
143127
conf.joinpath("conftest.py").touch()
144128
conftest = PytestPluginManager()
145129
conftest_setinitial(conftest, [conf.name, conf.name])
146-
values = conftest._getconftestmodules(
147-
conf, importmode="prepend", rootpath=pytester.path
148-
)
130+
values = conftest._getconftestmodules(conf)
149131
assert len(values) == 1
150132

151133

@@ -192,26 +174,22 @@ def test_conftestcutdir(pytester: Pytester) -> None:
192174
p = pytester.mkdir("x")
193175
conftest = PytestPluginManager()
194176
conftest_setinitial(conftest, [pytester.path], confcutdir=p)
195-
values = conftest._getconftestmodules(
196-
p, importmode="prepend", rootpath=pytester.path
197-
)
177+
conftest._loadconftestmodules(p, importmode="prepend", rootpath=pytester.path)
178+
values = conftest._getconftestmodules(p)
198179
assert len(values) == 0
199-
values = conftest._getconftestmodules(
180+
conftest._loadconftestmodules(
200181
conf.parent, importmode="prepend", rootpath=pytester.path
201182
)
183+
values = conftest._getconftestmodules(conf.parent)
202184
assert len(values) == 0
203185
assert not conftest.has_plugin(str(conf))
204186
# but we can still import a conftest directly
205187
conftest._importconftest(conf, importmode="prepend", rootpath=pytester.path)
206-
values = conftest._getconftestmodules(
207-
conf.parent, importmode="prepend", rootpath=pytester.path
208-
)
188+
values = conftest._getconftestmodules(conf.parent)
209189
assert values[0].__file__ is not None
210190
assert values[0].__file__.startswith(str(conf))
211191
# and all sub paths get updated properly
212-
values = conftest._getconftestmodules(
213-
p, importmode="prepend", rootpath=pytester.path
214-
)
192+
values = conftest._getconftestmodules(p)
215193
assert len(values) == 1
216194
assert values[0].__file__ is not None
217195
assert values[0].__file__.startswith(str(conf))
@@ -221,9 +199,7 @@ def test_conftestcutdir_inplace_considered(pytester: Pytester) -> None:
221199
conf = pytester.makeconftest("")
222200
conftest = PytestPluginManager()
223201
conftest_setinitial(conftest, [conf.parent], confcutdir=conf.parent)
224-
values = conftest._getconftestmodules(
225-
conf.parent, importmode="prepend", rootpath=pytester.path
226-
)
202+
values = conftest._getconftestmodules(conf.parent)
227203
assert len(values) == 1
228204
assert values[0].__file__ is not None
229205
assert values[0].__file__.startswith(str(conf))
@@ -433,10 +409,8 @@ def impct(p, importmode, root):
433409
conftest = PytestPluginManager()
434410
conftest._confcutdir = pytester.path
435411
monkeypatch.setattr(conftest, "_importconftest", impct)
436-
mods = cast(
437-
List[Path],
438-
conftest._getconftestmodules(sub, importmode="prepend", rootpath=pytester.path),
439-
)
412+
conftest._loadconftestmodules(sub, importmode="prepend", rootpath=pytester.path)
413+
mods = cast(List[Path], conftest._getconftestmodules(sub))
440414
expected = [ct1, ct2]
441415
assert mods == expected
442416

0 commit comments

Comments
 (0)