NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #116 most downloaded on PyPI
Virtual Python Environment builder
Last release 2 days ago
02 Oct 2026
Ships on a steady schedule
a new release about every 2 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
3 versions withdrawn
withdrawn after publishing
19 years old
301 releases · first in 2007
🎨 style(test): mark prompt fixture locals Final by @gaborbernat in #3374
Full Changelog: 21.14.4...21.14.5
Fall back to the bundled seed wheel and remove the embed update log when the log in the app data folder holds JSON of the wrong shape, instead of failing to create the environment - by @pasmud . ( #3376 )
One column per quarter.
Upgrade embedded pip/setuptools/wheel and CI test tools by @github-actions[bot] in #3372
Full Changelog: 21.14.3...21.14.4
Fix activate running commands from a virtual environment name or --prompt that holds $(...) , backticks or ${...} when zsh has PROMPT_SUBST set, and show a % in the name as typed under zsh ( GHSA-5vjq-rrrf-7h2q ); reported by @kemrec . ( #3373 )
✨ feat(security): add a private vulnerability report form by @gaborbernat in #3370
Full Changelog: 21.14.2...21.14.3
Honor ~= and every clause of a seed wheel’s Requires-Python when picking a wheel for the target Python, and skip a wheel whose Requires-Python is not a valid specifier instead of failing - by @pasmud . ( #3369 )
📝 docs(changelog): note the activation security fixes by @gaborbernat in #3367
Full Changelog: 21.14.1...21.14.2
Fix pyvenv.cfg getting an absolute path in python-version , include-system-site-packages and the other keys that hold no path when the working directory has an entry named like the value, such as 3.14 for virtualenv 3.14 or true with --system-site-packages - by @darrenhuai . ( #3366 )
Fix activation scripts running code from a virtual environment path whose parent directory carries a placeholder name such as VIRTUAL_NAME ( GHSA-8rjx-v5ww-45pp ), and activate.fish running commands from a path or --prompt that holds a backslash before a single quote ( GHSA-c947-3pg5-gm8q ); both reported by @Kwstubbs of GitHub Security Lab. ( #3367 )
No significant changes.
fix(ci): allow attestation bundle downloads by @gaborbernat in #3364
Full Changelog: 21.14.0...21.14.1
🔧 build(docs): load Mermaid 12.0.0 by @gaborbernat in #3335
Full Changelog: 21.13.0...21.14.0
Record the SPDX license id in the wheel and zipapp SBOMs for bundled packages that declare their license by name or classifier, such as distlib and python-discovery , so license scanners can match them. ( #3339 )
Add the Tidelift and thanks.dev funding links to the PyPI project URLs, next to GitHub Sponsors - by @gaborbernat . ( #3340 )
👷 ci(codeql): scan local inputs and guard activation templates by @gaborbernat in #3317
Full Changelog: 21.12.1...21.13.0
Add Changelog and Funding links to the PyPI project metadata, and replace the 2020-202x placeholder in LICENSE with 2020-present so the copyright field of the wheel SBOM reads as a real range - by @gaborbernat . ( #3334 )
🐛 fix(create): limit .venv redirect to projects by @gaborbernat in #3316
Full Changelog: 21.12.0...21.12.1
Limit the PEP 832 .venv redirect to folders holding a pyproject.toml and no .venv yet, so virtualenv foo in a scratch folder, and tools such as tox or nox building environments through virtualenv, no longer claim a folder’s default environment - by @gaborbernat .
--venv-redirect writes the redirect in any folder and replaces an earlier virtualenv redirect.
A flag on the command line overrides the environment variable and the config file in either direction. ( #3316 )
✨ feat(create): point a .venv redirect per PEP 832 by @gaborbernat in #3204
Full Changelog: 21.11.1...21.12.0
Write the PEP 838 python-version key into pyvenv.cfg , holding the target interpreter’s feature release. The new Generated files page covers it alongside every other file a created environment holds - by @konstin . ( #3193 )
Point a .venv redirect file in the parent folder at the created environment, per PEP 832 , so editors and type checkers can find it - by @gaborbernat .
virtualenv leaves a .venv folder alone, and a redirect pointing at an environment it did not create.
Pass --no-venv-redirect to opt out.
The feature is provisional while PEP 832 is a draft: a minor or patch release may change it in backward incompatible ways to follow the PEP. ( #3204 )
📝 docs(security): close threat items resolved by 21.11.0 by @gaborbernat in #3313
Full Changelog: 21.11.0...21.11.1
Include the pre-commit configuration and the zipapp lock file in the source distribution, so downstream packagers can run the test suite from it. ( #3314 )
ci(pre-release): disable the uv cache by @gaborbernat in #3288
Full Changelog: 21.10.0...21.11.0
Attach the CycloneDX SBOM and an SPDX 2.3 rendering of it ( virtualenv.cdx.json , virtualenv.spdx.json ) to each GitHub release, and attest the SPDX document against the sdist and wheel. ( #3299 )
Describe the zipapp in its own CycloneDX SBOM, which lists virtualenv, the embedded pip and setuptools wheels, and each bundled dependency with the Python versions that load it, down to a SHA-256 per file. The SBOM sits at the root of virtualenv.pyz , ships as the virtualenv.pyz.cdx.json release asset, and GitHub attests it against the zipapp. ( #3310 )
feat: allow filelock 4.x on Python 3.10+ by @r3wretrhy in #3286
Full Changelog: 21.9.1...21.10.0
Include versioned identities for packages vendored inside seed wheels in the embedded SBOM. ( #3281 )
Allow filelock 4.x on Python 3.10+ by relaxing the upper bound from <4 to <5 - by @r3wretrhy . ( #3285 )
🐛 fix(upgrade): format generated notices by @gaborbernat in #3272
Full Changelog: 21.9.0...21.9.1
Correct SBOM CSV parsing and unresolved dependency relationships, and omit CI run identifiers from reproducible builds. ( #3278 )
✨ feat(build): add SBOM timestamp and generator metadata by @gaborbernat in #3269
Full Changelog: 21.8.1...21.9.0
The embedded SBOM now describes the root component’s license, copyright, maintainers and project links, each bundled wheel from its own metadata, the declared runtime dependencies, and the full build environment (interpreter, OS and every distribution in the isolated build environment with the dependency graph between them), plus the GitHub Actions run when built there. ( #3270 )
🐛 fix(build): make the SBOM serial number deterministic and validate its structure in CI by @gaborbernat in #3268
Full Changelog: 21.8.0...21.8.1
Make the embedded SBOM’s serialNumber a deterministic UUID derived from the package name, version and bundled wheel hashes, so the same source tree produces a byte-identical SBOM, and validate the SBOM’s structure as part of the packaging checks that already run on every pull request. ( #3268 )
📝 docs(security): add an incident response plan by @gaborbernat in #3262
Full Changelog: 21.7.15...21.7.16
Fix activate.csh rendering the venv’s prompt text wrong when it contains ! (csh and tcsh both expand it) or % (tcsh only, since plain csh has no % prompt escape at all). ( #3263 )
🐛 fix(activation): restore empty saved values on deactivate by @gaborbernat in #3259
Full Changelog: 21.7.14...21.7.15
Restore an empty PATH on deactivate in the bash and fish activators, and stop bash leaving the prompt in PS1 when it was unset before activation. ( #3259 )
Fix activate.csh failing to restore PATH and other saved variables on deactivate when PATH was already empty. ( #3260 )
🐛 fix(activation): escape ! for csh history expansion by @gaborbernat in #3256
Full Changelog: 21.7.13...21.7.14
Fix activate.csh failing with Event not found when the virtual environment path contains ! . ( #3256 )
👷 ci: correct a stale checkout pin comment by @gaborbernat in #3254
Full Changelog: 21.7.12...21.7.13
Fix activate and activate.fish running commands embedded in the virtual environment path or in the interpreter’s Tcl/Tk library paths. ( #3252 )
🔧 chore(changelog): drop dead CVE-2026-24049 fragment by @gaborbernat in #3249
Full Changelog: 21.7.11...21.7.12
Fix activate.bat running arbitrary commands from a crafted --prompt , VIRTUALENV_PROMPT , or config file value. ( #3250 )
Verify a downloaded seed wheel’s sha256 against PyPI before seeding it into a virtual environment, skipped when a custom pip index is configured. ( #3251 )
Add OpenSSF Scorecard workflow by @gaborbernat in #3238
Full Changelog: 21.7.10...21.7.11
Running activate.bat again before deactivate no longer makes deactivate leave the environment’s PKG_CONFIG_PATH , TCL_LIBRARY and TK_LIBRARY behind, or lose values the user had set before the first activation - by @darrenhuai . ( #3245 )
Write pyvenv.cfg values on a single line, so a prompt carrying a line boundary can no longer inject configuration. --prompt , the VIRTUALENV_PROMPT environment variable and the config file all set the prompt, and pyvenv.cfg has no escape syntax, so a newline, a carriage return, or any other boundary str.splitlines recognizes, such as U+2028 , started a new configuration line. Reading the file back picked up those lines as keys, and since the last value for a key wins, they replaced anything written earlier, including home . ( #3247 )
🔧 chore: check spelling with typos in pre-commit by @even-even in #3235
Full Changelog: 21.7.9...21.7.10
Skip blank lines, # comments and lines without = in pyvenv.cfg instead of raising ValueError - by @r3wretrhy . ( #3232 )
deactivate in bash, fish and PowerShell unsets PKG_CONFIG_PATH when activation found it unset, instead of keeping the environment’s lib/pkgconfig . csh activation no longer drops a PKG_CONFIG_PATH the user had set. Activation in batch, fish, nushell and PowerShell no longer adds a trailing separator when PKG_CONFIG_PATH is unset, and PowerShell and nushell build the value with the host’s path separators - by @darrenhuai . ( #3233 )
Activation in bash, csh, fish and PowerShell keeps the user’s TCL_LIBRARY and TK_LIBRARY , and deactivate restores them. csh and PowerShell removed both variables on every activation, fish did so when the interpreter has tcl, and bash kept the environment’s value after deactivate when the variable was unset before - by @darrenhuai . ( #3234 )
fix(test): EncodingWarning: 'encoding' argument not specified by @even-even in #3228
Full Changelog: 21.7.8...21.7.9
Replace dangling symlinks, including interpreter aliases, when recreating an environment. This prevents FileExistsError with --symlinks and writes outside the environment with --copies - by @darrenhuai . ( #3229 )
Ignore malformed or unreadable virtualenv.ini files and report the error in the log and --help . Accept a UTF-8 byte order mark, as written by PowerShell 5 and older Notepad versions - by @darrenhuai . ( #3230 )
🐛 fix(create): report a missing source that both modes need by @darrenhuai in #3227
Full Changelog: 21.7.7...21.7.8
A missing source needed by both install modes now disables the builtin creator through meta.error . The check compared RefWhen values against RefMust members, so creation went on to fail with a FileNotFoundError or a dangling symlink - by @darrenhuai . ( #3227 )
📄 docs: document the interpreter names in an environment by @gaborbernat in #3225
Full Changelog: 21.7.6...21.7.7
Bump the python-discovery minimum to >=1.6 for PythonInfo.system_exe , which reports the system interpreter without the nullable typing of system_executable - by @gaborbernat . ( #3224 )
🐛 fix(create): name Windows venv exes after the interpreter by @darrenhuai in #3223
Full Changelog: 21.7.5...21.7.6
On Windows, virtualenv no longer copies the CPython 3.13+ venvlauncher.exe shim into Scripts under the shim’s own name, and a host such as python_d.exe gets its alias back. The alias set took its names from the shim that stands in for the interpreter, so every environment gained a stray launcher copy and lost the interpreter’s own file name - by @darrenhuai . ( #3223 )
🐛 fix(types): adapt to python-discovery 1.5.2 annotations by @gaborbernat in #3211
Full Changelog: 21.7.4...21.7.5
Fix the type check against python-discovery 1.5.2, whose annotations allow a None prefix and integer sysconfig_vars values: config var substitution now skips a missing prefix and locating the shared libpython requires string INSTSONAME / LIBDIR values. ( #3211 )
ExePathRef.can_run now checks the group and other execute bits instead of only the owner one, and returns False rather than None when a file carries none of the three - by @darrenhuai . ( #3217 )
safe_delete no longer passes ignore_errors=True to shutil.rmtree , which replaced its own chmod-and-retry handler with a no-op and swallowed every failure. Read-only files - every file in a wheel image, which set_tree marks - survived, so --reset-app-data and --clear kept trees they reported deleting. The handler now retries only the deletion itself, keeps the other mode bits, and raises the original error for anything it cannot clear - by @darrenhuai . ( #3222 )
Upgrade embedded pip/setuptools/wheel by @github-actions[bot] in #3208
Full Changelog: 21.7.3...21.7.4
Upgrade embedded wheels:
setuptools to 84.0.0 from 83.0.0 ( #3208 )
🐛 fix(config): return a real list from ListType.split_values by @darrenhuai in #3207
Full Changelog: 21.7.2...21.7.3
ListType.split_values now returns a list you can iterate more than once, and accepts bytes input instead of raising TypeError - by @darrenhuai . ( #3207 )
ListType.split_values now returns a list you can iterate more than once, and accepts bytes input instead of raising TypeError - by darrenhuai. (3207)
Upgrade embedded pip/setuptools/wheel by @github-actions[bot] in #3206
Full Changelog: 21.7.1...21.7.2
Upgrade embedded wheels:
pip to 26.2.1 from 26.2 ( #3206 )
📝 docs(branding): clarify official logo vs favicon by @gaborbernat in #3200
Full Changelog: 21.7.0...21.7.1
Upgrade embedded wheels:
pip to 26.2 from 26.1.2 ( #u )
Replace prettier with mdformat and yamlfmt by @gaborbernat in #3190
Full Changelog: 21.6.1...21.7.0
Declare support for Python 3.15: CI now tests against the CPython 3.15 beta, including the free-threaded 3.15t build, and the Programming Language :: Python :: 3.15 classifier is advertised. ( #3192 )
🐛 fix(fish): harden prompt against shadowed builtins by @gaborbernat in #3185
Full Changelog: 21.6.0...21.6.1
Harden the fish activator prompt against user functions that shadow builtins. Routing functions , printf , string , echo and source / . through builtin stops a shadowing function (such as a dot-style directory navigator that redefines . ) from hijacking the prompt and dropping the previous command’s exit status, matching the CPython fix in gh-140006 . ( #3185 )
✨ feat(create): skip distutils hook on Python 3.10+ by @gaborbernat in #3184
Full Changelog: 21.5.2...21.6.0
Stop installing the _virtualenv.{py,pth} distutils import hook for Python 3.10 and later, where pip, setuptools and CPython already ignore the install config keys it guards against; this removes the hook’s startup import cost. The hook is still installed for Python 3.9 - #3181 . ( #3181 )
🐛 fix(seed): sync wheel regen script with seeder guard by @gaborbernat in #3175
Full Changelog: 21.5.1...21.5.2
Upgrade embedded wheels:
setuptools to 83.0.0 ( #3180 )
🐛 fix(seed): refuse to seed unsupported Python versions by @gaborbernat in #3173
Full Changelog: 21.5.0...21.5.1
Refuse to create environments whose Python the bundled wheels no longer cover (currently below 3.9). virtualenv used to substitute the newest bundled pip , which cannot run on such a target, leaving a broken environment; seeder selection now rejects it up front with a clear error. --no-seed and third-party seeders that ship compatible wheels still work - by @gaborbernat . ( #3171 )
Set git identity in upgrade changelog rename step by @gaborbernat in #3169
Full Changelog: 21.4.3...21.5.0
Drop support for Python 3.8; virtualenv now requires Python 3.9 or later to run and to create environments. Remove the embedded wheel seed package, which virtualenv bundled only for Python 3.8. The --wheel and --no-wheel options stay as no-ops, but now warn that virtualenv will remove them in a release after 2026-12 - by @gaborbernat . ( #3170 )
Add wheel-0.47.0 to seed packages as mitigation of CVE-2026-24049 by @apophizzz in https://github.com/pypa/virtualenv/pull/3167
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.3 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.4.2...21.4.3
Upgrade embedded wheels:
pip to 26.1.2 from 26.1.1 ( #u )
Resolve executable-only symlinks when recording home and base-executable in pyvenv.cfg , mirroring CPython’s getpath.realpath (python/cpython#115237), so environments created from a symlink to the interpreter binary locate the base stdlib (for example python-build-standalone); a fully symlinked interpreter tree is kept as-is
by @gaborbernat . ( #3157 )
Stop exporting PS1 from the bash activator so child processes do not inherit shell prompt state. ( #3158 )
Handle CYGWIN/MSYS/MINGW path conversions in fish activation script - by user:: LuNoX . ( #3160 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.2 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.2 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.4.1...21.4.2
Stop deactivate in the bash/zsh activation script from aborting under set -e when hash -r fails (for example with shell hashing disabled) by appending || true , matching CPython venv (gh-149701) and the existing non-deactivate call - by @gaborbernat . ( #3152 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.1 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.1 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.4.0...21.4.1
Fix Windows debug build venvlauncher_d.exe substitution never triggering because executables() compared the source executable name instead of the target name, and fix AttributeError on debug_build attribute for interpreter info objects missing the field - by @gaborbernat . ( #3151 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.0 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.4.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.3.3...21.4.0
Remove dead code targeting Python versions below the supported target range (PyPy 3.6, deprecated importlib APIs) and simplify the runtime import hook in _virtualenv.py - by @gaborbernat . ( #3149 )
Support Windows debug builds ( python_d.exe , venvlauncher_d.exe ) matching CPython venv behavior, remove dead SCRIPT_DIR replacement and has_shim version guard, drop unreachable Python 3.7 branch from pyvenv_launch_patch_active , and fix wheel deprecation message to say >= 3.9 - by @gaborbernat . ( #3150 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.3 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.3 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.3.2...21.3.3
recognize GraalPy interpreters using the normalized GraalPy name - by @timfel . ( #3144 )
No significant changes.
recognize GraalPy interpreters using the normalized GraalPy name - by timfel. (3144)
No significant changes.
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.2 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.2 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.3.1...21.3.2
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.1 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.1 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.3.0...21.3.1
Upgrade embedded wheels:
pip to 26.1.1 from 26.1 ( #3138 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.0 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.3.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.2.4...21.3.0
Re-introduce xonsh shell activator ( activate.xsh ) previously removed in 20.7.0, and make the plugin loader prefer virtualenv’s built-in entry points so a third-party package cannot override them by registering a duplicate name. ( #3003 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.4 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.4 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.2.3...21.2.4
Security hardening: validate each entry of a seed wheel archive before extracting it so a tampered wheel cannot escape the app-data image directory via an absolute path or .. traversal. ( #3118 )
Security hardening: verify the SHA-256 of every bundled seed wheel when it is loaded so a corrupted or tampered file on disk fails loud instead of being handed to pip. The hash table is generated alongside BUNDLE_SUPPORT by tasks/upgrade_wheels.py . ( #3119 )
Security hardening: validate the distribution name and version specifier passed to pip download when acquiring a seed wheel so extras, pip flags, or shell metacharacters cannot be smuggled into the subprocess command line. ( #3120 )
Security hardening: replace the string-prefix containment check in virtualenv.util.zipapp with Path.relative_to so the zipapp extraction helpers refuse any path that does not resolve under the archive root. ( #3121 )
Security hardening: do not silently fall back to an unverified HTTPS context when the periodic update request to PyPI fails TLS verification. The returned metadata drives which wheel version virtualenv considers “up to date”, so accepting an unverified response lets a network-level attacker suppress security updates. Set VIRTUALENV_PERIODIC_UPDATE_INSECURE=1 to restore the previous behavior on hosts with broken trust stores. ( #3122 )
No significant changes.
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.3 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.3 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.2.2...21.2.3
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.2 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.2 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.2.1...21.2.2
Bump python-discovery minimum to >=1.2.2 to include normalize_isa support - by @rahuldevikar . ( #3117 )
Bump python-discovery minimum to >=1.2.2 to include normalize_isa support - by rahuldevikar. (3117)
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.1 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.1 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.2.0...21.2.1
Upgrade embedded wheels:
setuptools to 82.0.1 from 82.0.0 ( #3093 )
Use terminal width for help formatting instead of hardcoded 240. ( #3110 )
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.0 -->
<!-- Release notes generated using configuration in .github/release.yaml at 21.2.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.1.0...21.2.0
Update embed wheel generator ( tasks/upgrade_wheels.py ) to include type annotations in generated output - by @rahuldevikar . ( #3075 )
Update embed wheel generator (tasks/upgrade_wheels.py) to include type annotations in generated output - by rahuldevikar. (3075)
<!-- Release notes generated using configuration in .github/release.yml at 21.1.0 -->
<!-- Release notes generated using configuration in .github/release.yml at 21.1.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/21.0.0...21.1.0
Add comprehensive type annotations across the entire codebase and ship a PEP 561 py.typed marker so downstream consumers and type checkers recognize virtualenv as an inline-typed package - by @rahuldevikar . ( #3075 )
<!-- Release notes generated using configuration in .github/release.yml at 21.0.0 -->
<!-- Release notes generated using configuration in .github/release.yml at 21.0.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.39.1...21.0.0
The Python discovery logic has been extracted into a standalone python-discovery package on PyPI ( documentation ) and is now consumed as a dependency. If you previously imported discovery internals directly (e.g. from virtualenv.discovery.py_info import PythonInfo ), switch to from python_discovery import PythonInfo . Backward-compatibility re-export shims are provided at virtualenv.discovery.py_info , virtualenv.discovery.py_spec , and virtualenv.discovery.cached_py_info , however these are considered unsupported and may be removed in a future release - by @gaborbernat . ( #3070 )
<!-- Release notes generated using configuration in .github/release.yml at 20.39.1 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.39.1 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.39.0...20.39.1
Add support for creating virtual environments with RustPython - by @elmjag . ( #3010 )
Add support for creating virtual environments with RustPython - by elmjag. (3010)
<!-- Release notes generated using configuration in .github/release.yml at 20.39.0 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.39.0 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.38.0...20.39.0
Automatically resolve version manager shims (pyenv, mise, asdf) to the real Python binary during discovery, preventing incorrect interpreter selection when shims are on PATH - by @gaborbernat . ( #3049 )
Add architecture (ISA) awareness to Python discovery — users can now specify a CPU architecture suffix in the --python spec string (e.g. cpython3.12-64-arm64 ) to distinguish between interpreters that share the same version and bitness but target different architectures. Uses sysconfig.get_platform() as the data source, with cross-platform normalization ( amd64 ↔ x86_64 , aarch64 ↔ arm64 ). Omitting the suffix preserves existing behavior - by @rahuldevikar . ( #3059 )
<!-- Release notes generated using configuration in .github/release.yml at 20.38.0 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.38.0 -->
Automated testing documentation section by @elmjag in https://github.com/pypa/virtualenv/pull/3016PKG_CONFIG_PATH environment variable support to all activation scripts by @rahuldevikar in https://github.com/pypa/virtualenv/pull/3023Full Changelog: https://github.com/pypa/virtualenv/compare/20.37.0...20.38.0
Store app data (pip/setuptools/wheel caches) under the OS cache directory ( platformdirs.user_cache_dir ) instead of the data directory ( platformdirs.user_data_dir ). Existing app data at the old location is automatically migrated on first use. This ensures cached files that can be redownloaded are placed in the standard cache location (e.g. ~/.cache on Linux, ~/Library/Caches on macOS) where they are excluded from backups and can be cleaned by system tools - by @rahuldevikar . ( #1884 ) ( #1884 )
Add PKG_CONFIG_PATH environment variable support to all activation scripts (Bash, Batch, PowerShell, Fish, C Shell, Nushell, and Python). The virtualenv’s lib/pkgconfig directory is now automatically prepended to PKG_CONFIG_PATH on activation and restored on deactivation, enabling packages that use pkg-config during build/install to find their configuration files - by @rahuldevikar . ( #2637 )
Upgrade embedded pip to 26.0.1 from 25.3 and setuptools to 82.0.0 , 75.3.4 from 75.3.2 , 80.9.0 - by @rahuldevikar . ( #3027 )
Replace ty: ignore comments with proper type narrowing using assertions and explicit None checks - by @rahuldevikar . ( #3029 )
- Fix TOCTOU vulnerabilities in app_data and lock directory creation that could be exploited via symlink attacks - reported by @tsigouris007 , fixed b…
Fix TOCTOU vulnerabilities in app_data and lock directory creation that could be exploited via symlink attacks - reported by @tsigouris007 , fixed by @gaborbernat . ( #3013 )
Fix TOCTOU vulnerabilities in app_data and lock directory creation that could be exploited via symlink attacks - reported by tsigouris007, fixed by gaborbernat. (3013)
fix: update filelock dependency version to 3.20.1 to fix CVE CVE-2025-68146 by @pythonhubdev in https://github.com/pypa/virtualenv/pull/3002
<!-- Release notes generated using configuration in .github/release.yml at 20.36.0 -->
errno.EMFILE instead of strerror by @pltrz in https://github.com/pypa/virtualenv/pull/3001--python flag. by @rahuldevikar in https://github.com/pypa/virtualenv/pull/3008Full Changelog: https://github.com/pypa/virtualenv/compare/20.35.3...20.36.0
Add support for PEP 440 version specifiers in the --python flag. Users can now specify Python versions using operators like >= , <= , ~= , etc. For example: virtualenv --python=">=3.12" myenv . (:issue:`2994 )
<!-- Release notes generated using configuration in .github/release.yml at 20.35.4 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.35.4 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.35.3...20.35.4
Fix race condition in _virtualenv.py when file is overwritten during import, preventing NameError when _DISTUTILS_PATCH is accessed - by @gracetyy . ( #2969 )
Upgrade embedded wheels:
pip to 25.3 from 25.2 ( #2989 )
<!-- Release notes generated using configuration in .github/release.yml at 20.35.3 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.35.3 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.35.1...20.35.3
Accept RuntimeError in test_too_many_open_files , by @esafak ( #2935 )
Accept RuntimeError in test_too_many_open_files, by esafak (2935)
<!-- Release notes generated using configuration in .github/release.yml at 20.35.2 -->
<!-- Release notes generated using configuration in .github/release.yml at 20.35.2 -->
Full Changelog: https://github.com/pypa/virtualenv/compare/20.35.1...20.35.2
Revert out changes related to the extraction of the discovery module - by @gaborbernat . ( #2978 )
Revert out changes related to the extraction of the discovery module - by gaborbernat. (2978)
Your coding agent can read these notes before it upgrades. Set up the MCP server →