Skip to content

✨ feat(env): add virtualenv_spec for per-env version pinning#3794

Merged
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:feat/3656-virtualenv-spec
Feb 20, 2026
Merged

✨ feat(env): add virtualenv_spec for per-env version pinning#3794
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:feat/3656-virtualenv-spec

Conversation

@gaborbernat
Copy link
Copy Markdown
Member

No single virtualenv release covers the full range of Python versions that projects need to test against — older versions like virtualenv<20.22.0 are required for Python 3.6, while the latest virtualenv is needed for Python 3.15+. Since tox imports virtualenv as a library, environments targeting unsupported Python versions simply fail with no workaround. ✨ This becomes a real blocker for projects that must maintain compatibility across a wide Python version range in a single tox.toml.

The new virtualenv_spec per-environment config key (e.g. virtualenv_spec = "virtualenv<20.22.0") solves this by bootstrapping the specified virtualenv version into a cached venv under .tox/.virtualenv-bootstrap/ and driving it via subprocess instead of the imported library. The bootstrap is content-addressed by spec hash, protected by file locks for concurrent safety, and reused across runs. When virtualenv_spec is empty (the default), tox continues using the imported virtualenv with zero overhead — the subprocess path only activates when explicitly configured.

The VirtualEnv class now operates in dual mode: its session property routes to either the imported session_via_cli or a new SubprocessSession that mimics the same Session/Creator/Describe interface. Path accessors (bin_dir, purelib, exe, etc.) dispatch through isinstance checks so both modes integrate transparently with the rest of the environment lifecycle. The python_cache() dict includes the spec string when set, ensuring environments are automatically recreated when the pinned version changes.

Closes #3656

@gaborbernat gaborbernat force-pushed the feat/3656-virtualenv-spec branch 3 times, most recently from 9e78de8 to f6768d5 Compare February 20, 2026 05:48
No single virtualenv version supports both very old (3.6) and very new
(3.15+) Python versions. When the installed virtualenv cannot handle a
target Python, the entire environment fails with no workaround.

The new `virtualenv_spec` config key (e.g. `virtualenv<20.22.0`) lets
users pin a different virtualenv version per environment. When set, tox
bootstraps that version into a cached venv under `.virtualenv-bootstrap`
and drives it via subprocess instead of the imported library. This keeps
the default zero-overhead path for normal usage while enabling mixed
old/new Python testing in a single tox config.

Closes tox-dev#3656
@gaborbernat gaborbernat force-pushed the feat/3656-virtualenv-spec branch from f6768d5 to d9bdb5f Compare February 20, 2026 07:20
@gaborbernat gaborbernat merged commit c80c62f into tox-dev:main Feb 20, 2026
28 checks passed
@gaborbernat gaborbernat deleted the feat/3656-virtualenv-spec branch February 20, 2026 07:38
@hroncok
Copy link
Copy Markdown
Contributor

hroncok commented Feb 20, 2026

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow testing under both Python 3.6 and 3.15+

2 participants