1515
1616import re
1717import shutil
18+ import subprocess
1819from pathlib import Path
1920from string import Template
20- from typing import Callable
21+ from typing import Any , Callable
2122
2223import pytest
2324
@@ -63,6 +64,22 @@ def generate_noxfile(**option_mapping: str | bool) -> str:
6364 return generate_noxfile
6465
6566
67+ # This fixture will be automatically used unless the test has the 'conda' marker
68+ @pytest .fixture
69+ def prevent_conda (monkeypatch : pytest .MonkeyPatch ) -> None :
70+ def blocked_popen (* args : Any , ** kwargs : Any ) -> Any :
71+ cmd = args [0 ]
72+ msg = "Use of 'conda' command is blocked in tests without @pytest.mark.conda"
73+ if (isinstance (cmd , list ) and "conda" in cmd [0 ]) or (
74+ isinstance (cmd , str ) and "conda" in cmd
75+ ):
76+ raise RuntimeError (msg )
77+ return original_popen (* args , ** kwargs )
78+
79+ original_popen = subprocess .Popen
80+ monkeypatch .setattr (subprocess , "Popen" , blocked_popen )
81+
82+
6683@pytest .hookimpl (tryfirst = True )
6784def pytest_collection_modifyitems (items : list [pytest .Item ]) -> None :
6885 for item in items :
@@ -73,3 +90,9 @@ def pytest_collection_modifyitems(items: list[pytest.Item]) -> None:
7390 pytest .mark .skipif (not HAS_CONDA , reason = "Missing conda command." )
7491 )
7592 item .add_marker (pytest .mark .xdist_group (name = "conda" ))
93+
94+
95+ # Protection to make sure every conda-using test requests it
96+ def pytest_runtest_setup (item : pytest .Item ) -> None :
97+ if not any (mark .name == "conda" for mark in item .iter_markers ()):
98+ item .fixturenames = [* item .fixturenames , "prevent_conda" ] # type: ignore[attr-defined]
0 commit comments