Skip to content

Commit 7230088

Browse files
Ensure automatically provisioned environment is torn down (#3601)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 2c31dbc commit 7230088

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

docs/changelog/3600.bugfix.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Previously, when tox ran in an automatically provisioned environment, it could hang waiting for a PEP 517 build backend
2+
if used in conjunction with the ``--installpkg`` option. This has been fixed by properly tearing down the automatically
3+
provisioned environment after the tests.
4+
- by :user:`vytas7`

src/tox/provision.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,14 @@ def run_provision(name: str, state: State) -> int:
146146
logging.info("will run in a automatically provisioned python environment under %s", env_python)
147147
try:
148148
tox_env.setup()
149+
args: list[str] = [str(env_python), "-m", "tox"]
150+
args.extend(state.args)
151+
outcome = tox_env.execute(
152+
cmd=args, stdin=StdinSource.user_only(), show=True, run_id="provision", cwd=Path.cwd()
153+
)
154+
return cast("int", outcome.exit_code)
149155
except Skip as exception:
150156
msg = f"cannot provision tox environment {tox_env.conf['env_name']} because {exception}"
151157
raise HandledError(msg) from exception
152-
args: list[str] = [str(env_python), "-m", "tox"]
153-
args.extend(state.args)
154-
outcome = tox_env.execute(cmd=args, stdin=StdinSource.user_only(), show=True, run_id="provision", cwd=Path.cwd())
155-
return cast("int", outcome.exit_code)
158+
finally:
159+
tox_env.teardown()

src/tox/tox_env/package.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ def mark_active_run_env(self, run_env: RunToxEnv) -> None:
9797
self._envs.add(run_env.conf.name)
9898

9999
def teardown_env(self, conf: EnvConfigSet) -> None:
100-
self._envs.remove(conf.name)
100+
if conf.name in self._envs:
101+
# conf.name (".tox") may be missing in self._envs in the case of an automatically provisioned environment
102+
self._envs.remove(conf.name)
101103
if len(self._envs) == 0:
102104
self._teardown()
103105

tests/test_provision.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from contextlib import contextmanager
88
from pathlib import Path
99
from subprocess import check_call
10-
from typing import TYPE_CHECKING, Callable, Iterator
10+
from typing import TYPE_CHECKING, Callable, Iterator, Sequence
1111
from unittest import mock
1212
from zipfile import ZipFile
1313

@@ -16,6 +16,7 @@
1616
from packaging.requirements import Requirement
1717

1818
if TYPE_CHECKING:
19+
from build import DistributionType
1920
from devpi_process import Index, IndexServer
2021

2122
from tox.pytest import MonkeyPatch, TempPathFactory, ToxProjectCreator
@@ -102,22 +103,38 @@ def tox_wheels(tox_wheel: Path, tmp_path_factory: TempPathFactory) -> list[Path]
102103

103104

104105
@pytest.fixture(scope="session")
105-
def pypi_index_self(pypi_server: IndexServer, tox_wheels: list[Path], demo_pkg_inline_wheel: Path) -> Index:
106-
with elapsed("start devpi and create index"): # takes around 1s
106+
def local_pypi_indexes(
107+
pypi_server: IndexServer, tox_wheels: list[Path], demo_pkg_inline_wheel: Path
108+
) -> tuple[Index, Index]:
109+
with elapsed("start devpi and create indexes"): # takes around 1s
110+
pypi_server.create_index("mirror", "type=mirror", "mirror_url=https://pypi.org/simple/")
111+
mirrored_index = pypi_server.create_index("magic", f"bases={pypi_server.user}/mirror")
107112
self_index = pypi_server.create_index("self", "volatile=False")
108113
with elapsed("upload tox and its wheels to devpi"): # takes around 3.2s on build
114+
mirrored_index.upload(*tox_wheels, demo_pkg_inline_wheel)
109115
self_index.upload(*tox_wheels, demo_pkg_inline_wheel)
110-
return self_index
116+
return mirrored_index, self_index
111117

112118

113-
@pytest.fixture
114-
def _pypi_index_self(pypi_index_self: Index, monkeypatch: MonkeyPatch) -> None:
115-
pypi_index_self.use()
116-
monkeypatch.setenv("PIP_INDEX_URL", pypi_index_self.url)
119+
def _use_pypi_index(pypi_index: Index, monkeypatch: MonkeyPatch) -> None:
120+
pypi_index.use()
121+
monkeypatch.setenv("PIP_INDEX_URL", pypi_index.url)
117122
monkeypatch.setenv("PIP_RETRIES", str(2))
118123
monkeypatch.setenv("PIP_TIMEOUT", str(5))
119124

120125

126+
@pytest.fixture
127+
def _pypi_index_mirrored(local_pypi_indexes: tuple[Index, Index], monkeypatch: MonkeyPatch) -> None:
128+
pypi_index_mirrored, _ = local_pypi_indexes
129+
_use_pypi_index(pypi_index_mirrored, monkeypatch)
130+
131+
132+
@pytest.fixture
133+
def _pypi_index_self(local_pypi_indexes: tuple[Index, Index], monkeypatch: MonkeyPatch) -> None:
134+
_, pypi_index_self = local_pypi_indexes
135+
_use_pypi_index(pypi_index_self, monkeypatch)
136+
137+
121138
def test_provision_requires_nok(tox_project: ToxProjectCreator) -> None:
122139
ini = "[tox]\nrequires = pkg-does-not-exist\n setuptools==1\nskipsdist=true\n"
123140
outcome = tox_project({"tox.ini": ini}).run("c", "-e", "py")
@@ -254,3 +271,33 @@ def test_provision_default_arguments_exists(tox_project: ToxProjectCreator, subc
254271
outcome = project.run(subcommand)
255272
for argument in ["result_json", "hash_seed", "discover", "list_dependencies"]:
256273
assert hasattr(outcome.state.conf.options, argument)
274+
275+
276+
@pytest.mark.integration
277+
@pytest.mark.usefixtures("_pypi_index_mirrored")
278+
def test_provision_install_pkg_pep517(
279+
tmp_path_factory: TempPathFactory,
280+
tox_project: ToxProjectCreator,
281+
pkg_builder: Callable[[Path, Path, Sequence[DistributionType], bool], Path],
282+
) -> None:
283+
example = tmp_path_factory.mktemp("example")
284+
skeleton = """
285+
[build-system]
286+
requires = ["setuptools"]
287+
build-backend = "setuptools.build_meta"
288+
[project]
289+
name = "skeleton"
290+
version = "0.1.1337"
291+
"""
292+
(example / "pyproject.toml").write_text(skeleton)
293+
sdist = pkg_builder(example / "dist", example, ["sdist"], False)
294+
295+
tox_ini = r"""
296+
[tox]
297+
requires = demo-pkg-inline
298+
[testenv]
299+
commands = python -c "print(42)"
300+
"""
301+
project = tox_project({"tox.ini": tox_ini}, base=example)
302+
result = project.run("r", "-e", "py", "--installpkg", str(sdist), "--notest")
303+
result.assert_success()

0 commit comments

Comments
 (0)