From 2c31dbcbfc4d28944b4116b86a70420a815a012a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:14:44 -0700 Subject: [PATCH 1/4] Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0 (#3603) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 79a3a2561..1820f90de 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,6 +44,6 @@ jobs: name: ${{ env.dists-artifact-name }} path: dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: attestations: true From 723008808899afec3c1aa7412bd7771694d66f5a Mon Sep 17 00:00:00 2001 From: Vytautas Liuolia Date: Thu, 4 Sep 2025 17:23:59 +0200 Subject: [PATCH 2/4] Ensure automatically provisioned environment is torn down (#3601) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/changelog/3600.bugfix.rst | 4 +++ src/tox/provision.py | 12 ++++--- src/tox/tox_env/package.py | 4 ++- tests/test_provision.py | 63 +++++++++++++++++++++++++++++----- 4 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 docs/changelog/3600.bugfix.rst diff --git a/docs/changelog/3600.bugfix.rst b/docs/changelog/3600.bugfix.rst new file mode 100644 index 000000000..4fa82025b --- /dev/null +++ b/docs/changelog/3600.bugfix.rst @@ -0,0 +1,4 @@ +Previously, when tox ran in an automatically provisioned environment, it could hang waiting for a PEP 517 build backend +if used in conjunction with the ``--installpkg`` option. This has been fixed by properly tearing down the automatically +provisioned environment after the tests. +- by :user:`vytas7` diff --git a/src/tox/provision.py b/src/tox/provision.py index c989c39dd..86fedf912 100644 --- a/src/tox/provision.py +++ b/src/tox/provision.py @@ -146,10 +146,14 @@ def run_provision(name: str, state: State) -> int: logging.info("will run in a automatically provisioned python environment under %s", env_python) try: tox_env.setup() + args: list[str] = [str(env_python), "-m", "tox"] + args.extend(state.args) + outcome = tox_env.execute( + cmd=args, stdin=StdinSource.user_only(), show=True, run_id="provision", cwd=Path.cwd() + ) + return cast("int", outcome.exit_code) except Skip as exception: msg = f"cannot provision tox environment {tox_env.conf['env_name']} because {exception}" raise HandledError(msg) from exception - args: list[str] = [str(env_python), "-m", "tox"] - args.extend(state.args) - outcome = tox_env.execute(cmd=args, stdin=StdinSource.user_only(), show=True, run_id="provision", cwd=Path.cwd()) - return cast("int", outcome.exit_code) + finally: + tox_env.teardown() diff --git a/src/tox/tox_env/package.py b/src/tox/tox_env/package.py index a870d3649..a097b5a67 100644 --- a/src/tox/tox_env/package.py +++ b/src/tox/tox_env/package.py @@ -97,7 +97,9 @@ def mark_active_run_env(self, run_env: RunToxEnv) -> None: self._envs.add(run_env.conf.name) def teardown_env(self, conf: EnvConfigSet) -> None: - self._envs.remove(conf.name) + if conf.name in self._envs: + # conf.name (".tox") may be missing in self._envs in the case of an automatically provisioned environment + self._envs.remove(conf.name) if len(self._envs) == 0: self._teardown() diff --git a/tests/test_provision.py b/tests/test_provision.py index 0cf4de589..2cde4f68b 100644 --- a/tests/test_provision.py +++ b/tests/test_provision.py @@ -7,7 +7,7 @@ from contextlib import contextmanager from pathlib import Path from subprocess import check_call -from typing import TYPE_CHECKING, Callable, Iterator +from typing import TYPE_CHECKING, Callable, Iterator, Sequence from unittest import mock from zipfile import ZipFile @@ -16,6 +16,7 @@ from packaging.requirements import Requirement if TYPE_CHECKING: + from build import DistributionType from devpi_process import Index, IndexServer from tox.pytest import MonkeyPatch, TempPathFactory, ToxProjectCreator @@ -102,22 +103,38 @@ def tox_wheels(tox_wheel: Path, tmp_path_factory: TempPathFactory) -> list[Path] @pytest.fixture(scope="session") -def pypi_index_self(pypi_server: IndexServer, tox_wheels: list[Path], demo_pkg_inline_wheel: Path) -> Index: - with elapsed("start devpi and create index"): # takes around 1s +def local_pypi_indexes( + pypi_server: IndexServer, tox_wheels: list[Path], demo_pkg_inline_wheel: Path +) -> tuple[Index, Index]: + with elapsed("start devpi and create indexes"): # takes around 1s + pypi_server.create_index("mirror", "type=mirror", "mirror_url=https://pypi.org/simple/") + mirrored_index = pypi_server.create_index("magic", f"bases={pypi_server.user}/mirror") self_index = pypi_server.create_index("self", "volatile=False") with elapsed("upload tox and its wheels to devpi"): # takes around 3.2s on build + mirrored_index.upload(*tox_wheels, demo_pkg_inline_wheel) self_index.upload(*tox_wheels, demo_pkg_inline_wheel) - return self_index + return mirrored_index, self_index -@pytest.fixture -def _pypi_index_self(pypi_index_self: Index, monkeypatch: MonkeyPatch) -> None: - pypi_index_self.use() - monkeypatch.setenv("PIP_INDEX_URL", pypi_index_self.url) +def _use_pypi_index(pypi_index: Index, monkeypatch: MonkeyPatch) -> None: + pypi_index.use() + monkeypatch.setenv("PIP_INDEX_URL", pypi_index.url) monkeypatch.setenv("PIP_RETRIES", str(2)) monkeypatch.setenv("PIP_TIMEOUT", str(5)) +@pytest.fixture +def _pypi_index_mirrored(local_pypi_indexes: tuple[Index, Index], monkeypatch: MonkeyPatch) -> None: + pypi_index_mirrored, _ = local_pypi_indexes + _use_pypi_index(pypi_index_mirrored, monkeypatch) + + +@pytest.fixture +def _pypi_index_self(local_pypi_indexes: tuple[Index, Index], monkeypatch: MonkeyPatch) -> None: + _, pypi_index_self = local_pypi_indexes + _use_pypi_index(pypi_index_self, monkeypatch) + + def test_provision_requires_nok(tox_project: ToxProjectCreator) -> None: ini = "[tox]\nrequires = pkg-does-not-exist\n setuptools==1\nskipsdist=true\n" outcome = tox_project({"tox.ini": ini}).run("c", "-e", "py") @@ -254,3 +271,33 @@ def test_provision_default_arguments_exists(tox_project: ToxProjectCreator, subc outcome = project.run(subcommand) for argument in ["result_json", "hash_seed", "discover", "list_dependencies"]: assert hasattr(outcome.state.conf.options, argument) + + +@pytest.mark.integration +@pytest.mark.usefixtures("_pypi_index_mirrored") +def test_provision_install_pkg_pep517( + tmp_path_factory: TempPathFactory, + tox_project: ToxProjectCreator, + pkg_builder: Callable[[Path, Path, Sequence[DistributionType], bool], Path], +) -> None: + example = tmp_path_factory.mktemp("example") + skeleton = """ + [build-system] + requires = ["setuptools"] + build-backend = "setuptools.build_meta" + [project] + name = "skeleton" + version = "0.1.1337" + """ + (example / "pyproject.toml").write_text(skeleton) + sdist = pkg_builder(example / "dist", example, ["sdist"], False) + + tox_ini = r""" + [tox] + requires = demo-pkg-inline + [testenv] + commands = python -c "print(42)" + """ + project = tox_project({"tox.ini": tox_ini}, base=example) + result = project.run("r", "-e", "py", "--installpkg", str(sdist), "--notest") + result.assert_success() From 64e8a34883369a80350b311ceb3550f30931cd51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:03:35 -0700 Subject: [PATCH 3/4] Bump pypa/gh-action-pypi-publish in /.github/workflows (#3604) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 5e0784a7f5ea5f89c089351c9a7e23863bd131b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 4 Sep 2025 09:23:53 -0700 Subject: [PATCH 4/4] release 4.30.2 --- docs/changelog.rst | 10 ++++++++++ docs/changelog/3600.bugfix.rst | 4 ---- 2 files changed, 10 insertions(+), 4 deletions(-) delete mode 100644 docs/changelog/3600.bugfix.rst diff --git a/docs/changelog.rst b/docs/changelog.rst index 225ce668f..952f15fb7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,16 @@ Release History .. towncrier release notes start +v4.30.2 (2025-09-04) +-------------------- + +Bugfixes - 4.30.2 +~~~~~~~~~~~~~~~~~ +- Previously, when tox ran in an automatically provisioned environment, it could hang waiting for a PEP 517 build backend + if used in conjunction with the ``--installpkg`` option. This has been fixed by properly tearing down the automatically + provisioned environment after the tests. + - by :user:`vytas7` (:issue:`3600`) + v4.30.1 (2025-09-03) -------------------- diff --git a/docs/changelog/3600.bugfix.rst b/docs/changelog/3600.bugfix.rst deleted file mode 100644 index 4fa82025b..000000000 --- a/docs/changelog/3600.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -Previously, when tox ran in an automatically provisioned environment, it could hang waiting for a PEP 517 build backend -if used in conjunction with the ``--installpkg`` option. This has been fixed by properly tearing down the automatically -provisioned environment after the tests. -- by :user:`vytas7`