diff options
author | Masen Furer <m_github@0x26.net> | 2023-01-16 14:08:26 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-16 14:08:26 -0800 |
commit | e4c65bb1fef704aadc6192679f21a55dfeee9c62 (patch) | |
tree | 82b4a7637212019e4a9b8071d91af8cb23cb57dc | |
parent | a2222e98b320467e821cf9444113e9b40ab3ad1b (diff) | |
download | tox-git-e4c65bb1fef704aadc6192679f21a55dfeee9c62.tar.gz |
Provision: ignore other test environments (#2865)
Fix https://github.com/tox-dev/tox/issues/2862
-rw-r--r-- | docs/changelog/2862.bugfix.rst | 4 | ||||
-rw-r--r-- | docs/upgrading.rst | 7 | ||||
-rw-r--r-- | src/tox/provision.py | 3 | ||||
-rw-r--r-- | src/tox/session/env_select.py | 13 | ||||
-rw-r--r-- | tests/demo_pkg_inline/build.py | 27 | ||||
-rw-r--r-- | tests/test_provision.py | 25 |
6 files changed, 72 insertions, 7 deletions
diff --git a/docs/changelog/2862.bugfix.rst b/docs/changelog/2862.bugfix.rst new file mode 100644 index 00000000..c52228ff --- /dev/null +++ b/docs/changelog/2862.bugfix.rst @@ -0,0 +1,4 @@ +The provision environment (``.tox``) will never inherit from ``testenv``. +During provisioning, other test environments are not processed, allowing the +use of keys and values that may be registered by later tox version or +provisioned plugins - by :user:`masenf`. diff --git a/docs/upgrading.rst b/docs/upgrading.rst index 90b2c550..b44fae87 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -317,3 +317,10 @@ version is above the version this feature was added to it, for example for setup [testenv:dev] deps = setuptools>=64 package = editable + +Provisioning environment +------------------------ + +The provisioning environment is triggered when ``minversion`` or ``requires`` are specified and the current environment +does not satisfy the requirement. In tox 4, the provisioning environment (``.tox`` by default) must be explicitly +configured and will not inherit values from ``[testenv]`` section. diff --git a/src/tox/provision.py b/src/tox/provision.py index 34b56d07..9b1aeba5 100644 --- a/src/tox/provision.py +++ b/src/tox/provision.py @@ -97,7 +97,8 @@ def provision(state: State) -> int | bool: recreate=state.conf.options.recreate and not state.conf.options.no_recreate_provision, ) provision_tox_env: str = state.conf.core["provision_tox_env"] - state.envs._mark_provision(bool(missing), provision_tox_env, loader) + state.conf.memory_seed_loaders[provision_tox_env].append(loader) + state.envs._mark_provision(bool(missing), provision_tox_env) from tox.plugin.manager import MANAGER diff --git a/src/tox/session/env_select.py b/src/tox/session/env_select.py index f926beda..52f11953 100644 --- a/src/tox/session/env_select.py +++ b/src/tox/session/env_select.py @@ -13,7 +13,6 @@ from tox.tox_env.api import ToxEnvCreateArgs from tox.tox_env.register import REGISTER from tox.tox_env.runner import RunToxEnv -from ..config.loader.memory import MemoryLoader from ..config.types import EnvList from ..report import HandledError from ..tox_env.errors import Skip @@ -134,7 +133,7 @@ class EnvSelector: self._manager = MANAGER self._log_handler = self._state._options.log_handler self._journal = self._state._journal - self._provision: None | tuple[bool, str, MemoryLoader] = None + self._provision: None | tuple[bool, str] = None self._state.conf.core.add_config("labels", Dict[str, EnvList], {}, "core labels") tox_env_filter_regex = getattr(state.conf.options, "skip_env", "").strip() @@ -242,10 +241,12 @@ class EnvSelector: def _build_run_env(self, name: str) -> RunToxEnv | None: if self._provision is not None and self._provision[0] is False and name == self._provision[1]: + # ignore provision env unless this is a provision run + return None + if self._provision is not None and self._provision[0] and name != self._provision[1]: + # ignore other envs when this is a provision run return None env_conf = self._state.conf.get_env(name, package=False) - if self._provision is not None and self._provision[1] == name: - env_conf.loaders.insert(0, self._provision[2]) desc = "the tox execute used to evaluate this environment" env_conf.add_config(keys="runner", desc=desc, of_type=str, default=self._state.conf.options.default_runner) runner = REGISTER.runner(cast(str, env_conf["runner"])) @@ -367,8 +368,8 @@ class EnvSelector: if invalid: raise HandledError(f"cannot run packaging environment(s) {','.join(invalid)}") - def _mark_provision(self, on: bool, provision_tox_env: str, loader: MemoryLoader) -> None: - self._provision = on, provision_tox_env, loader + def _mark_provision(self, on: bool, provision_tox_env: str) -> None: + self._provision = on, provision_tox_env __all__ = [ diff --git a/tests/demo_pkg_inline/build.py b/tests/demo_pkg_inline/build.py index 35e22f03..47df3a3d 100644 --- a/tests/demo_pkg_inline/build.py +++ b/tests/demo_pkg_inline/build.py @@ -14,11 +14,38 @@ pkg_name = name.replace("_", "-") version = "1.0.0" dist_info = "{}-{}.dist-info".format(name, version) logic = "{}/__init__.py".format(name) +plugin = "{}/example_plugin.py".format(name) +entry_points = "{}/entry_points.txt".format(dist_info) metadata = "{}/METADATA".format(dist_info) wheel = "{}/WHEEL".format(dist_info) record = "{}/RECORD".format(dist_info) content = { logic: "def do():\n print('greetings from {}')".format(name), + plugin: dedent( + """ + try: + from tox.plugin import impl + from tox.tox_env.python.virtual_env.runner import VirtualEnvRunner + from tox.tox_env.register import ToxEnvRegister + except ImportError: + pass + else: + class ExampleVirtualEnvRunner(VirtualEnvRunner): + @staticmethod + def id() -> str: + return "example" + @impl + def tox_register_tox_env(register: ToxEnvRegister) -> None: + register.add_run_env(ExampleVirtualEnvRunner) + """, + ), + entry_points: dedent( + """ + [tox] + example = {}.example_plugin""".format( + name, + ), + ), metadata: """ Metadata-Version: 2.1 Name: {} diff --git a/tests/test_provision.py b/tests/test_provision.py index c7a7fac2..91d7689d 100644 --- a/tests/test_provision.py +++ b/tests/test_provision.py @@ -187,3 +187,28 @@ def test_provision_no_recreate_json(tox_project: ToxProjectCreator) -> None: with (project.path / "out.json").open() as file_handler: requires = json.load(file_handler) assert requires == {"minversion": None, "requires": ["p", "tox"]} + + +@pytest.mark.integration() +@pytest.mark.usefixtures("_pypi_index_self") +@pytest.mark.parametrize("plugin_testenv", ["testenv", "testenv:a"]) +def test_provision_plugin_runner(tox_project: ToxProjectCreator, tmp_path: Path, plugin_testenv: str) -> None: + """Ensure that testenv runner doesn't affect the provision env.""" + log = tmp_path / "out.log" + proj = tox_project({"tox.ini": f"[tox]\nrequires=demo-pkg-inline\n[{plugin_testenv}]\nrunner=example"}) + result_first = proj.run("r", "-e", "py", "--result-json", str(log)) + result_first.assert_success() + prov_msg = ( + f"ROOT: will run in automatically provisioned tox, host {sys.executable} is missing" + f" [requires (has)]: demo-pkg-inline" + ) + assert prov_msg in result_first.out + + +@pytest.mark.integration() +def test_provision_plugin_runner_in_provision(tox_project: ToxProjectCreator, tmp_path: Path) -> None: + """Ensure that provision environment can be explicitly configured.""" + log = tmp_path / "out.log" + proj = tox_project({"tox.ini": "[tox]\nrequires=somepkg123xyz\n[testenv:.tox]\nrunner=example"}) + with pytest.raises(KeyError, match="example"): + proj.run("r", "-e", "py", "--result-json", str(log)) |