| VIRTUALENV(1) | virtualenv | VIRTUALENV(1) |
NAME
virtualenv - virtualenv 21.1.0 [image: Latest version on PyPI]
[image]
https://pypi.org/project/virtualenv/#history[image: PyPI -
Implementation] [image] [image: PyPI - Python Version] [image] [image:
Documentation status] [image]
https://virtualenv.pypa.io[image: Discord] [image]
https://discord.gg/pypa[image: PyPI - Downloads] [image]
https://pypistats.org/packages/virtualenv[image: PyPI - License]
[image]
https://opensource.org/licenses/MIT[image: Open issues] [image]
https://github.com/pypa/virtualenv/issues[image: Open pull requests]
[image]
https://github.com/pypa/virtualenv/pulls[image: Package popularity]
[image]
https://pypistats.org/packages/virtualenv
virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. For how virtualenv compares to the stdlib venv module, see Explanation <>.
QUICK NAVIGATION
Tutorials - Learn by doing
- •
- Getting started <> — Create your first virtual environment and learn the basic workflow
How-to guides - Solve specific problems
- Install virtualenv <> — Install virtualenv on your system
- Use virtualenv <> — Select Python versions, activate environments, configure defaults, and use from Python code
Reference - Technical information
- Compatibility <> — Supported Python versions and operating systems
- Command line <> — Command line options and flags
- Python <> — Programmatic Python API reference
Explanation - Understand the concepts
- •
- Explanation <> — How virtualenv works under the hood and why it exists
Extensions
- •
- Plugins <> — Extend virtualenv with custom creators, seeders, and activators
RELATED PROJECTS
Several tools build on virtualenv to provide higher-level workflows:
- virtualenvwrapper https://virtualenvwrapper.readthedocs.io/en/latest/ — Shell wrapper for creating and managing multiple virtualenvs
- pew https://github.com/berdario/pew — Python Env Wrapper, a set of commands to manage multiple virtual environments
- tox https://tox.readthedocs.io/en/latest/ — Automate testing across multiple Python versions
- nox https://nox.thea.codes/en/stable/ — Flexible test automation in Python
EXTERNAL RESOURCES
Learn more about virtualenv from these community resources:
- Corey Schafer's virtualenv tutorial https://www.youtube.com/watch?v=N5vscPTWKOk — Video walkthrough for beginners
- Bernat Gabor's status quo https://www.youtube.com/watch?v=o1Vue9CWRxU — Talk about the current state of Python packaging
- Carl Meyer's reverse-engineering http://pyvideo.org/video/568/reverse-engineering-ian-bicking--39-s-brain--insi — Deep dive into how virtualenv works internally
Getting started
This tutorial will teach you the basics of virtualenv through hands-on practice. You'll create your first virtual environment, install packages, and learn how to manage project dependencies.
Prerequisites
Before starting this tutorial, you need:
- Python 3.8 or later installed on your system. If you use a version manager like pyenv https://github.com/pyenv/pyenv, mise https://mise.jdx.dev/, or asdf https://asdf-vm.com/, virtualenv will automatically discover the Python version they manage.
- virtualenv installed (see Install virtualenv <>).
Create your first virtual environment
Let's create a virtual environment called myproject:
$ virtualenv myproject created virtual environment CPython3.13.2.final.0-64 in 200ms creator CPython3Posix(dest=/home/user/myproject, clear=False, no_vcs_ignore=False, global=False) seeder FromAppData(download=False, pip=bundle, setuptools=bundle, via=copy, app_data_dir=/home/user/.cache/virtualenv) activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
This creates a new directory called myproject containing a complete, isolated Python environment with its own copy of Python, pip, and other tools.
Activate the environment
To use your virtual environment, you can activate it. The activation command differs by platform: [Linux/macOS]
$ source myproject/bin/activate
PS> .\myproject\Scripts\Activate.ps1
C:\> .\myproject\Scripts\activate.bat
After activation, your prompt changes to show the active environment:
(myproject) $
You can verify that Python is now running from inside the virtual environment: [Linux/macOS]
(myproject) $ which python /home/user/myproject/bin/python
(myproject) PS> where.exe python C:\Users\user\myproject\Scripts\python.exe
(myproject) C:\> where.exe python C:\Users\user\myproject\Scripts\python.exe
Install a package
With the environment activated, install a package using pip:
(myproject) $ pip install requests Collecting requests Using cached requests-2.32.3-py3-none-any.whl (64 kB) Installing collected packages: requests Successfully installed requests-2.32.3
Verify that the package is installed only inside your virtual environment:
(myproject) $ python -c "import requests; print(requests.__file__)" /home/user/myproject/lib/python3.13/site-packages/requests/__init__.py
The path shows that requests is installed in the virtual environment, not in your system Python.
Deactivate
When you're done working in the virtual environment, deactivate it:
(myproject) $ deactivate $
The prompt returns to normal, and Python commands now use your system Python again.
Use without activation
Activation is a convenience, not a requirement. You can run any executable from the virtual environment directly by using its full path: [Linux/macOS]
$ myproject/bin/python -c "import sys; print(sys.prefix)" /home/user/myproject $ myproject/bin/pip install httpx
PS> .\myproject\Scripts\python.exe -c "import sys; print(sys.prefix)" C:\Users\user\myproject PS> .\myproject\Scripts\pip.exe install httpx
C:\> .\myproject\Scripts\python.exe -c "import sys; print(sys.prefix)" C:\Users\user\myproject C:\> .\myproject\Scripts\pip.exe install httpx
This is especially useful in scripts, CI pipelines, and automation where modifying the shell environment is unnecessary.
Set up a real project
Now let's apply what you've learned to a real project workflow:
$ mkdir myapp && cd myapp $ virtualenv venv $ source venv/bin/activate # or use the appropriate command for your platform (venv) $ pip install flask requests (venv) $ pip freeze > requirements.txt
The requirements.txt file now contains your project's dependencies:
blinker==1.9.0 certifi==2025.1.31 charset-normalizer==3.4.1 click==8.1.8 flask==3.1.0 idna==3.10 itsdangerous==2.2.0 Jinja2==3.1.5 MarkupSafe==3.0.2 requests==2.32.3 urllib3==2.3.0 werkzeug==3.1.3
This file lets you recreate the exact environment later. Let's test this:
(venv) $ deactivate $ rm -rf venv $ virtualenv venv $ source venv/bin/activate (venv) $ pip install -r requirements.txt
All packages are reinstalled exactly as before. Here's the complete workflow: [graph].SS What you learned
In this tutorial, you learned how to:
- Create a virtual environment with virtualenv.
- Activate and deactivate virtual environments on different platforms.
- Install packages in isolation from your system Python.
- Save project dependencies with pip freeze.
- Reproduce environments using requirements.txt.
Next steps
Now that you understand the basics, explore these topics:
- Use virtualenv <> for selecting specific Python versions, configuring defaults, and advanced usage patterns.
- Explanation <> for understanding how virtualenv works under the hood and how it compares to venv.
- Command line <> for all available command line options and flags.
Install virtualenv
virtualenv is a command-line tool, so it should be installed in an isolated environment rather than into your system Python. Pick the method that fits your setup:
- uv https://docs.astral.sh/uv/ -- fast, modern Python package manager. Use this if you already have uv or are starting fresh.
- pipx https://pipx.pypa.io/stable/ -- installs Python CLI tools in isolated environments. Use this if you already have pipx set up.
- pip https://pip.pypa.io/stable/ -- the standard Python package installer. Use --user to avoid modifying system packages. May not work on distributions with externally-managed Python environments.
- zipapp https://docs.python.org/3/library/zipapp.html -- a self-contained executable requiring no installation. Use this in CI or environments where you cannot install packages.
$ uv tool install virtualenv
Install the development version:
$ uv tool install git+https://github.com/pypa/virtualenv.git@main
$ pipx install virtualenv
Install the development version:
$ pipx install git+https://github.com/pypa/virtualenv.git@main
$ python -m pip install --user virtualenv
Install the development version:
$ python -m pip install git+https://github.com/pypa/virtualenv.git@main
Warning:
$ python virtualenv.pyz --help
Download the latest version from https://bootstrap.pypa.io/virtualenv.pyz or a specific version from https://bootstrap.pypa.io/virtualenv/x.y/virtualenv.pyz.
Verify installation
Check the installed version:
$ virtualenv --version
See Compatibility <> for supported Python versions.
Use virtualenv
Select a Python version
By default, virtualenv uses the same Python version it runs under. Override this with --python or -p.
Using version specifiers
Specify a Python version by name or version number:
$ virtualenv -p python3.8 venv $ virtualenv -p 3.10 venv $ virtualenv -p pypy3 venv $ virtualenv -p rustpython venv
Using PEP 440 specifiers
Use PEP 440 https://peps.python.org/pep-0440/#version-specifiers version specifiers to match Python versions:
$ virtualenv --python ">=3.12" venv $ virtualenv --python "~=3.11.0" venv $ virtualenv --python "cpython>=3.10" venv
- >=3.12 -- any Python 3.12 or later.
- ~=3.11.0 -- compatible release, equivalent to >=3.11.0, <3.12.0 (any 3.11.x patch).
- cpython>=3.10 -- restrict to CPython implementation, 3.10 or later.
Using free-threading Python
Create an environment with free-threading Python https://docs.python.org/3/howto/free-threading-python.html:
$ virtualenv -p 3.13t venv
Targeting a specific CPU architecture
On machines that support multiple architectures — such as Apple Silicon (arm64 + x86_64 via Rosetta) or Windows on ARM — you can request a specific CPU architecture by appending it to the spec string:
$ virtualenv -p cpython3.12-64-arm64 venv $ virtualenv -p 3.11-64-x86_64 venv
Cross-platform aliases are normalized automatically, so amd64 and x86_64 are treated as equivalent, as are aarch64 and arm64. If omitted, any architecture matches (preserving existing behavior).
Using absolute paths
Specify the full path to a Python interpreter:
$ virtualenv -p /usr/bin/python3.9 venv
Using --try-first-with
Use --try-first-with to provide a hint about which Python to check first. Unlike --python, this is a hint rather than a rule. The interpreter at this path is checked first, but only used if it matches the --python constraint.
$ virtualenv --python ">=3.10" --try-first-with /usr/bin/python3.9 venv
In this example, /usr/bin/python3.9 is checked first but rejected because it does not satisfy the >=3.10 constraint.
Using version managers (pyenv, mise, asdf)
virtualenv automatically resolves shims from pyenv https://github.com/pyenv/pyenv, mise https://mise.jdx.dev/, and asdf https://asdf-vm.com/ to the real Python binary. Set the active Python version using any of the standard mechanisms and virtualenv will discover it:
$ pyenv local 3.12.0 $ virtualenv venv # uses pyenv's 3.12.0, not the system Python $ PYENV_VERSION=3.11.0 virtualenv venv # uses 3.11.0
This also works with mise and asdf:
$ mise use python@3.12 $ virtualenv venv
No additional configuration is required. See Explanation <> for details on how shim resolution works.
Activate a virtual environment
Activate the environment to modify your shell's PATH and environment variables. [Bash/Zsh]
$ source venv/bin/activate
$ source venv/bin/activate.fish
PS> .\venv\Scripts\Activate.ps1
Note:
> .\venv\Scripts\activate.bat
$ overlay use venv/bin/activate.nu
Deactivate the environment
Exit the virtual environment:
$ deactivate
Use without activation
Use the environment without activating it by calling executables with their full paths:
$ venv/bin/python script.py $ venv/bin/pip install package
Customize prompt
Set a custom prompt prefix:
$ virtualenv --prompt myproject venv
Disable the prompt modification by setting the VIRTUAL_ENV_DISABLE_PROMPT environment variable.
Access the prompt string via the VIRTUAL_ENV_PROMPT environment variable.
Programmatic activation
Activate the environment from within a running Python process using activate_this.py. This modifies sys.path and environment variables in the current process so that subsequent imports resolve from the virtual environment.
import runpy
runpy.run_path("venv/bin/activate_this.py")
A common use case is web applications served by a system-wide WSGI server (such as mod_wsgi or uWSGI) that need to load packages from a virtual environment:
import runpy
from pathlib import Path
runpy.run_path(str(Path("/var/www/myapp/venv/bin/activate_this.py")))
from myapp import create_app # noqa: E402
application = create_app()
Configure defaults
Use a configuration file to set default options for virtualenv.
Configuration file location
The configuration file is named virtualenv.ini and located in the platformdirs app config directory. Run virtualenv --help to see the exact location for your system.
Override the location with the VIRTUALENV_CONFIG_FILE environment variable.
Configuration format
Derive configuration keys from command-line options by stripping leading - and replacing remaining - with _:
[virtualenv] python = /opt/python-3.8/bin/python
Multi-value options
Specify multiple values on separate lines:
[virtualenv]
extra_search_dir =
/path/to/dists
/path/to/other/dists
Environment variables
Set options using environment variables with the VIRTUALENV_ prefix and uppercase key names:
$ export VIRTUALENV_PYTHON=/opt/python-3.8/bin/python
For multi-value options, separate values with commas or newlines.
Override app-data location
Set the VIRTUALENV_OVERRIDE_APP_DATA environment variable to override the default app-data cache directory location.
Configuration priority
Options are resolved in this order (highest to lowest priority): [graph].SS Control seed packages
Upgrade embedded wheels
Update the embedded wheel files to the latest versions:
$ virtualenv --upgrade-embed-wheels
Provide custom wheels
Use custom wheel files from a local directory:
$ virtualenv --extra-search-dir /path/to/wheels venv
Download latest from PyPI
Download the latest versions of seed packages from PyPI:
$ virtualenv --download venv
Disable periodic updates
Disable automatic periodic updates of seed packages:
$ virtualenv --no-periodic-update venv
For distribution maintainers
Patch the virtualenv.seed.wheels.embed module and set PERIODIC_UPDATE_ON_BY_DEFAULT to False to disable periodic updates by default. See Explanation <> for implementation details.
Use from Python code
Call virtualenv from Python code using the cli_run function:
from virtualenv import cli_run cli_run(["venv"])
Pass options as list elements:
cli_run(["-p", "python3.8", "--without-pip", "myenv"])
Use the returned session object to access environment details:
result = cli_run(["venv"]) print(result.creator.dest) # path to created environment print(result.creator.exe) # path to python executable
Use session_via_cli to describe the environment without creating it:
from virtualenv import session_via_cli session = session_via_cli(["venv"]) # inspect session.creator, session.seeder, session.activators
See Python <> for complete API documentation.
Compatibility
Supported Python implementations
virtualenv works with the following Python interpreter implementations. Only the latest patch version of each minor version is fully supported; previous patch versions work on a best effort basis.
CPython
3.14 >= python_version >= 3.8
PyPy
3.11 >= python_version >= 3.8
GraalPy
24.1 and later (Linux and macOS only).
RustPython
Experimental support (Linux, macOS, and Windows). RustPython https://github.com/RustPython/RustPython implements Python 3.14.
Support policy
- New versions are added close to their release date, typically during the beta phase.
- Old versions are dropped 18 months after CPython EOL https://devguide.python.org/versions/, giving users plenty of time to migrate.
Version support timeline
Major version support changes:
- 20.27.0 (2024-10-17): dropped support for running under Python 3.7 and earlier.
- 20.22.0 (2023-04-19): dropped support for creating environments for Python 3.6 and earlier.
- 20.18.0 (2023-02-06): dropped support for running under Python 3.6 and earlier.
Supported operating systems
CPython is shipped in multiple forms, and each OS repackages it, often applying some customization. The platforms listed below are tested. Unlisted platforms may work but are not explicitly supported. If you encounter issues on unlisted platforms, please open a feature request.
Cross-platform
These Python distributions work on Linux, macOS, and Windows:
- Installations from python.org https://www.python.org/downloads/
- python-build-standalone https://github.com/astral-sh/python-build-standalone builds (used by uv https://docs.astral.sh/uv/ and mise https://mise.jdx.dev/)
- Python versions managed by pyenv https://github.com/pyenv/pyenv, mise https://mise.jdx.dev/, or asdf https://asdf-vm.com/ (shims are automatically resolved to the real binary)
Linux
- Ubuntu 16.04 and later (both upstream and deadsnakes https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa builds)
- Fedora
- RHEL and CentOS
- OpenSuse
- Arch Linux
macOS
- Python versions installed via Homebrew https://docs.brew.sh/Homebrew-and-Python (works, but not recommended https://justinmayer.com/posts/homebrew-python-is-not-for-you/ -- Homebrew may upgrade or remove Python versions without warning, breaking existing virtual environments)
- Python 3 part of XCode (Python framework builds at /Library/Frameworks/Python3.framework/)
Note:
Windows
- •
- Windows Store https://apps.microsoft.com/search?query=python Python 3.8 and later
Command line
virtualenv is primarily a command line application. All options have sensible defaults, and there is one required argument: the name or path of the virtual environment to create.
See Use virtualenv <> for how to select Python versions, configure defaults, and use environment variables.
Command line options
virtualenv [OPTIONS]
| Named Arguments | ||
| --version | '==SUPPRESS==' | display the version of the virtualenv package and its location, then exit |
| --with-traceback | False | on failure also display the stacktrace internals of virtualenv |
| --read-only-app-data | False | use app data folder in read-only mode (write operations will fail with error) |
| --app-data | platform specific application data folder | a data folder used as cache by the virtualenv |
| --reset-app-data | False | start with empty app data folder |
| --upgrade-embed-wheels | False | trigger a manual update of the embedded wheels |
| verbosity ⇒ verbosity = verbose - quiet, default INFO, mapping => CRITICAL=0, ERROR=1, WARNING=2, INFO=3, DEBUG=4, NOTSET=5 | ||
| -v, --verbose | 2 | increase verbosity |
| -q, --quiet | 0 | decrease verbosity |
discovery
| core ⇒ options shared across all discovery | ||
| --discovery | 'builtin' | interpreter discovery method; choice of: builtin |
| -p, --python | the python executable virtualenv is installed into | interpreter based on what to create environment (path/identifier/version-specifier) - by default use the interpreter where the tool is installed - first found wins. Version specifiers (e.g., >=3.12, ~=3.11.0, ==3.10) are also supported |
| --try-first-with | [] | try first these interpreters before starting the discovery |
creator
| core ⇒ options shared across all creator | ||
| --creator | builtin if exist, else venv | create environment via; choice of: cpython3-mac-brew, cpython3-mac-framework, cpython3-posix, cpython3-win, graalpy-posix, graalpy-win, pypy3-posix, pypy3-win, rustpython-posix, rustpython-win, venv |
| dest | directory to create virtualenv at | |
| --clear | False | remove the destination directory if exist before starting (will overwrite files otherwise) |
| --no-vcs-ignore | False | don't create VCS ignore directive in the destination directory |
| --system-site-packages | False | give the virtual environment access to the system site-packages dir |
| --symlinks | True | try to use symlinks rather than copies, when symlinks are not the default for the platform |
| --copies, --always-copy | False | try to use copies rather than symlinks, even when symlinks are the default for the platform |
seeder
| core ⇒ options shared across all seeder | ||
| --seeder | 'app-data' | seed packages install method; choice of: app-data, pip |
| --no-seed, --without-pip | False | do not install seed packages |
| --no-download, --never-download | True | pass to disable download of the latest pip/setuptools/wheel from PyPI |
| --download | False | pass to enable download of the latest pip/setuptools/wheel from PyPI |
| --extra-search-dir | [] | a path containing wheels to extend the internal wheel list (can be set 1+ times) |
| --pip | 'bundle' | version of pip to install as seed: embed, bundle, none or exact version |
| --setuptools | 'none' | version of setuptools to install as seed: embed, bundle, none or exact version |
| --no-pip | False | do not install pip |
| --no-setuptools | False | do not install setuptools |
| --no-periodic-update | False | disable the periodic (once every 14 days) update of the embedded wheels |
| app-data ⇒ options specific to seeder app-data | ||
| --symlink-app-data | False | symlink the python packages from the app-data folder (requires seed pip>=19.3) |
activators
| core ⇒ options shared across all activators | ||
| --activators | comma separated list of activators supported | activators to generate - default is all supported; choice of: bash, batch, cshell, fish, nushell, powershell, python, xonsh |
| --prompt | provides an alternative prompt prefix for this environment (value of . means name of the current working directory) |
Python
The primary interface to virtualenv is the command line application. However, it can also be used programmatically via the virtualenv.cli_run function and the Session class.
See Use virtualenv <> for usage examples.
virtualenv module
- virtualenv.cli_run(args, options=None, setup_logging=True, env=None)
- Create a virtual environment given some command line interface arguments.
- args (list https://docs.python.org/3/library/stdtypes.html#list[str https://docs.python.org/3/library/stdtypes.html#str]) -- the command line arguments
- options (VirtualEnvOptions | None https://docs.python.org/3/library/constants.html#None) -- passing in a VirtualEnvOptions object allows return of the parsed options
- setup_logging (bool https://docs.python.org/3/library/functions.html#bool) -- True if setup logging handlers, False to use handlers already registered
- env (MutableMapping https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping[str https://docs.python.org/3/library/stdtypes.html#str, str https://docs.python.org/3/library/stdtypes.html#str] | None https://docs.python.org/3/library/constants.html#None) -- environment variables to use
- Return type
- Session
- Returns
- the session object of the creation (its structure for now is experimental and might change on short notice)
- virtualenv.session_via_cli(args, options=None, setup_logging=True, env=None)
- Create a virtualenv session (same as cli_run, but this does not perform the creation). Use this if you just want to query what the virtual environment would look like, but not actually create it.
- args (list https://docs.python.org/3/library/stdtypes.html#list[str https://docs.python.org/3/library/stdtypes.html#str]) -- the command line arguments
- options (VirtualEnvOptions | None https://docs.python.org/3/library/constants.html#None) -- passing in a VirtualEnvOptions object allows return of the parsed options
- setup_logging (bool https://docs.python.org/3/library/functions.html#bool) -- True if setup logging handlers, False to use handlers already registered
- env (MutableMapping https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping[str https://docs.python.org/3/library/stdtypes.html#str, str https://docs.python.org/3/library/stdtypes.html#str] | None https://docs.python.org/3/library/constants.html#None) -- environment variables to use
- Return type
- Session
- Returns
- the session object of the creation (its structure for now is experimental and might change on short notice)
Session class
The Session class represents a virtualenv creation session and provides access to the created environment's properties.
- class virtualenv.run.session.Session(verbosity, app_data, interpreter, creator, seeder, activators)
- Represents a virtual environment creation session.
- verbosity (int https://docs.python.org/3/library/functions.html#int)
- app_data (AppData <#virtualenv.app_data.base.AppData>)
- interpreter (PythonInfo <#virtualenv.discovery.py_info.PythonInfo>)
- creator (Creator <#virtualenv.create.creator.Creator>)
- seeder (Seeder <#virtualenv.seed.seeder.Seeder>)
- activators (list https://docs.python.org/3/library/stdtypes.html#list[Activator <#virtualenv.activation.activator.Activator>])
- property verbosity: int <https://docs.python.org/3/library/functions.html#int>
- The verbosity of the run.
- property interpreter: PythonInfo <#virtualenv.discovery.py_info.PythonInfo>
- Create a virtual environment based on this reference interpreter.
- property creator: Creator <#virtualenv.create.creator.Creator>
- The creator used to build the virtual environment (must be compatible with the interpreter).
- property seeder: Seeder <#virtualenv.seed.seeder.Seeder>
- The mechanism used to provide the seed packages (pip, setuptools, wheel).
- property activators: list <https://docs.python.org/3/library/stdtypes.html#list>[Activator <#virtualenv.activation.activator.Activator>]
- Activators used to generate activations scripts.
VirtualEnvOptions
Options namespace passed to plugin constructors, populated from the CLI, environment variables, and configuration files.
- set_src(key, value, src)
- Set an option value and record where it came from.
- key (str https://docs.python.org/3/library/stdtypes.html#str) -- the option name
- value (Any https://docs.python.org/3/library/typing.html#typing.Any) -- the option value
- src (str https://docs.python.org/3/library/stdtypes.html#str) -- the source of the value (e.g. "cli", "env var", "default")
- get_source(key)
- Return the source that provided a given option value.
- Parameters
- key (str https://docs.python.org/3/library/stdtypes.html#str) -- the option name
- Return type
- str https://docs.python.org/3/library/stdtypes.html#str | None https://docs.python.org/3/library/constants.html#None
- Returns
- the source string (e.g. "cli", "env var", "default"), or None if not tracked
- property verbosity: int <https://docs.python.org/3/library/functions.html#int> | None <https://docs.python.org/3/library/constants.html#None>
- The verbosity level, computed as verbose - quiet, clamped to zero.
- Returns
- the verbosity level, or None if neither --verbose nor --quiet has been parsed yet
Explanation
This page explains the design decisions and concepts behind virtualenv. It focuses on understanding why things work the way they do.
virtualenv vs venv vs uv
Since Python 3.3, the standard library includes the venv module, which provides basic virtual environment creation following PEP 405 https://www.python.org/dev/peps/pep-0405/. uv https://docs.astral.sh/uv/pip/environments/ is a newer, Rust-based tool that also creates virtual environments via uv venv.
virtualenv occupies a middle ground: faster and more featureful than venv, while remaining a pure Python solution with a plugin system for extensibility.
| venv | virtualenv | uv https://docs.astral.sh/uv/ | |
| Performance | Slowest (60s+); spawns pip https://pip.pypa.io as a subprocess to seed. | Fast; caches pre-built install images, subsequent creation < 1 second. | Fastest; Rust implementation, milliseconds. Does not seed pip/setuptools by default. |
| Extensibility | No plugin system. | Plugin system for discovery, creation, seeding, and activation. | No plugin system. |
| Cross-version | Only the Python version it runs under. | Any installed Python via auto-discovery (registry, uv-managed, PATH). | Any installed or uv-managed Python. |
| Upgradeability | Tied to Python releases. | Independent via PyPI https://pypi.org/project/virtualenv/. | Independent via its own release cycle. |
| Programmatic API | Basic create() function only. | Full Python API; can describe environments without creating them. Used by tox https://tox.readthedocs.io, poetry https://python-poetry.org/, pipx https://pipx.pypa.io, etc. | Command line only. |
| Type annotations | No py.typed marker; limited annotations. | Fully typed with PEP 561 https://peps.python.org/pep-0561/ py.typed marker; checked by ty https://docs.astral.sh/ty/. | Not applicable (Rust binary). |
| Best for | Zero dependencies, basic needs. | Plugin extensibility, programmatic API, tool compatibility (tox https://tox.readthedocs.io, virtualenvwrapper https://virtualenvwrapper.readthedocs.io). | Maximum speed, already using uv for package management. |
Python packaging often faces a fundamental problem: different applications require different versions of the same library. If Application A needs requests==2.25.1 but Application B needs requests==2.28.0, installing both into the global site-packages directory creates a conflict. Only one version can exist in a given location.
virtualenv solves this by creating isolated Python environments. Each environment has its own installation directories and can maintain its own set of installed packages, independent of other environments and the system Python.
virtualenv operates in two distinct phases: [graph].INDENT 0.0
- Phase 1: Discover a Python interpreter
- virtualenv first identifies which Python interpreter to use as the template for the virtual environment. By default, it uses the same Python version that virtualenv itself is running on. You can override this with the --python flag to specify a different interpreter.
- Phase 2: Create the virtual environment
- Once the target interpreter is identified, virtualenv creates the environment in four steps:
- 1.
- Create a Python executable matching the target interpreter
- 2.
- Install seed packages (pip, setuptools, wheel) to enable package installation
- 3.
- Install activation scripts for various shells
- 4.
- Create VCS ignore files (currently Git's .gitignore, skip with --no-vcs-ignore)
An important design principle: virtual environments are not self-contained. A complete Python installation consists of thousands of files, and copying all of them into every virtual environment would be wasteful. Instead, virtual environments are lightweight shells that borrow most content from the system Python. They contain only what's needed to redirect Python's behavior.
This design has two implications:
- Environment creation is fast because only a small number of files need to be created.
- Upgrading the system Python might affect existing virtual environments, since they reference the system Python's standard library and binary extensions.
The Python executable in a virtual environment is effectively isolated from the one used to create it, but the supporting files are shared.
Warning:
Python discovery
Before creating a virtual environment, virtualenv must locate a Python interpreter. The interpreter determines the virtual environment's Python version, implementation (CPython, PyPy, etc.), and architecture (32-bit or 64-bit).
The --python flag accepts several specifier formats:
- Path specifier
- An absolute or relative path to a Python executable, such as /usr/bin/python3.8 or ./python.
- Version specifier
- A string following the format {implementation}{version}{architecture}{machine} where:
- Implementation is alphabetic characters (python means any implementation; if omitted, defaults to python).
- Version is dot-separated numbers, optionally followed by t for free-threading builds.
- Architecture is -64 or -32 (if omitted, means any architecture).
- Machine is the CPU instruction set architecture, e.g. -arm64, -x86_64, -aarch64 (if omitted, means any machine). Cross-platform aliases are normalized automatically (amd64 ↔ x86_64, aarch64 ↔ arm64).
Examples:
- python3.8.1 - Any Python implementation with version 3.8.1
- 3 - Any Python implementation with major version 3
- 3.13t - Any Python implementation version 3.13 with free-threading enabled
- cpython3 - CPython implementation with major version 3
- pypy2 - PyPy implementation with major version 2
- cpython3.12-64-arm64 - CPython 3.12, 64-bit, ARM64 architecture
- 3.11-64-x86_64 - Any implementation, version 3.11, 64-bit, x86_64 architecture
- rustpython - RustPython implementation
- PEP 440 version specifier
- Version constraints using PEP 440 operators:
- >=3.12 - Any Python 3.12 or later
- ~=3.11.0 - Compatible with Python 3.11.0
- cpython>=3.10 - CPython 3.10 or later
When you provide a specifier, virtualenv searches for matching interpreters using this strategy: [graph].INDENT 0.0
- 1.
- Windows Registry (Windows only): Check registered Python installations per PEP 514 https://www.python.org/dev/peps/pep-0514/.
- 2.
- uv-managed installations: Check the UV_PYTHON_INSTALL_DIR environment variable or platform-specific uv Python directories for managed Python installations.
- 3.
- PATH search: Search for executables on the PATH environment variable with names matching the specification.
Version manager shim resolution
Version managers like pyenv https://github.com/pyenv/pyenv, mise https://mise.jdx.dev/, and asdf https://asdf-vm.com/ place lightweight shim scripts on PATH that delegate to the real Python binary. When virtualenv discovers a Python interpreter by running it as a subprocess, shims may resolve to the wrong Python version (typically the system Python) because the shim's resolution logic depends on shell environment state that doesn't fully propagate to child processes.
virtualenv detects shims by checking whether the candidate executable lives in a known shim directory ($PYENV_ROOT/shims, $MISE_DATA_DIR/shims, or $ASDF_DATA_DIR/shims). When a shim is detected, virtualenv bypasses it and locates the real binary directly under the version manager's versions directory, using the active version from:
- 1.
- The PYENV_VERSION environment variable (colon-separated for multiple versions).
- 2.
- A .python-version file in the current directory or any parent directory.
- 3.
- The global version file at $PYENV_ROOT/version.
This convention is shared across pyenv, mise, and asdf, so the same resolution logic works for all three.
Warning:
If you use a virtual environment's Python as the target for creating another virtual environment, virtualenv will detect the system Python version and create an environment matching the actual (upgraded) version, not the version reported by the virtual environment.
Creators
Creators are responsible for constructing the virtual environment structure. virtualenv supports two types of creators:
- venv creator
- This creator delegates the entire creation process to the standard library's venv module, following PEP 405 https://www.python.org/dev/peps/pep-0405/. The venv creator has two limitations:
- It only works with Python 3.5 or later.
- It requires spawning a subprocess to invoke the venv module, unless virtualenv is installed in the system Python.
The subprocess overhead can be significant, especially on Windows where process creation is expensive.
- builtin creator
- This creator means virtualenv performs the creation itself by knowing
exactly which files to create and which system files to reference. The
builtin creator is actually a family of specialized creators for different
combinations of Python implementation (CPython, PyPy, GraalPy, RustPython)
and platform (Windows, POSIX). The name builtin is an alias that
selects the first available builtin creator for the target environment.
Because builtin creators don't require subprocess invocation, they're generally faster than the venv creator.
virtualenv defaults to using the builtin creator if one is available for the target environment, falling back to the venv creator otherwise.
Seeders
After creating the virtual environment structure, virtualenv installs seed packages that enable package management within the environment. The seed packages are:
- pip - The package installer for Python (always installed).
- setuptools - Package development and installation library (disabled by default on Python 3.12+).
- wheel - Support for the wheel binary package format (only installed by default on Python 3.8).
virtualenv supports two seeding methods with dramatically different performance characteristics:
- pip seeder
- This method uses the bundled pip wheel to install seed packages by spawning a child pip process. The subprocess performs a full installation, including unpacking wheels and generating metadata. This method is reliable but slow, typically consuming 98% of the total virtual environment creation time.
- app-data seeder
- This method creates reusable install images in a user application data
directory. The first time you create an environment with specific seed
package versions, the app-data seeder builds complete install images and
stores them in the cache. Subsequent environment creations simply link or
copy these pre-built images into the virtual environment's
site-packages directory.
Performance comparison for creating virtual environments: [graph]
On platforms that support symlinks efficiently (Linux, macOS), the app-data seeder provides nearly instant seeding.
You can override the cache location using the VIRTUALENV_OVERRIDE_APP_DATA environment variable.
Wheel acquisition
Both seeding methods require wheel files for the seed packages. virtualenv acquires wheels using a priority system: [graph].INDENT 0.0
- Embedded wheels
- virtualenv ships with a set of wheels bundled directly into the package. These are tested with the virtualenv release and provide a baseline set of seed packages. Different Python versions require different package versions, so virtualenv bundles multiple wheels to support its wide Python version range.
- Upgraded embedded wheels
- Users can manually upgrade the embedded wheels by running virtualenv with
the --upgrade-embed-wheels flag. This fetches newer versions of
seed packages from PyPI and stores them in the user application data
directory. Subsequent virtualenv invocations will use these upgraded
wheels instead of the embedded ones.
virtualenv can also perform periodic automatic upgrades (see below).
- Extra search directories
- Users can specify additional directories containing wheels using the --extra-search-dir flag. This is useful in air-gapped environments or when using custom package builds.
- PyPI download
- If no suitable wheel is found in the above locations, or if the --download flag is set, virtualenv will use pip to download the latest compatible version from PyPI.
Periodic update mechanism
To keep the seed packages reasonably current without requiring users to manually upgrade virtualenv or run --upgrade-embed-wheels, virtualenv implements a periodic automatic update system: [graph]
The 28-day waiting period protects users from automatically adopting newly released packages that might contain bugs. The 1-hour delay after download ensures continuous integration systems don't start using different package versions mid-run, which could cause confusing test failures.
You can disable the periodic update mechanism with the --no-periodic-update flag.
Distribution maintainer patching
Operating system distributions and package managers sometimes need to customize which seed package versions virtualenv uses. They want to align virtualenv's bundled packages with system package versions.
Distributions can patch the virtualenv.seed.wheels.embed module, replacing the get_embed_wheel function with their own implementation that returns distribution-provided wheels. If they want to use virtualenv's test suite for validation, they should also provide the BUNDLE_FOLDER, BUNDLE_SUPPORT, and MAX variables.
Distributions should also consider patching virtualenv.seed.embed.base_embed.PERIODIC_UPDATE_ON_BY_DEFAULT to False, allowing the system package manager to control seed package updates rather than virtualenv's periodic update mechanism. Users can still manually request upgrades via --upgrade-embed-wheels, but automatic updates won't interfere with system-managed packages.
Activators
Activation scripts modify the current shell environment to prioritize the virtual environment's executables. This is purely a convenience mechanism - you can always use absolute paths to virtual environment executables without activating.
What activation does: [graph].INDENT 0.0
- PATH modification
- The activation script prepends the virtual environment's bin directory (Scripts on Windows) to the PATH environment variable. This ensures that when you run python, pip, or other executables, the shell finds the virtual environment's versions first.
- Environment variables
- Activation sets several environment variables:
- VIRTUAL_ENV - Absolute path to the virtual environment directory.
- VIRTUAL_ENV_PROMPT - The prompt prefix (the environment name or custom value from --prompt).
- PKG_CONFIG_PATH - Modified to include the virtual environment's lib/pkgconfig directory.
- Prompt modification
- By default, activation prepends the environment name to your shell prompt, typically shown as (venv) before the regular prompt. This visual indicator helps you remember which environment is active. You can customize this with the --prompt flag when creating the environment, or disable it entirely by setting the VIRTUAL_ENV_DISABLE_PROMPT environment variable.
- Deactivation
- Activation scripts also provide a deactivate command that reverses the changes, restoring your original PATH and removing the environment variables and prompt modifications.
virtualenv provides activation scripts for multiple shells:
- Bash https://www.gnu.org/software/bash/ (activate)
- Fish https://fishshell.com/ (activate.fish)
- Csh/Tcsh https://www.tcsh.org/ (activate.csh)
- PowerShell https://learn.microsoft.com/en-us/powershell/ (activate.ps1)
- Windows Batch https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd (activate.bat)
- Nushell https://www.nushell.sh/ (activate.nu)
- Python (activate_this.py) -- for programmatic activation from within a running Python process, see Programmatic activation <#programmatic-activation>
Note:
Set-ExecutionPolicy RemoteSigned
Since virtualenv generates activate.ps1 locally for each environment, PowerShell considers it a local script rather than a remote one and allows execution under the RemoteSigned policy.
Remember: activation is optional. The following commands are equivalent:
# With activation source venv/bin/activate python script.py deactivate # Without activation venv/bin/python script.py
For a deeper dive into how activation works under the hood, see Allison Kaptur's blog post There's no magic: virtualenv edition https://www.recurse.com/blog/14-there-is-no-magic-virtualenv-edition, which explains how virtualenv uses PATH and PYTHONHOME to isolate virtual environments.
See also
- Use virtualenv <> - Practical guides for common virtualenv tasks.
- Command line <> - Complete CLI reference documentation.
Plugins
virtualenv can be extended via plugins using Python entry points. Plugins are automatically discovered from the Python environment where virtualenv is installed, allowing you to customize how virtual environments are created, seeded, and activated.
Extension points
virtualenv provides four extension points through entry point groups:
- virtualenv.discovery
- Python interpreter discovery plugins. These plugins locate and identify Python interpreters that will be used as the base for creating virtual environments.
- virtualenv.create
- Virtual environment creator plugins. These plugins handle the actual creation of the virtual environment structure, including copying or symlinking the Python interpreter and standard library.
- virtualenv.seed
- Seed package installer plugins. These plugins install initial packages (like pip, setuptools, wheel) into newly created virtual environments.
- virtualenv.activate
- Shell activation script plugins. These plugins generate shell-specific activation scripts that modify the environment to use the virtual environment.
All extension points follow a common pattern: virtualenv discovers registered entry points, builds CLI options from them, and executes the selected implementations during environment creation.
Your first plugin
This tutorial walks through creating a simple discovery plugin that locates Python interpreters managed by pyenv.
Create the package structure
Set up a new Python package with the following structure:
virtualenv-pyenv/
├── pyproject.toml
└── src/
└── virtualenv_pyenv/
└── __init__.py
Configure the entry point
In pyproject.toml, declare your plugin as an entry point under the virtualenv.discovery group:
[project] name = "virtualenv-pyenv" version = "0.1.0" dependencies = ["virtualenv>=20"] [project.entry-points."virtualenv.discovery"] pyenv = "virtualenv_pyenv:PyEnvDiscovery" [build-system] requires = ["setuptools>=61"] build-backend = "setuptools.build_meta"
Implement the plugin
In src/virtualenv_pyenv/__init__.py, implement the discovery plugin by subclassing Discover:
from __future__ import annotations
import subprocess
from pathlib import Path
from virtualenv.discovery.discover import Discover
from virtualenv.discovery.py_info import PythonInfo
class PyEnvDiscovery(Discover):
def __init__(self, options):
super().__init__(options)
self.python_spec = options.python if options.python else "python"
@classmethod
def add_parser_arguments(cls, parser):
parser.add_argument(
"--python",
dest="python",
metavar="py",
type=str,
default=None,
help="pyenv Python version to use (e.g., 3.11.0)",
)
def run(self):
try:
result = subprocess.run(
["pyenv", "which", "python"],
capture_output=True,
text=True,
check=True,
)
python_path = Path(result.stdout.strip())
return PythonInfo.from_exe(str(python_path))
except (subprocess.CalledProcessError, FileNotFoundError) as e:
raise RuntimeError(f"Failed to locate pyenv Python: {e}")
Install the plugin
Install your plugin in development mode alongside virtualenv:
$ pip install -e virtualenv-pyenv/
Verify the plugin
Check that virtualenv recognizes your plugin by running:
$ virtualenv --discovery help
The output should list pyenv as an available discovery mechanism. You can now use it:
$ virtualenv --discovery=pyenv myenv
created virtual environment CPython3.11.0.final.0-64 in 234ms
creator CPython3Posix(dest=/path/to/myenv, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/path)
added seed packages: pip==23.0, setuptools==65.5.0, wheel==0.38.4
activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
Plugin how-to guides
This page provides task-oriented guides for creating each type of virtualenv plugin.
Create a discovery plugin
Discovery plugins locate Python interpreters. Register your plugin under the virtualenv.discovery entry point group.
Implement the Discover interface:
from virtualenv.discovery.discover import Discover
from virtualenv.discovery.py_info import PythonInfo
class CustomDiscovery(Discover):
@classmethod
def add_parser_arguments(cls, parser):
parser.add_argument("--custom-opt", help="custom discovery option")
def __init__(self, options):
super().__init__(options)
self.custom_opt = options.custom_opt
def run(self):
# Locate Python interpreter and return PythonInfo
python_exe = self._find_python()
return PythonInfo.from_exe(str(python_exe))
def _find_python(self):
# Implementation-specific logic
pass
Register the entry point:
[virtualenv.discovery] custom = your_package.discovery:CustomDiscovery
Create a creator plugin
Creator plugins build the virtual environment structure. Register under virtualenv.create.
Implement the Creator interface:
from virtualenv.create.creator import Creator
class CustomCreator(Creator):
@classmethod
def add_parser_arguments(cls, parser, interpreter):
parser.add_argument("--custom-creator-opt", help="custom creator option")
def __init__(self, options, interpreter):
super().__init__(options, interpreter)
self.custom_opt = options.custom_creator_opt
def create(self):
# Create directory structure
self.bin_dir.mkdir(parents=True, exist_ok=True)
# Copy or symlink Python executable
self.install_python()
# Set up site-packages
self.install_site_packages()
# Write pyvenv.cfg
self.set_pyenv_cfg()
Register the entry point using a naming pattern that matches platform and Python version:
[virtualenv.create] cpython3-posix = virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Posix cpython3-win = virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Windows
Create a seeder plugin
Seeder plugins install initial packages into the virtual environment. Register under virtualenv.seed.
Implement the Seeder interface:
from virtualenv.seed.seeder import Seeder
class CustomSeeder(Seeder):
@classmethod
def add_parser_arguments(cls, parser, interpreter, app_data):
parser.add_argument("--custom-seed-opt", help="custom seeder option")
def __init__(self, options, enabled, app_data):
super().__init__(options, enabled, app_data)
self.custom_opt = options.custom_seed_opt
def run(self, creator):
# Install packages into creator.bin_dir / creator.script("pip")
self._install_packages(creator)
def _install_packages(self, creator):
# Implementation-specific logic
pass
Register the entry point:
[virtualenv.seed] custom = your_package.seed:CustomSeeder
Create an activator plugin
Activator plugins generate shell activation scripts. Register under virtualenv.activate.
Implement the Activator interface:
from virtualenv.activation.activator import Activator
class CustomShellActivator(Activator):
def generate(self, creator):
# Generate activation script content
script_content = self._render_template(creator)
# Write to activation directory
dest = creator.bin_dir / self.script_name
dest.write_text(script_content)
def _render_template(self, creator):
# Return activation script content
return f"""
# Custom shell activation script
export VIRTUAL_ENV="{creator.dest}"
export PATH="{creator.bin_dir}:$PATH"
"""
@property
def script_name(self):
return "activate.custom"
Register the entry point:
[virtualenv.activate] bash = virtualenv.activation.bash:BashActivator fish = virtualenv.activation.fish:FishActivator custom = your_package.activation:CustomShellActivator
Package and distribute a plugin
Use pyproject.toml to declare entry points:
[project] name = "virtualenv-custom-plugin" version = "1.0.0" dependencies = ["virtualenv>=20.0.0"] [project.entry-points."virtualenv.discovery"] custom = "virtualenv_custom.discovery:CustomDiscovery" [project.entry-points."virtualenv.create"] custom-posix = "virtualenv_custom.creator:CustomCreator" [project.entry-points."virtualenv.seed"] custom = "virtualenv_custom.seeder:CustomSeeder" [project.entry-points."virtualenv.activate"] custom = "virtualenv_custom.activator:CustomActivator" [build-system] requires = ["setuptools>=61"] build-backend = "setuptools.build_meta"
Install your plugin alongside virtualenv:
$ pip install virtualenv-custom-plugin
Or in development mode:
$ pip install -e /path/to/virtualenv-custom-plugin
Test your plugin by creating a virtual environment:
$ virtualenv --discovery=custom --creator=custom-posix --seeder=custom --activators=custom test-env
Plugin API reference
This page documents the interfaces that plugins must implement.
Discovery
Discovery plugins locate Python interpreters for creating virtual environments.
- Parameters
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>)
- Return type
- PythonInfo | None https://docs.python.org/3/library/constants.html#None
- Returns
- the interpreter as returned by run(), cached
PythonInfo
Discovery plugins return a PythonInfo object describing the located interpreter.
- class virtualenv.discovery.py_info.PythonInfo
- Contains information for a Python interpreter.
- install_path(key)
- Return the relative installation path for a given installation scheme key.
- property version_str: str <https://docs.python.org/3/library/stdtypes.html#str>
- The full version as major.minor.micro string (e.g. 3.13.2).
- property version_release_str: str <https://docs.python.org/3/library/stdtypes.html#str>
- The release version as major.minor string (e.g. 3.13).
- property python_name: str <https://docs.python.org/3/library/stdtypes.html#str>
- The python executable name as pythonX.Y (e.g. python3.13).
- property is_old_virtualenv: bool <https://docs.python.org/3/library/functions.html#bool>
- True if this interpreter runs inside an old-style virtualenv (has real_prefix).
- property is_venv: bool <https://docs.python.org/3/library/functions.html#bool>
- True if this interpreter runs inside a PEP 405 venv (has base_prefix).
- sysconfig_path(key, config_var=None, sep='/')
- Return the sysconfig install path for a scheme key, optionally substituting config variables.
- key (str https://docs.python.org/3/library/stdtypes.html#str)
- config_var (dict https://docs.python.org/3/library/stdtypes.html#dict[str https://docs.python.org/3/library/stdtypes.html#str, str https://docs.python.org/3/library/stdtypes.html#str] | None https://docs.python.org/3/library/constants.html#None)
- sep (str https://docs.python.org/3/library/stdtypes.html#str)
- property system_include: str <https://docs.python.org/3/library/stdtypes.html#str>
- The path to the system include directory for C headers.
- property system_prefix: str <https://docs.python.org/3/library/stdtypes.html#str>
- The prefix of the system Python this interpreter is based on.
- property system_exec_prefix: str <https://docs.python.org/3/library/stdtypes.html#str>
- The exec prefix of the system Python this interpreter is based on.
- property machine: str <https://docs.python.org/3/library/stdtypes.html#str>
- Return the instruction set architecture (ISA) derived from sysconfig.get_platform() https://docs.python.org/3/library/sysconfig.html#sysconfig.get_platform.
- property spec: str <https://docs.python.org/3/library/stdtypes.html#str>
- A specification string identifying this interpreter (e.g. CPython3.13.2-64-arm64).
- classmethod clear_cache(cache)
- Clear all cached interpreter information from cache.
- Parameters
- cache (PyInfoCache)
- Return type
- None https://docs.python.org/3/library/constants.html#None
- satisfies(spec, *, impl_must_match)
- Check if a given specification can be satisfied by this python interpreter instance.
- spec (PythonSpec)
- impl_must_match (bool https://docs.python.org/3/library/functions.html#bool)
- classmethod current(cache=None)
- Locate the current host interpreter information.
- Parameters
- cache (PyInfoCache | None https://docs.python.org/3/library/constants.html#None)
- Return type
- PythonInfo
- classmethod current_system(cache=None)
- Locate the current system interpreter information, resolving through any virtualenv layers.
- Parameters
- cache (PyInfoCache | None https://docs.python.org/3/library/constants.html#None)
- Return type
- PythonInfo
- classmethod from_exe(exe, cache=None, *, raise_on_error=True, ignore_cache=False, resolve_to_host=True, env=None)
- Get the python information for a given executable path.
- exe (str https://docs.python.org/3/library/stdtypes.html#str)
- cache (PyInfoCache | None https://docs.python.org/3/library/constants.html#None)
- raise_on_error (bool https://docs.python.org/3/library/functions.html#bool)
- ignore_cache (bool https://docs.python.org/3/library/functions.html#bool)
- resolve_to_host (bool https://docs.python.org/3/library/functions.html#bool)
- env (Mapping https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping[str https://docs.python.org/3/library/stdtypes.html#str, str https://docs.python.org/3/library/stdtypes.html#str] | None https://docs.python.org/3/library/constants.html#None)
- Return type
- PythonInfo | None https://docs.python.org/3/library/constants.html#None
- Parameters
- payload (str https://docs.python.org/3/library/stdtypes.html#str)
- Return type
- PythonInfo
- cache (PyInfoCache | None https://docs.python.org/3/library/constants.html#None)
- target (PythonInfo)
- Return type
- PythonInfo
- discover_exe(cache, prefix, *, exact=True, env=None)
- Discover a matching Python executable under a given prefix directory.
- cache (PyInfoCache)
- prefix (str https://docs.python.org/3/library/stdtypes.html#str)
- exact (bool https://docs.python.org/3/library/functions.html#bool)
- env (Mapping https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping[str https://docs.python.org/3/library/stdtypes.html#str, str https://docs.python.org/3/library/stdtypes.html#str] | None https://docs.python.org/3/library/constants.html#None)
- Return type
- PythonInfo
App data
The application data interface used by plugins for caching.
- class virtualenv.app_data.base.AppData
- Abstract storage interface for the virtualenv application.
- abstractmethod close()
- Called before virtualenv exits.
- abstractmethod reset()
- Called when the user passes in the reset app data.
- abstractmethod py_info(path)
- Return a content store for cached interpreter information at the given path.
- Parameters
- path (Path https://docs.python.org/3/library/pathlib.html#pathlib.Path) -- the interpreter executable path
- Return type
- ContentStore
- Returns
- a content store for the cached data
- abstractmethod py_info_clear()
- Clear all cached interpreter information.
- property can_update: bool <https://docs.python.org/3/library/functions.html#bool>
- True if this app data store supports updating cached content.
- abstractmethod embed_update_log(distribution, for_py_version)
- Return a content store for the embed update log of a distribution.
- distribution (str https://docs.python.org/3/library/stdtypes.html#str) -- the package name (e.g. pip)
- for_py_version (str https://docs.python.org/3/library/stdtypes.html#str) -- the target Python version string
- Return type
- ContentStore
- Returns
- a content store for the update log
- property house: Path <https://docs.python.org/3/library/pathlib.html#pathlib.Path>
- The root directory of the application data store.
- property transient: bool <https://docs.python.org/3/library/functions.html#bool>
- True if this app data store is transient and does not persist across runs.
- abstractmethod wheel_image(for_py_version, name)
- Return the path to a cached wheel image.
- for_py_version (str https://docs.python.org/3/library/stdtypes.html#str) -- the target Python version string
- name (str https://docs.python.org/3/library/stdtypes.html#str) -- the package name
- Return type
- Path https://docs.python.org/3/library/pathlib.html#pathlib.Path
- Returns
- the path to the cached wheel
- ensure_extracted(path, to_folder=None)
- Ensure a path is available on disk, extracting from zipapp if needed.
- path (Path https://docs.python.org/3/library/pathlib.html#pathlib.Path) -- the path to ensure is available
- to_folder (Path https://docs.python.org/3/library/pathlib.html#pathlib.Path | None https://docs.python.org/3/library/constants.html#None) -- optional target directory for extraction
- Return type
- Generator https://docs.python.org/3/library/collections.abc.html#collections.abc.Generator[Path https://docs.python.org/3/library/pathlib.html#pathlib.Path]
- Returns
- yields the usable path on disk
- abstractmethod extract(path, to_folder)
- Extract a path from the zipapp to a location on disk.
- path (Path https://docs.python.org/3/library/pathlib.html#pathlib.Path) -- the path to extract
- to_folder (Path https://docs.python.org/3/library/pathlib.html#pathlib.Path | None https://docs.python.org/3/library/constants.html#None) -- optional target directory
- Return type
- Generator https://docs.python.org/3/library/collections.abc.html#collections.abc.Generator[Path https://docs.python.org/3/library/pathlib.html#pathlib.Path]
- Returns
- yields the extracted path
- abstractmethod locked(path)
- Acquire an exclusive lock on the given path.
Creators
Creator plugins build the virtual environment directory structure and install the Python interpreter.
- class virtualenv.create.creator.Creator(options, interpreter)
- A class that given a python Interpreter creates a virtual environment.
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>)
- interpreter (PythonInfo)
Construct a new virtual environment creator.
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>) -- the CLI option as parsed from add_parser_arguments()
- interpreter (PythonInfo) -- the interpreter to create virtual environment from
- classmethod can_create(interpreter)
- Determine if we can create a virtual environment.
- Parameters
- interpreter (PythonInfo) -- the interpreter in question
- Return type
- CreatorMeta | None https://docs.python.org/3/library/constants.html#None
- Returns
- None if we can't create, any other object otherwise that will be forwarded to add_parser_arguments()
- classmethod add_parser_arguments(parser, interpreter, meta, app_data)
- Add CLI arguments for the creator.
- parser (ArgumentParser https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser) -- the CLI parser
- app_data (AppData) -- the application data folder
- interpreter (PythonInfo) -- the interpreter we're asked to create virtual environment for
- meta (CreatorMeta) -- value as returned by can_create()
- abstractmethod create()
- Perform the virtual environment creation.
- add_cachedir_tag()
- Generate a file indicating that this is not meant to be backed up.
- setup_ignore_vcs()
- Generate ignore instructions for version control systems.
Seeders
Seeder plugins install initial packages (like pip, setuptools, wheel) into the virtual environment.
- class virtualenv.seed.seeder.Seeder(options, enabled)
- A seeder will install some seed packages into a virtual environment.
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>)
- enabled (bool https://docs.python.org/3/library/functions.html#bool)
Create.
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>) -- the parsed options as defined within add_parser_arguments()
- enabled (bool https://docs.python.org/3/library/functions.html#bool) -- a flag weather the seeder is enabled or not
- classmethod add_parser_arguments(parser, interpreter, app_data)
- Add CLI arguments for this seed mechanisms.
- parser (ArgumentParser https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser) -- the CLI parser
- app_data (AppData) -- the CLI parser
- interpreter (PythonInfo) -- the interpreter this virtual environment is based of
- abstractmethod run(creator)
- Perform the seed operation.
- Parameters
- creator (Creator) -- the creator (based of virtualenv.create.creator.Creator) we used to create this virtual environment
- Return type
- None https://docs.python.org/3/library/constants.html#None
Activators
Activator plugins generate shell-specific activation scripts.
- class virtualenv.activation.activator.Activator(options)
- Generates activate script for the virtual environment.
- Parameters
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>)
Create a new activator generator.
- Parameters
- options (VirtualEnvOptions <#virtualenv.config.cli.parser.VirtualEnvOptions>) -- the parsed options as defined within add_parser_arguments()
- classmethod supports(interpreter)
- Check if the activation script is supported in the given interpreter.
- Parameters
- interpreter (PythonInfo) -- the interpreter we need to support
- Return type
- bool https://docs.python.org/3/library/functions.html#bool
- Returns
- True if supported, False otherwise
- classmethod add_parser_arguments(parser, interpreter)
- Add CLI arguments for this activation script.
- parser (ArgumentParser https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser) -- the CLI parser
- interpreter (PythonInfo) -- the interpreter this virtual environment is based of
- abstractmethod generate(creator)
- Generate activate script for the given creator.
- Parameters
- creator (Creator) -- the creator (based of virtualenv.create.creator.Creator) we used to create this virtual environment
- Return type
- list https://docs.python.org/3/library/stdtypes.html#list[Path https://docs.python.org/3/library/pathlib.html#pathlib.Path]
Plugin architecture
This page explains how virtualenv's plugin system works internally.
Entry points
virtualenv uses Python entry points (setuptools / importlib.metadata) to discover plugins. Each plugin registers under one of four entry point groups:
- virtualenv.discovery
- virtualenv.create
- virtualenv.seed
- virtualenv.activate
At startup, virtualenv loads all registered entry points from these groups and makes them available as CLI options. Built-in implementations are registered in virtualenv's own pyproject.toml, while third-party plugins register their entry points in their own package metadata.
When a package with virtualenv plugins is installed in the same environment as virtualenv, the plugins become immediately available without additional configuration.
Plugin lifecycle
The following diagram shows how plugins are discovered and executed: [graph]
The lifecycle follows these stages:
- 1.
- virtualenv starts and discovers all entry points from the four plugin groups
- 2.
- The CLI parser is built dynamically, incorporating options from all discovered plugins
- 3.
- User arguments are parsed to select which discovery, creator, seeder, and activator plugins to use
- 4.
- Selected plugins execute in sequence: discover → create → seed → activate
- 5.
- Each stage passes its output to the next stage
Extension point design
Each extension point follows a consistent pattern:
- Base abstract class
- Each extension point defines a base abstract class (Discover, Creator, Seeder, Activator) that specifies the interface plugins must implement.
- Built-in implementations
- virtualenv includes built-in implementations registered as entry points in its own pyproject.toml. For example, the built-in CPython creator is registered as cpython3-posix.
- Third-party plugins
- External packages implement the base interface and register their own entry points under the same group. When installed, they appear alongside built-in options.
- CLI selection
- Command-line flags (--discovery, --creator, --seeder, --activators) allow users to select which implementation to use. Multiple activators can be selected simultaneously.
- Parser integration
- Each plugin can contribute CLI arguments through the add_parser_arguments classmethod. These arguments appear in virtualenv --help and are available when the plugin is selected.
How plugins interact
Plugins execute in a pipeline where each stage depends on the previous one:
- Discovery → Creator
- The discovery plugin produces a PythonInfo object describing the source Python interpreter. This object contains metadata about the Python version, platform, paths, and capabilities. The creator plugin receives this PythonInfo and uses it to determine how to build the virtual environment structure.
- Creator → Seeder
- The creator plugin produces a Creator object representing the newly created virtual environment. This includes paths to the environment's bin directory, site-packages, and Python executable. The seeder plugin uses these paths to install packages.
- Seeder → Activator
- After seeding completes, activator plugins use the Creator object to generate shell activation scripts. These scripts reference the environment's bin directory and other paths to configure the shell environment.
This pipeline ensures that each plugin has the information it needs from previous stages. The PythonInfo flows from discovery to creator, and the Creator object flows from creator to both seeder and activators.
Plugin isolation
Plugins within the same extension point do not interact with each other. Only one discovery and one creator plugin can run per invocation, though multiple activators can run simultaneously. This isolation keeps plugins simple and focused on their specific task.
Development
Getting started
virtualenv is a volunteer maintained open source project and we welcome contributions of all forms. The sections below will help you get started with development, testing, and documentation. We’re pleased that you are interested in working on virtualenv. This document is meant to get you setup to work on virtualenv and to act as a guide and reference to the development setup. If you face any issues during this process, please open an issue https://github.com/pypa/virtualenv/issues/new?title=Trouble+with+development+environment about it on the issue tracker.
Setup
virtualenv is a command line application written in Python. To work on it, you'll need:
- •
git clone https://github.com/pypa/virtualenv cd virtualenv
- Python interpreter: We recommend using CPython. You can use this guide https://realpython.com/installing-python/ to set it up.
- tox https://pypi.org/project/tox: to automatically get the projects development dependencies and run the test suite. We recommend installing it using pipx https://pipxproject.github.io/pipx/.
Running from source tree
The easiest way to do this is to generate the development tox environment, and then invoke virtualenv from under the .tox/dev folder
tox -e dev .tox/dev/bin/virtualenv # on Linux .tox/dev/Scripts/virtualenv # on Windows
Running tests
virtualenv's tests are written using the pytest https://pypi.org/project/pytest test framework. tox https://pypi.org/project/tox is used to automate the setup and execution of virtualenv's tests.
To run tests locally execute:
tox -e py
This will run the test suite for the same Python version as under which tox is installed. Alternatively you can specify a specific version of python by using the pyNN format, such as: py38, pypy3, etc.
tox has been configured to forward any additional arguments it is given to pytest. This enables the use of pytest's rich CLI https://docs.pytest.org/en/latest/usage.html#specifying-tests-selecting-tests. As an example, you can select tests using the various ways that pytest provides:
# Using markers tox -e py -- -m "not slow" # Using keywords tox -e py -- -k "test_extra"
Some tests require additional dependencies to be run, such is the various shell activators (bash, fish, powershell, etc). These tests will automatically be skipped if these are not present, note however that in CI all tests are run; so even if all tests succeed locally for you, they may still fail in the CI.
Running linters
virtualenv uses pre-commit https://pypi.org/project/pre-commit for managing linting of the codebase. pre-commit performs various checks on all files in virtualenv and uses tools that help follow a consistent code style within the codebase. To use linters locally, run:
tox -e fix
Note:
Type checking
virtualenv ships a PEP 561 https://peps.python.org/pep-0561/ py.typed marker and has comprehensive type annotations across the entire codebase. This means downstream consumers and type checkers automatically recognize virtualenv as an inline-typed package.
All new code must include complete type annotations for function parameters and return types. To verify annotations locally, run:
tox -e type
This uses ty https://docs.astral.sh/ty/ (Astral's Rust-based type checker) to validate annotations against Python 3.14. A second environment checks compatibility with the minimum supported version:
tox -e type-3.8
Both environments validate that annotations are consistent and correct.
Annotation guidelines
- Use from __future__ import annotations at the top of every module (enforced by ruff's required-imports setting).
- Place imports that are only needed for type checking inside an if TYPE_CHECKING: block to avoid runtime overhead.
- Ruff's ANN rules are enabled. ANN401 (typing.Any) is suppressed on a case-by-case basis with inline # noqa: ANN401 comments where Any is genuinely required (e.g. serialization, dynamic dispatch).
- Prefer concrete types over Any. Use Union / | for nullable or multi-type parameters.
- When a type error is genuinely unfixable (e.g. third-party library limitations), suppress it with an inline # ty: ignore[rule-name] comment and a brief justification.
Building documentation
virtualenv's documentation is built using Sphinx https://pypi.org/project/Sphinx. The documentation is written in reStructuredText. To build it locally, run:
tox -e docs
The built documentation can be found in the .tox/docs_out folder and may be viewed by opening index.html within that folder.
Release
virtualenv's release schedule is tied to pip and setuptools. We bundle the latest version of these libraries so each time there's a new version of any of these, there will be a new virtualenv release shortly afterwards (we usually wait just a few days to avoid pulling in any broken releases).
Performing a release
A full release publishes to PyPI https://pypi.org/project/virtualenv/, creates a GitHub Release https://github.com/pypa/virtualenv/releases with the zipapp attached, and updates get-virtualenv https://github.com/pypa/get-virtualenv so that https://bootstrap.pypa.io/virtualenv.pyz serves the new version.
Version bumping
The --version argument to tox r -e release controls the version. It defaults to auto, which inspects the docs/changelog directory: if any *.feature.rst or *.removal.rst fragments exist, the minor version is bumped, otherwise the patch version is bumped. You can also pass major, minor, or patch explicitly.
Both methods produce identical results: a release commit and tag on main. Pushing the tag triggers the Release workflow https://github.com/pypa/virtualenv/actions/workflows/release.yaml which builds the sdist, wheel, and zipapp, publishes to PyPI via trusted publisher, creates a GitHub Release https://github.com/pypa/virtualenv/releases with the zipapp attached, and updates get-virtualenv https://github.com/pypa/get-virtualenv. If publish fails, a rollback job automatically reverts everything.
Via GitHub Actions (recommended)
- 1.
- Go to the Pre-release workflow https://github.com/pypa/virtualenv/actions/workflows/pre-release.yaml on GitHub.
- 2.
- Click Run workflow and select the bump type (auto, major, minor, or patch).
Locally
tox r -e release
Pass --version <bump> to override the default auto behavior (e.g. --version minor).
Contributing
Submitting pull requests
Submit pull requests against the main branch, providing a good description of what you're doing and why. You must have legal permission to distribute any code you contribute to virtualenv and it must be available under the MIT License. Provide tests that cover your changes and run the tests locally first. virtualenv supports <#compatibility-requirements> multiple Python versions and operating systems. Any pull request must consider and work on all these platforms.
Pull Requests should be small to facilitate review. Keep them self-contained, and limited in scope. Studies have shown https://www.kessler.de/prd/smartbear/BestPracticesForPeerCodeReview.pdf that review quality falls off as patch size grows. Sometimes this will result in many small PRs to land a single large feature. In particular, pull requests must not be treated as "feature branches", with ongoing development work happening within the PR. Instead, the feature should be broken up into smaller, independent parts which can be reviewed and merged individually.
Additionally, avoid including "cosmetic" changes to code that is unrelated to your change, as these make reviewing the PR more difficult. Examples include re-flowing text in comments or documentation, or addition or removal of blank lines or whitespace within lines. Such changes can be made separately, as a "formatting cleanup" PR, if needed.
Automated testing
All pull requests and merges to 'main' branch are tested using GitHub Actions https://docs.github.com/en/actions (configured by .github/workflows/check.yaml file at the root of the repository). You can find the status and results to the CI runs for your PR on GitHub's Web UI for the pull request. You can also find links to the CI services' pages for the specific builds in the form of "Details" links, in case the CI run fails and you wish to view the output.
To trigger CI to run again for a pull request, you can close and open the pull request or submit another change to the pull request. If needed, project maintainers can manually trigger a restart of a job/build.
NEWS entries
The changelog.rst file is managed using towncrier https://pypi.org/project/towncrier and all non trivial changes must be accompanied by a news entry. To add an entry to the news file, first you need to have created an issue describing the change you want to make. A Pull Request itself may function as such, but it is preferred to have a dedicated issue (for example, in case the PR ends up rejected due to code quality reasons).
Once you have an issue or pull request, you take the number and you create a file inside of the docs/changelog directory named after that issue number with an extension of:
- feature.rst,
- bugfix.rst,
- doc.rst,
- removal.rst,
- misc.rst.
Thus if your issue or PR number is 1234 and this change is fixing a bug, then you would create a file docs/changelog/1234.bugfix.rst. PRs can span multiple categories by creating multiple files (for instance, if you added a feature and deprecated/removed the old feature at the same time, you would create docs/changelog/1234.bugfix.rst and docs/changelog/1234.remove.rst). Likewise if a PR touches multiple issues/PRs you may create a file for each of them with the same contents and towncrier https://pypi.org/project/towncrier will deduplicate them.
Contents of a NEWS entry
The contents of this file are reStructuredText formatted text that will be used as the content of the news file entry. You do not need to reference the issue or PR numbers here as towncrier will automatically add a reference to all of the affected issues when rendering the news file.
In order to maintain a consistent style in the changelog.rst file, it is preferred to keep the news entry to the point, in sentence case, shorter than 120 characters and in an imperative tone -- an entry should complete the sentence This change will …. In rare cases, where one line is not enough, use a summary line in an imperative tone followed by a blank line separating it from a description of the feature/change in one or more paragraphs, each wrapped at 120 characters. Remember that a news entry is meant for end users and should only contain details relevant to an end user.
Choosing the type of NEWS entry
A trivial change is anything that does not warrant an entry in the news file. Some examples are: code refactors that don't change anything as far as the public is concerned, typo fixes, white space modification, etc. To mark a PR as trivial a contributor simply needs to add a randomly named, empty file to the news/ directory with the extension of .trivial.
Becoming a maintainer
If you want to become an official maintainer, start by helping out. As a first step, we welcome you to triage issues on virtualenv's issue tracker. virtualenv maintainers provide triage abilities to contributors once they have been around for some time and contributed positively to the project. This is optional and highly recommended for becoming a virtualenv maintainer. Later, when you think you're ready, get in touch with one of the maintainers and they will initiate a vote among the existing maintainers.
Note:
- GitHub Push Access
- PyPI Publishing Access
- CI Administration capabilities
- ReadTheDocs Administration capabilities
Release History
v[UNRELEASED DRAFT] (2026-02-28)
No significant changes.
v21.1.0 (2026-02-27)
Features - 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 https://github.com/rahuldevikar. (#3075 https://github.com/pypa/virtualenv/issues/3075)
v21.0.0 (2026-02-25)
Deprecations and Removals - 21.0.0
- •
- The Python discovery logic has been extracted into a standalone python-discovery package on PyPI (documentation https://python-discovery.readthedocs.io/) 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 https://github.com/gaborbernat. (#3070 https://github.com/pypa/virtualenv/issues/3070)
v20.39.1 (2026-02-25)
Features - 20.39.1
- •
- Add support for creating virtual environments with RustPython - by @elmjag https://github.com/elmjag. (#3010 https://github.com/pypa/virtualenv/issues/3010)
v20.39.0 (2026-02-23)
Features - 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 https://github.com/gaborbernat. (#3049 https://github.com/pypa/virtualenv/issues/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 https://github.com/rahuldevikar. (#3059 https://github.com/pypa/virtualenv/issues/3059)
v20.38.0 (2026-02-19)
Features - 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 https://github.com/rahuldevikar. (#1884 https://github.com/pypa/virtualenv/issues/1884) (#1884 https://github.com/pypa/virtualenv/issues/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 https://github.com/rahuldevikar. (#2637 https://github.com/pypa/virtualenv/issues/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 https://github.com/rahuldevikar. (#3027 https://github.com/pypa/virtualenv/issues/3027)
- Replace ty: ignore comments with proper type narrowing using assertions and explicit None checks - by @rahuldevikar https://github.com/rahuldevikar. (#3029 https://github.com/pypa/virtualenv/issues/3029)
Bugfixes - 20.38.0
- Exclude pywin32 DLLs (pywintypes*.dll, pythoncom*.dll) from being copied to the Scripts directory during virtualenv creation on Windows. This fixes compatibility issues with pywin32, which expects its DLLs to be installed in site-packages/pywin32_system32 by its own post-install script - by @rahuldevikar https://github.com/rahuldevikar. (#2662 https://github.com/pypa/virtualenv/issues/2662)
- Preserve symlinks in pyvenv.cfg paths to match venv behavior. Use os.path.abspath() instead of os.path.realpath() to normalize paths without resolving symlinks, fixing issues with Python installations accessed via symlinked directories (common in network-mounted filesystems) - by @rahuldevikar https://github.com/rahuldevikar. Fixes #2770 https://github.com/pypa/virtualenv/issues/2770. (#2770 https://github.com/pypa/virtualenv/issues/2770)
- Fix Windows activation scripts to properly quote python.exe path, preventing failures when Python is installed in a path with spaces (e.g., C:\Program Files) and a file named C:\Program exists on the filesystem - by @rahuldevikar https://github.com/rahuldevikar. (#2985 https://github.com/pypa/virtualenv/issues/2985)
- Fix bash -u (set -o nounset) compatibility in bash activation script by using ${PKG_CONFIG_PATH:-} and ${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} to handle unset PKG_CONFIG_PATH - by @Fridayai700 https://github.com/Fridayai700. (#3044 https://github.com/pypa/virtualenv/issues/3044)
- Gracefully handle corrupted on-disk cache and invalid JSON from Python interrogation subprocess instead of crashing with unhandled JSONDecodeError or KeyError - by @gaborbernat https://github.com/gaborbernat. (#3054 https://github.com/pypa/virtualenv/issues/3054)
v20.36.1 (2026-01-09)
Bugfixes - 20.36.1
- •
- Fix TOCTOU vulnerabilities in app_data and lock directory creation that could be exploited via symlink attacks - reported by @tsigouris007 https://github.com/tsigouris007, fixed by @gaborbernat https://github.com/gaborbernat. (#3013 https://github.com/pypa/virtualenv/issues/3013)
v20.36.0 (2026-01-07)
Features - 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)
v20.35.4 (2025-10-28)
Bugfixes - 20.35.4
- Fix race condition in _virtualenv.py when file is overwritten during import, preventing NameError when _DISTUTILS_PATCH is accessed - by @gracetyy https://github.com/gracetyy. (#2969 https://github.com/pypa/virtualenv/issues/2969)
- Upgrade embedded wheels:
- •
- pip to 25.3 from 25.2 (#2989 https://github.com/pypa/virtualenv/issues/2989)
v20.35.3 (2025-10-10)
Bugfixes - 20.35.3
- •
- Accept RuntimeError in test_too_many_open_files, by @esafak https://github.com/esafak (#2935 https://github.com/pypa/virtualenv/issues/2935)
v20.35.2 (2025-10-10)
Bugfixes - 20.35.2
- •
- Revert out changes related to the extraction of the discovery module - by @gaborbernat https://github.com/gaborbernat. (#2978 https://github.com/pypa/virtualenv/issues/2978)
v20.35.1 (2025-10-09)
Bugfixes - 20.35.1
- Patch get_interpreter to handle missing cache and app_data - by @esafak https://github.com/esafak (#2972 https://github.com/pypa/virtualenv/issues/2972)
- Fix backwards incompatible changes to PythonInfo - by @gaborbernat https://github.com/gaborbernat. (#2975 https://github.com/pypa/virtualenv/issues/2975)
v20.35.0 (2025-10-08)
Features - 20.35.0
- Add AppData and Cache protocols to discovery for decoupling - by @esafak https://github.com/esafak. (#2074 https://github.com/pypa/virtualenv/issues/2074)
- Ensure python3.exe and python3 on Windows for Python 3 - by @esafak https://github.com/esafak. (#2774 https://github.com/pypa/virtualenv/issues/2774)
Bugfixes - 20.35.0
- Replaced direct references to tcl/tk library paths with getattr - by @esafak https://github.com/esafak (#2944 https://github.com/pypa/virtualenv/issues/2944)
- Restore absolute import of fs_is_case_sensitive - by @esafak https://github.com/esafak. (#2955 https://github.com/pypa/virtualenv/issues/2955)
v20.34.0 (2025-08-13)
Features - 20.34.0
- Abstract out caching in discovery - by @esafak https://github.com/esafak. Decouple FileCache from py_info (discovery) - by @esafak https://github.com/esafak. Remove references to py_info in FileCache - by @esafak https://github.com/esafak. Decouple discovery from creator plugins - by @esafak https://github.com/esafak. Decouple discovery by duplicating info utils - by @esafak https://github.com/esafak. (#2074 https://github.com/pypa/virtualenv/issues/2074)
- Add PyPy 3.11 support. Contributed by @esafak https://github.com/esafak. (#2932 https://github.com/pypa/virtualenv/issues/2932)
Bugfixes - 20.34.0
- Upgrade embedded wheel pip to 25.2 from 25.1.1 - by @gaborbernat https://github.com/gaborbernat. (#2333 https://github.com/pypa/virtualenv/issues/2333)
- Accept RuntimeError in test_too_many_open_files, by @esafak https://github.com/esafak (#2935 https://github.com/pypa/virtualenv/issues/2935)
- Python in PATH takes precedence over uv-managed python. Contributed by @edgarrmondragon https://github.com/edgarrmondragon. (#2952 https://github.com/pypa/virtualenv/issues/2952)
v20.33.1 (2025-08-05)
Bugfixes - 20.33.1
- Correctly unpack _get_tcl_tk_libs() response in PythonInfo. Contributed by @esafak https://github.com/esafak. (#2930 https://github.com/pypa/virtualenv/issues/2930)
- Restore py_info.py timestamp in test_py_info_cache_invalidation_on_py_info_change Contributed by @esafak https://github.com/esafak. (#2933 https://github.com/pypa/virtualenv/issues/2933)
v20.33.0 (2025-08-03)
Features - 20.33.0
- •
- Added support for Tcl and Tkinter. You're welcome. Contributed by @esafak https://github.com/esafak. (#425 https://github.com/pypa/virtualenv/issues/425)
Bugfixes - 20.33.0
- Prevent logging setup when --help is passed, fixing a flaky test. Contributed by @esafak https://github.com/esafak. (#u https://github.com/pypa/virtualenv/issues/u)
- Fix cache invalidation for PythonInfo by hashing py_info.py. Contributed by @esafak https://github.com/esafak. (#2467 https://github.com/pypa/virtualenv/issues/2467)
- When no discovery plugins are found, the application would crash with a StopIteration. This change catches the StopIteration and raises a RuntimeError with a more informative message. Contributed by @esafak https://github.com/esafak. (#2493 https://github.com/pypa/virtualenv/issues/2493)
- Stop --try-first-with overriding absolute --python paths. Contributed by @esafak https://github.com/esafak. (#2659 https://github.com/pypa/virtualenv/issues/2659)
- Force UTF-8 encoding for pip download Contributed by @esafak https://github.com/esafak. (#2780 https://github.com/pypa/virtualenv/issues/2780)
- Creating a virtual environment on a filesystem without symlink-support would fail even with --copies Make fs_supports_symlink perform a real symlink creation check on all platforms. Contributed by @esafak https://github.com/esafak. (#2786 https://github.com/pypa/virtualenv/issues/2786)
- Add a note to the user guide recommending the use of a specific Python version when creating virtual environments. Contributed by @esafak https://github.com/esafak. (#2808 https://github.com/pypa/virtualenv/issues/2808)
- Fix 'Too many open files' error due to a file descriptor leak in virtualenv's locking mechanism. Contributed by @esafak https://github.com/esafak. (#2834 https://github.com/pypa/virtualenv/issues/2834)
- Support renamed Windows venv redirector (venvlauncher.exe and venvwlauncher.exe) on Python 3.13 Contributed by @esafak https://github.com/esafak. (#2851 https://github.com/pypa/virtualenv/issues/2851)
- Resolve Nushell activation script deprecation warnings by dynamically selecting the --optional flag for Nushell get command on version 0.106.0 and newer, while retaining the deprecated -i flag for older versions to maintain compatibility. Contributed by @gaborbernat https://github.com/gaborbernat. (#2910 https://github.com/pypa/virtualenv/issues/2910)
v20.32.0 (2025-07-20)
Features - 20.32.0
- Warn on incorrect invocation of Nushell activation script - by @esafak https://github.com/esafak. (#nushell_activation https://github.com/pypa/virtualenv/issues/nushell_activation)
- Discover uv-managed Python installations (#2901 https://github.com/pypa/virtualenv/issues/2901)
Bugfixes - 20.32.0
- Ignore missing absolute paths for python discovery - by @esafak https://github.com/esafak (#2870 https://github.com/pypa/virtualenv/issues/2870)
- Upgrade embedded setuptools to 80.9.0 from 80.3.1 - by @gaborbernat https://github.com/gaborbernat. (#2900 https://github.com/pypa/virtualenv/issues/2900)
v20.31.2 (2025-05-08)
No significant changes.
v20.31.1 (2025-05-05)
Bugfixes - 20.31.1
- •
- Upgrade embedded wheels:
- pip to 25.1.1 from 25.1
- setuptools to 80.3.1 from 78.1.0 (#2880 https://github.com/pypa/virtualenv/issues/2880)
v20.31.0 (2025-05-05)
Features - 20.31.0
- •
- No longer bundle wheel wheels (except on Python 3.8), setuptools includes native bdist_wheel support. Update pip to 25.1. (#2868 https://github.com/pypa/virtualenv/issues/2868)
Bugfixes - 20.31.0
- get_embed_wheel() no longer fails with a TypeError https://docs.python.org/3/library/exceptions.html#TypeError when it is called with an unknown distribution. (#2877 https://github.com/pypa/virtualenv/issues/2877)
- Fix HelpFormatter error with Python 3.14.0b1. (#2878 https://github.com/pypa/virtualenv/issues/2878)
v20.30.0 (2025-03-31)
Features - 20.30.0
- •
- Add support for GraalPy https://github.com/oracle/graalpython. (#2832 https://github.com/pypa/virtualenv/issues/2832)
Bugfixes - 20.30.0
- •
- Upgrade embedded wheels:
- •
- setuptools to 78.1.0 from 75.3.2 (#2863 https://github.com/pypa/virtualenv/issues/2863)
v20.29.3 (2025-03-06)
Bugfixes - 20.29.3
- •
- Ignore unreadable directories in PATH. (#2794 https://github.com/pypa/virtualenv/issues/2794)
v20.29.2 (2025-02-10)
Bugfixes - 20.29.2
- Remove old virtualenv wheel from the source distribution - by @gaborbernat https://github.com/gaborbernat. (#2841 https://github.com/pypa/virtualenv/issues/2841)
- Upgrade embedded wheel pip to 25.0.1 from 24.3.1 - by @gaborbernat https://github.com/gaborbernat. (#2843 https://github.com/pypa/virtualenv/issues/2843)
v20.29.1 (2025-01-17)
Bugfixes - 20.29.1
- •
- Fix PyInfo cache incompatibility warnings - by @robsdedude https://github.com/robsdedude. (#2827 https://github.com/pypa/virtualenv/issues/2827)
v20.29.0 (2025-01-15)
Features - 20.29.0
- •
- Add support for selecting free-threaded Python interpreters, e.g., python3.13t. (#2809 https://github.com/pypa/virtualenv/issues/2809)
Bugfixes - 20.29.0
- •
- Upgrade embedded wheels:
- •
- setuptools to 75.8.0 from 75.6.0 (#2823 https://github.com/pypa/virtualenv/issues/2823)
v20.28.1 (2025-01-02)
Bugfixes - 20.28.1
- •
- Skip tcsh tests on broken tcsh versions - by @gaborbernat https://github.com/gaborbernat. (#2814 https://github.com/pypa/virtualenv/issues/2814)
v20.28.0 (2024-11-25)
Features - 20.28.0
- •
- Write CACHEDIR.TAG file on creation - by "user:neilramsay. (#2803 https://github.com/pypa/virtualenv/issues/2803)
v20.27.2 (2024-11-25)
Bugfixes - 20.27.2
- •
- Upgrade embedded wheels:
- •
- setuptools to 75.3.0 from 75.2.0 (#2798 https://github.com/pypa/virtualenv/issues/2798)
- •
- Upgrade embedded wheels:
- wheel to 0.45.0 from 0.44.0
- setuptools to 75.5.0 (#2800 https://github.com/pypa/virtualenv/issues/2800)
- no longer forcibly echo off during windows batch activation (#2801 https://github.com/pypa/virtualenv/issues/2801)
- Upgrade embedded wheels:
- setuptools to 75.6.0 from 75.5.0
- wheel to 0.45.1 from 0.45.0 (#2804 https://github.com/pypa/virtualenv/issues/2804)
v20.27.1 (2024-10-28)
Bugfixes - 20.27.1
- •
- Upgrade embedded wheels:
- •
- pip to 24.3.1 from 24.2 (#2789 https://github.com/pypa/virtualenv/issues/2789)
v20.27.0 (2024-10-17)
Features - 20.27.0
- •
- Drop 3.7 support as the CI environments no longer allow it running - by @gaborbernat https://github.com/gaborbernat. (#2758 https://github.com/pypa/virtualenv/issues/2758)
Bugfixes - 20.27.0
- When a $PATH entry cannot be checked for existence, skip it instead of terminating - by @hroncok https://github.com/hroncok. (#2782 https://github.com/pypa/virtualenv/issues/2782)
- Upgrade embedded wheels:
- setuptools to 75.2.0 from 75.1.0
- Removed pip of 24.0
- Removed setuptools of 68.0.0
- Removed wheel of 0.42.0
- by @gaborbernat https://github.com/gaborbernat. (#2783 https://github.com/pypa/virtualenv/issues/2783)
- •
- Fix zipapp is broken on Windows post distlib 0.3.9 - by @gaborbernat https://github.com/gaborbernat. (#2784 https://github.com/pypa/virtualenv/issues/2784)
v20.26.6 (2024-09-27)
Bugfixes - 20.26.6
- •
- Properly quote string placeholders in activation script templates to mitigate potential command injection - by @y5c4l3 https://github.com/y5c4l3. (#2768 https://github.com/pypa/virtualenv/issues/2768)
v20.26.5 (2024-09-17)
Bugfixes - 20.26.5
- •
- Upgrade embedded wheels: setuptools to 75.1.0 from 74.1.2 - by @gaborbernat https://github.com/gaborbernat. (#2765 https://github.com/pypa/virtualenv/issues/2765)
v20.26.4 (2024-09-07)
Bugfixes - 20.26.4
- no longer create () output in console during activation of a virtualenv by .bat file. (#2728 https://github.com/pypa/virtualenv/issues/2728)
- Upgrade embedded wheels:
- wheel to 0.44.0 from 0.43.0
- pip to 24.2 from 24.1
- setuptools to 74.1.2 from 70.1.0 (#2760 https://github.com/pypa/virtualenv/issues/2760)
v20.26.3 (2024-06-21)
Bugfixes - 20.26.3
- •
- Upgrade embedded wheels:
- setuptools to 70.1.0 from 69.5.1
- pip to 24.1 from 24.0 (#2741 https://github.com/pypa/virtualenv/issues/2741)
v20.26.2 (2024-05-13)
Bugfixes - 20.26.2
- virtualenv.pyz no longer fails when zipapp path contains a symlink - by @HandSonic https://github.com/HandSonic and @petamas https://github.com/petamas. (#1949 https://github.com/pypa/virtualenv/issues/1949)
- Fix bad return code from activate.sh if hashing is disabled - by :user:'fenkes-ibm'. (#2717 https://github.com/pypa/virtualenv/issues/2717)
v20.26.1 (2024-04-29)
Bugfixes - 20.26.1
- •
- fix PATH-based Python discovery on Windows - by @ofek https://github.com/ofek. (#2712 https://github.com/pypa/virtualenv/issues/2712)
v20.26.0 (2024-04-23)
Bugfixes - 20.26.0
- •
- allow builtin discovery to discover specific interpreters (e.g. python3.12) given an unspecific spec (e.g. python3) - by @flying-sheep https://github.com/flying-sheep. (#2709 https://github.com/pypa/virtualenv/issues/2709)
v20.25.3 (2024-04-17)
Bugfixes - 20.25.3
- •
- Python 3.13.0a6 renamed pathmod to parser. (#2702 https://github.com/pypa/virtualenv/issues/2702)
v20.25.2 (2024-04-16)
Bugfixes - 20.25.2
- •
- Upgrade embedded wheels:
- setuptools of 69.1.0 to 69.5.1
- wheel of 0.42.0 to 0.43.0 (#2699 https://github.com/pypa/virtualenv/issues/2699)
v20.25.1 (2024-02-21)
Bugfixes - 20.25.1
- •
- Upgrade embedded wheels:
- setuptools to 69.0.3 from 69.0.2
- pip to 23.3.2 from 23.3.1 (#2681 https://github.com/pypa/virtualenv/issues/2681)
- •
- Upgrade embedded wheels:
- pip 23.3.2 to 24.0,
- setuptools 69.0.3 to 69.1.0. (#2691 https://github.com/pypa/virtualenv/issues/2691)
Misc - 20.25.1
v20.25.0 (2023-12-01)
Features - 20.25.0
- •
- The tests now pass on the CI with Python 3.13.0a2 - by @hroncok https://github.com/hroncok. (#2673 https://github.com/pypa/virtualenv/issues/2673)
Bugfixes - 20.25.0
- •
- Upgrade embedded wheels:
- •
- wheel to 0.41.3 from 0.41.2 (#2665 https://github.com/pypa/virtualenv/issues/2665)
- •
- Upgrade embedded wheels:
- wheel to 0.42.0 from 0.41.3
- setuptools to 69.0.2 from 68.2.2 (#2669 https://github.com/pypa/virtualenv/issues/2669)
v20.24.6 (2023-10-23)
Bugfixes - 20.24.6
- Use get_hookimpls method instead of the private attribute in tests. (#2649 https://github.com/pypa/virtualenv/issues/2649)
- Upgrade embedded wheels:
- setuptools to 68.2.2 from 68.2.0
- pip to 23.3.1 from 23.2.1 (#2656 https://github.com/pypa/virtualenv/issues/2656)
v20.24.5 (2023-09-08)
Bugfixes - 20.24.5
- Declare PyPy 3.10 support - by @cclauss https://github.com/cclauss. (#2638 https://github.com/pypa/virtualenv/issues/2638)
- Brew on macOS no longer allows copy builds - disallow choosing this by @gaborbernat https://github.com/gaborbernat. (#2640 https://github.com/pypa/virtualenv/issues/2640)
- Upgrade embedded wheels:
- •
- setuptools to 68.2.0 from 68.1.2 (#2642 https://github.com/pypa/virtualenv/issues/2642)
v20.24.4 (2023-08-30)
Bugfixes - 20.24.4
- •
- Upgrade embedded wheels:
- setuptools to 68.1.2 from 68.1.0 on 3.8+
- wheel to 0.41.2 from 0.41.1 on 3.7+ (#2628 https://github.com/pypa/virtualenv/issues/2628)
v20.24.3 (2023-08-11)
Bugfixes - 20.24.3
- Fixed ResourceWarning on exit caused by periodic update subprocess (#2472 https://github.com/pypa/virtualenv/issues/2472)
- Upgrade embedded wheels:
- •
- wheel to 0.41.1 from 0.41.0 (#2622 https://github.com/pypa/virtualenv/issues/2622)
Misc - 20.24.3
v20.24.2 (2023-07-24)
Bugfixes - 20.24.2
- •
- Upgrade embedded wheels:
- pip to 23.2.1 from 23.2
- wheel to 0.41.0 from 0.40.0 (#2614 https://github.com/pypa/virtualenv/issues/2614)
v20.24.1 (2023-07-19)
Bugfixes - 20.24.1
- •
- Upgrade embedded wheels:
- •
- pip to 23.2 from 23.1.2 - by @arielkirkwood https://github.com/arielkirkwood (#2611 https://github.com/pypa/virtualenv/issues/2611)
v20.24.0 (2023-07-14)
Features - 20.24.0
- •
- Export the prompt prefix as VIRTUAL_ENV_PROMPT when activating a virtual environment - by @jimporter https://github.com/jimporter. (#2194 https://github.com/pypa/virtualenv/issues/2194)
Bugfixes - 20.24.0
- Fix test suite - by @gaborbernat https://github.com/gaborbernat. (#2592 https://github.com/pypa/virtualenv/issues/2592)
- Upgrade embedded wheels:
- •
- setuptools to 68.0.0 from 67.8.0 (#2607 https://github.com/pypa/virtualenv/issues/2607)
v20.23.1 (2023-06-16)
Bugfixes - 20.23.1
- update and simplify nushell activation script, fixes an issue on Windows resulting in consecutive command not found - by @melMass https://github.com/melMass. (#2572 https://github.com/pypa/virtualenv/issues/2572)
- Upgrade embedded wheels:
- •
- setuptools to 67.8.0 from 67.7.2 (#2588 https://github.com/pypa/virtualenv/issues/2588)
v20.23.0 (2023-04-27)
Features - 20.23.0
- •
- Do not install wheel and setuptools seed packages for Python 3.12+. To restore the old behavior use:
- for wheel use VIRTUALENV_WHEEL=bundle environment variable or --wheel=bundle CLI flag,
- for setuptools use VIRTUALENV_SETUPTOOLS=bundle environment variable or --setuptools=bundle CLI flag.
By @chrysle https://github.com/chrysle. (#2487 https://github.com/pypa/virtualenv/issues/2487)
- •
- 3.12 support - by @gaborbernat https://github.com/gaborbernat. (#2558 https://github.com/pypa/virtualenv/issues/2558)
Bugfixes - 20.23.0
- Prevent PermissionError when using venv creator on systems that deliver files without user write permission - by @kulikjak https://github.com/kulikjak. (#2543 https://github.com/pypa/virtualenv/issues/2543)
- Upgrade setuptools to 67.7.2 from 67.6.1 and pip to 23.1.2 from 23.1 - by @szleb https://github.com/szleb. (#2560 https://github.com/pypa/virtualenv/issues/2560)
v20.22.0 (2023-04-19)
Features - 20.22.0
- •
- Drop support for creating Python <=3.6 (including 2) interpreters. Removed pip of 20.3.4, 21.3.1; wheel of 0.37.1; setuptools of 59.6.0, 44.1.1, 50.3.2- by @gaborbernat https://github.com/gaborbernat. (#2548 https://github.com/pypa/virtualenv/issues/2548)
v20.21.1 (2023-04-19)
Bugfixes - 20.21.1
- Add tox.ini to sdist - by @mtelka https://github.com/mtelka. (#2511 https://github.com/pypa/virtualenv/issues/2511)
- Move the use of 'let' in nushell to ensure compatibility with future releases of nushell, where 'let' no longer assumes that its initializer is a full expressions. (#2527 https://github.com/pypa/virtualenv/issues/2527)
- The nushell command 'str collect' has been superseded by the 'str join' command. The activate.nu script has been updated to reflect this change. (#2532 https://github.com/pypa/virtualenv/issues/2532)
- Upgrade embedded wheels:
- wheel to 0.40.0 from 0.38.4
- setuptools to 67.6.1 from 67.4.0
- pip to 23.1 from 23.0.1 (#2546 https://github.com/pypa/virtualenv/issues/2546)
v20.21.0 (2023-03-12)
Features - 20.21.0
- •
- Make closure syntax explicitly starts with {||. (#2512 https://github.com/pypa/virtualenv/issues/2512)
Bugfixes - 20.21.0
- Add print command to nushell print_prompt to ensure compatibility with future release of nushell, where intermediate commands no longer print their result to stdout. (#2514 https://github.com/pypa/virtualenv/issues/2514)
- Do not assume the default encoding. (#2515 https://github.com/pypa/virtualenv/issues/2515)
- Make ReentrantFileLock thread-safe and, thereby, fix race condition in virtualenv.cli_run - by @radoering https://github.com/radoering. (#2516 https://github.com/pypa/virtualenv/issues/2516)
v20.20.0 (2023-02-28)
Features - 20.20.0
- •
- Change environment variable existence check in Nushell activation script to not use deprecated command. (#2506 https://github.com/pypa/virtualenv/issues/2506)
Bugfixes - 20.20.0
- Discover CPython implementations distributed on Windows by any organization - by @faph https://github.com/faph. (#2504 https://github.com/pypa/virtualenv/issues/2504)
- Upgrade embedded setuptools to 67.4.0 from 67.1.0 and pip to 23.0.1 from 23.0 - by @gaborbernat https://github.com/gaborbernat. (#2510 https://github.com/pypa/virtualenv/issues/2510)
v20.19.0 (2023-02-07)
Features - 20.19.0
- •
- Allow platformdirs version 3 - by @cdce8p https://github.com/cdce8p. (#2499 https://github.com/pypa/virtualenv/issues/2499)
v20.18.0 (2023-02-06)
Features - 20.18.0
- •
- Drop 3.6 runtime support (can still create 2.7+) - by @gaborbernat https://github.com/gaborbernat. (#2489 https://github.com/pypa/virtualenv/issues/2489)
Bugfixes - 20.18.0
- Fix broken prompt in Nushell when activating virtual environment - by @kubouc https://github.com/kubouc. (#2481 https://github.com/pypa/virtualenv/issues/2481)
- Bump embedded pip to 23.0 and setuptools to 67.1 - by @gaborbernat https://github.com/gaborbernat. (#2489 https://github.com/pypa/virtualenv/issues/2489)
v20.17.1 (2022-12-05)
Bugfixes - 20.17.1
- A py or python spec means any Python rather than CPython - by @gaborbernat https://github.com/gaborbernat. (#2460 https://github.com/pypa/virtualenv/issues/2460)
- Make activate.nu respect VIRTUAL_ENV_DISABLE_PROMPT and not set the prompt if requested - by @m-lima https://github.com/m-lima. (#2461 https://github.com/pypa/virtualenv/issues/2461)
v20.17.0 (2022-11-27)
Features - 20.17.0
- Change Nushell activation script to be a module meant to be activated as an overlay. (#2422 https://github.com/pypa/virtualenv/issues/2422)
- Update operator used in Nushell activation script to be compatible with future versions. (#2450 https://github.com/pypa/virtualenv/issues/2450)
Bugfixes - 20.17.0
- Do not use deprecated API from importlib.resources on Python 3.10 or later - by @gaborbernat https://github.com/gaborbernat. (#2448 https://github.com/pypa/virtualenv/issues/2448)
- Upgrade embedded setuptools to 65.6.3 from 65.5.1 - by @gaborbernat https://github.com/gaborbernat. (#2451 https://github.com/pypa/virtualenv/issues/2451)
v20.16.7 (2022-11-12)
Bugfixes - 20.16.7
- Use parent directory of python executable for pyvenv.cfg "home" value per PEP 405 - by @vfazio https://github.com/vfazio. (#2440 https://github.com/pypa/virtualenv/issues/2440)
- In POSIX virtual environments, try alternate binary names if sys._base_executable does not exist - by @vfazio https://github.com/vfazio. (#2442 https://github.com/pypa/virtualenv/issues/2442)
- Upgrade embedded wheel to 0.38.4 and pip to 22.3.1 from 22.3 and setuptools to 65.5.1 from 65.5.0 - by @gaborbernat https://github.com/gaborbernat. (#2443 https://github.com/pypa/virtualenv/issues/2443)
v20.16.6 (2022-10-25)
Features - 20.16.6
- •
- Drop unneeded shims for PyPy3 directory structure (#2426 https://github.com/pypa/virtualenv/issues/2426)
Bugfixes - 20.16.6
- Fix selected scheme on debian derivatives for python 3.10 when python3-distutils is not installed or the venv scheme is not available - by @asottile https://github.com/asottile. (#2350 https://github.com/pypa/virtualenv/issues/2350)
- Allow the test suite to pass even with the original C shell (rather than tcsh) - by @kulikjak https://github.com/kulikjak. (#2418 https://github.com/pypa/virtualenv/issues/2418)
- Fix fallback handling of downloading wheels for bundled packages - by @schaap https://github.com/schaap. (#2429 https://github.com/pypa/virtualenv/issues/2429)
- Upgrade embedded setuptools to 65.5.0 from 65.3.0 and pip to 22.3 from 22.2.2 - by @gaborbernat https://github.com/gaborbernat. (#2434 https://github.com/pypa/virtualenv/issues/2434)
v20.16.5 (2022-09-07)
Bugfixes - 20.16.5
- •
- Do not turn echo off for subsequent commands in batch activators (activate.bat and deactivate.bat) - by @pawelszramowski https://github.com/pawelszramowski. (#2411 https://github.com/pypa/virtualenv/issues/2411)
v20.16.4 (2022-08-29)
Bugfixes - 20.16.4
- •
- Bump embed setuptools to 65.3 - by @gaborbernat https://github.com/gaborbernat. (#2405 https://github.com/pypa/virtualenv/issues/2405)
v20.16.3 (2022-08-04)
Bugfixes - 20.16.3
- •
- Upgrade embedded pip to 22.2.2 from 22.2.1 and setuptools to 63.4.1 from 63.2.0 - by @gaborbernat https://github.com/gaborbernat. (#2395 https://github.com/pypa/virtualenv/issues/2395)
v20.16.2 (2022-07-27)
Bugfixes - 20.16.2
- •
- Bump embedded pip from 22.2 to 22.2.1 - by @gaborbernat https://github.com/gaborbernat. (#2391 https://github.com/pypa/virtualenv/issues/2391)
v20.16.1 (2022-07-26)
Features - 20.16.1
- •
- Update Nushell activation scripts to version 0.67 - by @kubouch https://github.com/kubouch. (#2386 https://github.com/pypa/virtualenv/issues/2386)
v20.16.0 (2022-07-25)
Features - 20.16.0
- Drop support for running under Python 2 (still can generate Python 2 environments) - by @gaborbernat https://github.com/gaborbernat. (#2382 https://github.com/pypa/virtualenv/issues/2382)
- Upgrade embedded pip to 22.2 from 22.1.2 and setuptools to 63.2.0 from 62.6.0 - by @gaborbernat https://github.com/gaborbernat. (#2383 https://github.com/pypa/virtualenv/issues/2383)
v20.15.1 (2022-06-28)
Bugfixes - 20.15.1
- Fix the incorrect operation when setuptools plugins output something into stdout. (#2335 https://github.com/pypa/virtualenv/issues/2335)
- CPython3Windows creator ignores missing DLLs dir. (#2368 https://github.com/pypa/virtualenv/issues/2368)
v20.15.0 (2022-06-25)
Features - 20.15.0
- •
- Support for Windows embeddable Python package: includes python<VERSION>.zip in the creator sources - by @reksarka https://github.com/reksarka. (#1774 https://github.com/pypa/virtualenv/issues/1774)
Bugfixes - 20.15.0
- Upgrade embedded setuptools to 62.3.3 from 62.6.0 and pip to 22.1.2 from 22.0.4 - by @gaborbernat https://github.com/gaborbernat. (#2348 https://github.com/pypa/virtualenv/issues/2348)
- Use shlex.quote instead of deprecated pipes.quote in Python 3 - by @frenzymadness https://github.com/frenzymadness. (#2351 https://github.com/pypa/virtualenv/issues/2351)
- Fix Windows PyPy 3.6 - by @reksarka https://github.com/reksarka. (#2363 https://github.com/pypa/virtualenv/issues/2363)
v20.14.1 (2022-04-11)
Features - 20.14.1
- •
- Support for creating a virtual environment from a Python 2.7 framework on macOS 12 - by @nickhutchinson https://github.com/nickhutchinson. (#2284 https://github.com/pypa/virtualenv/issues/2284)
Bugfixes - 20.14.1
- •
- Upgrade embedded setuptools to 62.1.0 from 61.0.0 - by @gaborbernat https://github.com/gaborbernat. (#2327 https://github.com/pypa/virtualenv/issues/2327)
v20.14.0 (2022-03-25)
Features - 20.14.0
- •
- Support Nushell activation scripts with nu version 0.60 - by @kubouch https://github.com/kubouch. (#2321 https://github.com/pypa/virtualenv/issues/2321)
Bugfixes - 20.14.0
- •
- Upgrade embedded setuptools to 61.0.0 from 60.10.0 - by @gaborbernat https://github.com/gaborbernat. (#2322 https://github.com/pypa/virtualenv/issues/2322)
v20.13.4 (2022-03-18)
Bugfixes - 20.13.4
- Improve performance of python startup inside created virtualenvs - by @asottile https://github.com/asottile. (#2317 https://github.com/pypa/virtualenv/issues/2317)
- Upgrade embedded setuptools to 60.10.0 from 60.9.3 - by @gaborbernat https://github.com/gaborbernat. (#2320 https://github.com/pypa/virtualenv/issues/2320)
v20.13.3 (2022-03-07)
Bugfixes - 20.13.3
- Avoid symlinking the contents of /usr into PyPy3.8+ virtualenvs - by @stefanor https://github.com/stefanor. (#2310 https://github.com/pypa/virtualenv/issues/2310)
- Bump embed pip from 22.0.3 to 22.0.4 - by @gaborbernat https://github.com/gaborbernat. (#2311 https://github.com/pypa/virtualenv/issues/2311)
v20.13.2 (2022-02-24)
Bugfixes - 20.13.2
- •
- Upgrade embedded setuptools to 60.9.3 from 60.6.0 - by @gaborbernat https://github.com/gaborbernat. (#2306 https://github.com/pypa/virtualenv/issues/2306)
v20.13.1 (2022-02-05)
Bugfixes - 20.13.1
- fix "execv() arg 2 must contain only strings" error on M1 MacOS (#2282 https://github.com/pypa/virtualenv/issues/2282)
- Upgrade embedded setuptools to 60.5.0 from 60.2.0 - by @asottile https://github.com/asottile. (#2289 https://github.com/pypa/virtualenv/issues/2289)
- Upgrade embedded pip to 22.0.3 and setuptools to 60.6.0 - by @gaborbernat https://github.com/gaborbernat and @asottile https://github.com/asottile. (#2294 https://github.com/pypa/virtualenv/issues/2294)
v20.13.0 (2022-01-02)
Features - 20.13.0
- •
- Add downloaded wheel information in the relevant JSON embed file to prevent additional downloads of the same wheel. - by @mayeut https://github.com/mayeut. (#2268 https://github.com/pypa/virtualenv/issues/2268)
Bugfixes - 20.13.0
- Fix AttributeError: 'bool' object has no attribute 'error' when creating a Python 2.x virtualenv on macOS - by moreati. (#2269 https://github.com/pypa/virtualenv/issues/2269)
- Fix PermissionError: [Errno 1] Operation not permitted when creating a Python 2.x virtualenv on macOS/arm64 - by moreati. (#2271 https://github.com/pypa/virtualenv/issues/2271)
v20.12.1 (2022-01-01)
Bugfixes - 20.12.1
- Try using previous updates of pip, setuptools & wheel when inside an update grace period rather than always falling back to embedded wheels - by @mayeut https://github.com/mayeut. (#2265 https://github.com/pypa/virtualenv/issues/2265)
- New patch versions of pip, setuptools & wheel are now returned in the expected timeframe. - by @mayeut https://github.com/mayeut. (#2266 https://github.com/pypa/virtualenv/issues/2266)
- Manual upgrades of pip, setuptools & wheel are not discarded by a periodic update - by @mayeut https://github.com/mayeut. (#2267 https://github.com/pypa/virtualenv/issues/2267)
v20.12.0 (2021-12-31)
Features - 20.12.0
- •
- Sign the python2 exe on Darwin arm64 - by @tmspicer https://github.com/tmspicer. (#2233 https://github.com/pypa/virtualenv/issues/2233)
Bugfixes - 20.12.0
- Fix --download option - by @mayeut https://github.com/mayeut. (#2120 https://github.com/pypa/virtualenv/issues/2120)
- Upgrade embedded setuptools to 60.2.0 from 60.1.1 - by @gaborbernat https://github.com/gaborbernat. (#2263 https://github.com/pypa/virtualenv/issues/2263)
v20.11.2 (2021-12-29)
Bugfixes - 20.11.2
- •
- Fix installation of pinned versions of pip, setuptools & wheel - by @mayeut https://github.com/mayeut. (#2203 https://github.com/pypa/virtualenv/issues/2203)
v20.11.1 (2021-12-29)
Bugfixes - 20.11.1
- •
- Bump embed setuptools to 60.1.1 from 60.1.0 - by @gaborbernat https://github.com/gaborbernat. (#2258 https://github.com/pypa/virtualenv/issues/2258)
v20.11.0 (2021-12-28)
Features - 20.11.0
- Avoid deprecation warning from py-filelock argument - by @ofek https://github.com/ofek. (#2237 https://github.com/pypa/virtualenv/issues/2237)
- Upgrade embedded setuptools to 61.1.0 from 58.3.0 - by @gaborbernat https://github.com/gaborbernat. (#2240 https://github.com/pypa/virtualenv/issues/2240)
- Drop the runtime dependency of backports.entry-points-selectable - by @hroncok https://github.com/hroncok. (#2246 https://github.com/pypa/virtualenv/issues/2246)
- Fish: PATH variables should not be quoted when being set - by @d3dave https://github.com/d3dave. (#2248 https://github.com/pypa/virtualenv/issues/2248)
v20.10.0 (2021-11-01)
Features - 20.10.0
- If a "venv" install scheme exists in sysconfig, virtualenv now uses it to create new virtual environments. This allows Python distributors, such as Fedora, to patch/replace the default install scheme without affecting the paths in new virtual environments. A similar technique was proposed to Python, for the venv module https://bugs.python.org/issue45413 - by hroncok (#2208 https://github.com/pypa/virtualenv/issues/2208)
- The activated virtualenv prompt is now always wrapped in parentheses. This affects venvs created with the --prompt attribute, and matches virtualenv's behavior on par with venv. (#2224 https://github.com/pypa/virtualenv/issues/2224)
Bugfixes - 20.10.0
- •
- Fix broken prompt set up by activate.bat - by @SiggyBar https://github.com/SiggyBar. (#2225 https://github.com/pypa/virtualenv/issues/2225)
v20.9.0 (2021-10-23)
Features - 20.9.0
- Special-case --prompt . to the name of the current directory - by @rkm https://github.com/rkm. (#2220 https://github.com/pypa/virtualenv/issues/2220)
- Add libffi-8.dll to pypy windows #2218 https://github.com/pypa/virtualenv/issues/2218 - by @mattip https://github.com/mattip
Bugfixes - 20.9.0
- Fixed path collision that could lead to a PermissionError or writing to system directories when using PyPy3.8 - by @mgorny https://github.com/mgorny. (#2182 https://github.com/pypa/virtualenv/issues/2182)
- Upgrade embedded setuptools to 58.3.0 from 58.1.0 and pip to 21.3.1 from 21.2.4 - by @gaborbernat https://github.com/gaborbernat. (#2205 https://github.com/pypa/virtualenv/issues/2205)
- Remove stray closing parenthesis in activate.bat - by @SiggyBar https://github.com/SiggyBar. (#2221 https://github.com/pypa/virtualenv/issues/2221)
v20.8.1 (2021-09-24)
Bugfixes - 20.8.1
- Fixed a bug where while creating a venv on top of an existing one, without cleaning, when seeded wheel version mismatch occurred, multiple .dist-info directories may be present, confounding entrypoint discovery - by @arcivanov https://github.com/arcivanov (#2185 https://github.com/pypa/virtualenv/issues/2185)
- Bump embed setuptools from 58.0.4 to 58.1.0 - by @gaborbernat https://github.com/gaborbernat. (#2195 https://github.com/pypa/virtualenv/issues/2195)
Misc - 20.8.1
v20.8.0 (2021-09-16)
- upgrade embedded setuptools to 58.0.4 from 57.4.0 and pip to 21.2.4 from 21.2.3
- Add nushell activation script
v20.7.2 (2021-08-10)
Bugfixes - 20.7.2
- •
- Upgrade embedded pip to 21.2.3 from 21.2.2 and wheel to 0.37.0 from 0.36.2 - by @gaborbernat https://github.com/gaborbernat. (#2168 https://github.com/pypa/virtualenv/issues/2168)
v20.7.1 (2021-08-09)
Bugfixes - 20.7.1
- •
- Fix unpacking dictionary items in PythonInfo.install_path (#2165 https://github.com/pypa/virtualenv/issues/2165)
v20.7.0 (2021-07-31)
Bugfixes - 20.7.0
- •
- upgrade embedded pip to 21.2.2 from 21.1.3 and setuptools to 57.4.0 from 57.1.0 - by @gaborbernat https://github.com/gaborbernat (#2159 https://github.com/pypa/virtualenv/issues/2159)
Deprecations and Removals - 20.7.0
- •
- Removed xonsh activator due to this breaking fairly often the CI and lack of support from those packages maintainers, upstream is encouraged to continue supporting the project as a plugin https://github.com/xonsh/xonsh/issues/3689 - by @gaborbernat https://github.com/gaborbernat. (#2160 https://github.com/pypa/virtualenv/issues/2160)
v20.6.0 (2021-07-14)
Features - 20.6.0
- •
- Support Python interpreters without distutils (fallback to syconfig in these cases) - by @gaborbernat https://github.com/gaborbernat. (#1910 https://github.com/pypa/virtualenv/issues/1910)
v20.5.0 (2021-07-13)
Features - 20.5.0
- Plugins now use 'selectable' entry points - by @jaraco https://github.com/jaraco. (#2093 https://github.com/pypa/virtualenv/issues/2093)
- add libffi-7.dll to the hard-coded list of dlls for PyPy (#2141 https://github.com/pypa/virtualenv/issues/2141)
- Use the better maintained platformdirs instead of appdirs - by @gaborbernat https://github.com/gaborbernat. (#2142 https://github.com/pypa/virtualenv/issues/2142)
Bugfixes - 20.5.0
- •
- Bump pip the embedded pip 21.1.3 and setuptools to 57.1.0 - by @gaborbernat https://github.com/gaborbernat. (#2135 https://github.com/pypa/virtualenv/issues/2135)
Deprecations and Removals - 20.5.0
- •
- Drop python 3.4 support as it has been over 2 years since EOL - by @gaborbernat https://github.com/gaborbernat. (#2141 https://github.com/pypa/virtualenv/issues/2141)
v20.4.7 (2021-05-24)
Bugfixes - 20.4.7
- •
- Upgrade embedded pip to 21.1.2 and setuptools to 57.0.0 - by @gaborbernat https://github.com/gaborbernat. (#2123 https://github.com/pypa/virtualenv/issues/2123)
v20.4.6 (2021-05-05)
Bugfixes - 20.4.6
- •
- Fix site.getsitepackages() broken on python2 on debian - by @freundTech https://github.com/freundTech. (#2105 https://github.com/pypa/virtualenv/issues/2105)
v20.4.5 (2021-05-05)
Bugfixes - 20.4.5
- Bump pip to 21.1.1 from 21.0.1 - by @gaborbernat https://github.com/gaborbernat. (#2104 https://github.com/pypa/virtualenv/issues/2104)
- Fix site.getsitepackages() ignoring --system-site-packages on python2 - by @freundTech https://github.com/freundTech. (#2106 https://github.com/pypa/virtualenv/issues/2106)
v20.4.4 (2021-04-20)
Bugfixes - 20.4.4
- Built in discovery class is always preferred over plugin supplied classes. (#2087 https://github.com/pypa/virtualenv/issues/2087)
- Upgrade embedded setuptools to 56.0.0 by @gaborbernat https://github.com/gaborbernat. (#2094 https://github.com/pypa/virtualenv/issues/2094)
v20.4.3 (2021-03-16)
Bugfixes - 20.4.3
- Bump embedded setuptools from 52.0.0 to 54.1.2 - by @gaborbernat https://github.com/gaborbernat (#2069 https://github.com/pypa/virtualenv/issues/2069)
- Fix PyPy3 stdlib on Windows is incorrect - by @gaborbernat https://github.com/gaborbernat. (#2071 https://github.com/pypa/virtualenv/issues/2071)
v20.4.2 (2021-02-01)
Bugfixes - 20.4.2
- •
- Running virtualenv --upgrade-embed-wheels crashes - by @gaborbernat https://github.com/gaborbernat. (#2058 https://github.com/pypa/virtualenv/issues/2058)
v20.4.1 (2021-01-31)
Bugfixes - 20.4.1
- •
- Bump embedded pip and setuptools packages to latest upstream supported (21.0.1 and 52.0.0) - by @gaborbernat https://github.com/gaborbernat. (#2060 https://github.com/pypa/virtualenv/issues/2060)
v20.4.0 (2021-01-19)
Features - 20.4.0
- •
- On the programmatic API allow passing in the environment variable dictionary to use, defaults to os.environ if not specified - by @gaborbernat https://github.com/gaborbernat. (#2054 https://github.com/pypa/virtualenv/issues/2054)
Bugfixes - 20.4.0
- •
- Upgrade embedded setuptools to 51.3.3 from 51.1.2 - by @gaborbernat https://github.com/gaborbernat. (#2055 https://github.com/pypa/virtualenv/issues/2055)
v20.3.1 (2021-01-13)
Bugfixes - 20.3.1
- Bump embed pip to 20.3.3, setuptools to 51.1.1 and wheel to 0.36.2 - by @gaborbernat https://github.com/gaborbernat. (#2036 https://github.com/pypa/virtualenv/issues/2036)
- Allow unfunctioning of pydoc to fail freely so that virtualenvs can be activated under Zsh with set -e (since otherwise unset -f and unfunction exit with 1 if the function does not exist in Zsh) - by @d125q https://github.com/d125q. (#2049 https://github.com/pypa/virtualenv/issues/2049)
- Drop cached python information if the system executable is no longer present (for example when the executable is a shim and the mapped executable is replaced - such is the case with pyenv) - by @gaborbernat https://github.com/gaborbernat. (#2050 https://github.com/pypa/virtualenv/issues/2050)
v20.3.0 (2021-01-10)
Features - 20.3.0
- •
- The builtin discovery takes now a --try-first-with argument and is first attempted as valid interpreters. One can use this to force discovery of a given python executable when the discovery order/mechanism raises errors - by @gaborbernat https://github.com/gaborbernat. (#2046 https://github.com/pypa/virtualenv/issues/2046)
Bugfixes - 20.3.0
- On Windows python 3.7+ distributions where the exe shim is missing fallback to the old ways - by @gaborbernat https://github.com/gaborbernat. (#1986 https://github.com/pypa/virtualenv/issues/1986)
- When discovering interpreters on Windows, via the PEP-514, prefer PythonCore releases over other ones. virtualenv is used via pip mostly by this distribution, so prefer it over other such as conda - by @gaborbernat https://github.com/gaborbernat. (#2046 https://github.com/pypa/virtualenv/issues/2046)
v20.2.2 (2020-12-07)
Bugfixes - 20.2.2
- •
- Bump pip to 20.3.1, setuptools to 51.0.0 and wheel to 0.36.1 - by @gaborbernat https://github.com/gaborbernat. (#2029 https://github.com/pypa/virtualenv/issues/2029)
v20.2.1 (2020-11-23)
No significant changes.
v20.2.0 (2020-11-21)
Features - 20.2.0
- Optionally skip VCS ignore directive for entire virtualenv directory, using option no-vcs-ignore <#no-vcs-ignore>, by default False. (#2003 https://github.com/pypa/virtualenv/issues/2003)
- Add --read-only-app-data option to allow for creation based on an existing app data cache which is non-writable. This may be useful (for example) to produce a docker image where the app-data is pre-populated.
ENV \
VIRTUALENV_OVERRIDE_APP_DATA=/opt/virtualenv/cache \
VIRTUALENV_SYMLINK_APP_DATA=1
RUN virtualenv venv && rm -rf venv
ENV VIRTUALENV_READ_ONLY_APP_DATA=1
USER nobody
# this virtualenv has symlinks into the read-only app-data cache
RUN virtualenv /tmp/venv
Patch by @asottile https://github.com/asottile. (#2009 https://github.com/pypa/virtualenv/issues/2009)
Bugfixes - 20.2.0
- •
- Fix processing of the VIRTUALENV_PYTHON environment variable and make it multi-value as well (separated by comma) - by @pneff https://github.com/pneff. (#1998 https://github.com/pypa/virtualenv/issues/1998)
v20.1.0 (2020-10-25)
Features - 20.1.0
- •
- The python specification can now take one or more values, first found is used to create the virtual environment - by @gaborbernat https://github.com/gaborbernat. (#1995 https://github.com/pypa/virtualenv/issues/1995)
v20.0.35 (2020-10-15)
Bugfixes - 20.0.35
- Bump embedded setuptools from 50.3.0 to 50.3.1 - by @gaborbernat https://github.com/gaborbernat. (#1982 https://github.com/pypa/virtualenv/issues/1982)
- After importing virtualenv passing cwd to a subprocess calls breaks with invalid directory - by @gaborbernat https://github.com/gaborbernat. (#1983 https://github.com/pypa/virtualenv/issues/1983)
v20.0.34 (2020-10-12)
Bugfixes - 20.0.34
- Align with venv module when creating virtual environments with builtin creator on Windows 3.7 and later - by @gaborbernat https://github.com/gaborbernat. (#1782 https://github.com/pypa/virtualenv/issues/1782)
- Handle Cygwin path conversion in the activation script - by @davidcoghlan https://github.com/davidcoghlan. (#1969 https://github.com/pypa/virtualenv/issues/1969)
v20.0.33 (2020-10-04)
Bugfixes - 20.0.33
- Fix None type error in cygwin if POSIX path in dest - by @danyeaw https://github.com/danyeaw. (#1962 https://github.com/pypa/virtualenv/issues/1962)
- Fix Python 3.4 incompatibilities (added back to the CI) - by @gaborbernat https://github.com/gaborbernat. (#1963 https://github.com/pypa/virtualenv/issues/1963)
v20.0.32 (2020-10-01)
Bugfixes - 20.0.32
- For activation scripts always use UNIX line endings (unless it's BATCH shell related) - by @saytosid https://github.com/saytosid. (#1818 https://github.com/pypa/virtualenv/issues/1818)
- Upgrade embedded pip to 20.2.1 and setuptools to 49.4.0 - by @gaborbernat https://github.com/gaborbernat. (#1918 https://github.com/pypa/virtualenv/issues/1918)
- Avoid spawning new windows when doing seed package upgrades in the background on Windows - by @gaborbernat https://github.com/gaborbernat. (#1928 https://github.com/pypa/virtualenv/issues/1928)
- Fix a bug that reading and writing on the same file may cause race on multiple processes. (#1938 https://github.com/pypa/virtualenv/issues/1938)
- Upgrade embedded setuptools to 50.2.0 and pip to 20.2.3 - by @gaborbernat https://github.com/gaborbernat. (#1939 https://github.com/pypa/virtualenv/issues/1939)
- Provide correct path for bash activator in cygwin or msys2 - by @danyeaw https://github.com/danyeaw. (#1940 https://github.com/pypa/virtualenv/issues/1940)
- Relax importlib requirement to allow version<3 - by @usamasadiq https://github.com/usamasadiq (#1953 https://github.com/pypa/virtualenv/issues/1953)
- pth files were not processed on CPython2 if $PYTHONPATH was pointing to site-packages/ - by @navytux https://github.com/navytux. (#1959 https://github.com/pypa/virtualenv/issues/1959) (#1960 https://github.com/pypa/virtualenv/issues/1960)
v20.0.31 (2020-08-17)
Bugfixes - 20.0.31
- •
- Upgrade embedded pip to 20.2.1, setuptools to 49.6.0 and wheel to 0.35.1 - by @gaborbernat https://github.com/gaborbernat. (#1918 https://github.com/pypa/virtualenv/issues/1918)
v20.0.30 (2020-08-04)
Bugfixes - 20.0.30
- •
- Upgrade pip to 20.2.1 and setuptools to 49.2.1 - by @gaborbernat https://github.com/gaborbernat. (#1915 https://github.com/pypa/virtualenv/issues/1915)
v20.0.29 (2020-07-31)
Bugfixes - 20.0.29
- •
- Upgrade embedded pip from version 20.1.2 to 20.2 - by @gaborbernat https://github.com/gaborbernat. (#1909 https://github.com/pypa/virtualenv/issues/1909)
v20.0.28 (2020-07-24)
Bugfixes - 20.0.28
- Fix test suite failing if run from system Python - by @gaborbernat https://github.com/gaborbernat. (#1882 https://github.com/pypa/virtualenv/issues/1882)
- Provide setup_logging flag to python API so that users can bypass logging handling if their application already performs this - by @gaborbernat https://github.com/gaborbernat. (#1896 https://github.com/pypa/virtualenv/issues/1896)
- Use \n instead if \r\n as line separator for report (because Python already performs this transformation automatically upon write to the logging pipe) - by @gaborbernat https://github.com/gaborbernat. (#1905 https://github.com/pypa/virtualenv/issues/1905)
v20.0.27 (2020-07-15)
Bugfixes - 20.0.27
- No longer preimport threading to fix support for gpython https://pypi.org/project/pygolang/#gpython and gevent https://www.gevent.org/ - by @navytux https://github.com/navytux. (#1897 https://github.com/pypa/virtualenv/issues/1897)
- Upgrade setuptools from 49.2.0 on Python 3.5+ - by @gaborbernat https://github.com/gaborbernat. (#1898 https://github.com/pypa/virtualenv/issues/1898)
v20.0.26 (2020-07-07)
Bugfixes - 20.0.26
- Bump dependency distutils >= 0.3.1 - by @gaborbernat https://github.com/gaborbernat. (#1880 https://github.com/pypa/virtualenv/issues/1880)
- Improve periodic update handling:
- better logging output while running and enable logging on background process call ( _VIRTUALENV_PERIODIC_UPDATE_INLINE may be used to debug behavior inline)
- fallback to unverified context when querying the PyPi for release date,
- stop downloading wheels once we reach the embedded version,
by @gaborbernat https://github.com/gaborbernat. (#1883 https://github.com/pypa/virtualenv/issues/1883)
- Do not print error message if the application exists with SystemExit(0) - by @gaborbernat https://github.com/gaborbernat. (#1885 https://github.com/pypa/virtualenv/issues/1885)
- Upgrade embedded setuptools from 47.3.1 to 49.1.0 for Python 3.5+ - by @gaborbernat https://github.com/gaborbernat. (#1887 https://github.com/pypa/virtualenv/issues/1887)
v20.0.25 (2020-06-23)
Bugfixes - 20.0.25
- •
- Fix that when the app-data seeders image creation fails the exception is silently ignored. Avoid two virtual environment creations to step on each others toes by using a lock while creating the base images. By @gaborbernat https://github.com/gaborbernat. (#1869 https://github.com/pypa/virtualenv/issues/1869)
v20.0.24 (2020-06-22)
Features - 20.0.24
- •
- Ensure that the seeded packages do not get too much out of date:
- add a CLI flag that triggers upgrade of embedded wheels under upgrade-embed-wheels <#upgrade-embed-wheels>
- periodically (once every 14 days) upgrade the embedded wheels in a background process, and use them if they have been released for more than 28 days (can be disabled via no-periodic-update <#no-periodic-update>)
More details under Wheel acquisition <#wheels> - by @gaborbernat https://github.com/gaborbernat. (#1821 https://github.com/pypa/virtualenv/issues/1821)
- •
- Upgrade embed wheel content:
- ship wheels for Python 3.9 and 3.10
- upgrade setuptools for Python 3.5+ from 47.1.1 to 47.3.1
by @gaborbernat https://github.com/gaborbernat. (#1841 https://github.com/pypa/virtualenv/issues/1841)
- •
- Display the installed seed package versions in the final summary output, for example:
created virtual environment CPython3.8.3.final.0-64 in 350ms
creator CPython3Posix(dest=/x, clear=True, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/y/virtualenv)
added seed packages: pip==20.1.1, setuptools==47.3.1, wheel==0.34.2
by @gaborbernat https://github.com/gaborbernat. (#1864 https://github.com/pypa/virtualenv/issues/1864)
Bugfixes - 20.0.24
- Do not generate/overwrite .gitignore if it already exists at destination path - by @gaborbernat https://github.com/gaborbernat. (#1862 https://github.com/pypa/virtualenv/issues/1862)
- Improve error message for no .dist-info inside the app-data copy seeder - by @gaborbernat https://github.com/gaborbernat. (#1867 https://github.com/pypa/virtualenv/issues/1867)
Improved Documentation - 20.0.24
- How seeding mechanisms discover (and automatically keep it up to date) wheels at Wheel acquisition <#wheels> - by @gaborbernat https://github.com/gaborbernat. (#1821 https://github.com/pypa/virtualenv/issues/1821)
- How distributions should handle shipping their own embedded wheels at Distribution maintainer patching <#distribution-wheels> - by @gaborbernat https://github.com/gaborbernat. (#1840 https://github.com/pypa/virtualenv/issues/1840)
v20.0.23 (2020-06-12)
Bugfixes - 20.0.23
- •
- Fix typo in setup.cfg - by @RowdyHowell https://github.com/RowdyHowell. (#1857 https://github.com/pypa/virtualenv/issues/1857)
v20.0.22 (2020-06-12)
Bugfixes - 20.0.22
- Relax importlib.resources requirement to also allow version 2 - by @asottile https://github.com/asottile. (#1846 https://github.com/pypa/virtualenv/issues/1846)
- Upgrade embedded setuptools to 44.1.1 for python 2 and 47.1.1 for python3.5+ - by @gaborbernat https://github.com/gaborbernat. (#1855 https://github.com/pypa/virtualenv/issues/1855)
v20.0.21 (2020-05-20)
Features - 20.0.21
- •
- Generate ignore file for version control systems to avoid tracking virtual environments by default. Users should remove these files if still want to track. For now we support only git by @gaborbernat https://github.com/gaborbernat. (#1806 https://github.com/pypa/virtualenv/issues/1806)
Bugfixes - 20.0.21
- Fix virtualenv fails sometimes when run concurrently, --clear-app-data conflicts with clear <#clear> flag when abbreviation is turned on. To bypass this while allowing abbreviated flags on the command line we had to move it to reset-app-data <#reset-app-data> - by @gaborbernat https://github.com/gaborbernat. (#1824 https://github.com/pypa/virtualenv/issues/1824)
- Upgrade embedded setuptools to 46.4.0 from 46.1.3 on Python 3.5+, and pip from 20.1 to 20.1.1 - by @gaborbernat https://github.com/gaborbernat. (#1827 https://github.com/pypa/virtualenv/issues/1827)
- Seeder pip now correctly handles --extra-search-dir - by @frenzymadness https://github.com/frenzymadness. (#1834 https://github.com/pypa/virtualenv/issues/1834)
v20.0.20 (2020-05-04)
Bugfixes - 20.0.20
- Fix download fails with python 3.4 - by @gaborbernat https://github.com/gaborbernat. (#1809 https://github.com/pypa/virtualenv/issues/1809)
- Fixes older CPython2 versions use _get_makefile_filename instead of get_makefile_filename on sysconfig - by @ianw https://github.com/ianw. (#1810 https://github.com/pypa/virtualenv/issues/1810)
- Fix download is True by default - by @gaborbernat https://github.com/gaborbernat. (#1813 https://github.com/pypa/virtualenv/issues/1813)
- Fail app-data seed operation when wheel download fails and better error message - by @gaborbernat https://github.com/gaborbernat. (#1814 https://github.com/pypa/virtualenv/issues/1814)
v20.0.19 (2020-05-03)
Bugfixes - 20.0.19
- Fix generating a Python 2 environment from Python 3 creates invalid python activator - by @gaborbernat https://github.com/gaborbernat. (#1776 https://github.com/pypa/virtualenv/issues/1776)
- Fix pinning seed packages via app-data seeder raised Invalid Requirement - by @gaborbernat https://github.com/gaborbernat. (#1779 https://github.com/pypa/virtualenv/issues/1779)
- Do not stop interpreter discovery if we fail to find the system interpreter for a executable during discovery - by @gaborbernat https://github.com/gaborbernat. (#1781 https://github.com/pypa/virtualenv/issues/1781)
- On CPython2 POSIX platforms ensure syconfig.get_makefile_filename exists within the virtual environment (this is used by some c-extension based libraries - e.g. numpy - for building) - by @gaborbernat https://github.com/gaborbernat. (#1783 https://github.com/pypa/virtualenv/issues/1783)
- Better handling of options copies <#copies> and symlinks <#symlinks>. Introduce priority of where the option is set to follow the order: CLI, env var, file, hardcoded. If both set at same level prefers copy over symlink. - by @gaborbernat https://github.com/gaborbernat. (#1784 https://github.com/pypa/virtualenv/issues/1784)
- Upgrade pip for Python 2.7 and 3.5+ from 20.0.2 to 20.1 - by @gaborbernat https://github.com/gaborbernat. (#1793 https://github.com/pypa/virtualenv/issues/1793)
- Fix CPython is not discovered from Windows registry, and discover pythons from Windows registry in decreasing order by version - by @gaborbernat https://github.com/gaborbernat. (#1796 https://github.com/pypa/virtualenv/issues/1796)
- Fix symlink detection for creators - by @asottile https://github.com/asottile (#1803 https://github.com/pypa/virtualenv/issues/1803)
v20.0.18 (2020-04-16)
Bugfixes - 20.0.18
- •
- Importing setuptools before cli_run could cause our python information query to fail due to setuptools patching distutils.dist.Distribution - by @gaborbernat https://github.com/gaborbernat. (#1771 https://github.com/pypa/virtualenv/issues/1771)
v20.0.17 (2020-04-09)
Features - 20.0.17
- •
- Extend environment variables checked for configuration to also check aliases (e.g. setting either VIRTUALENV_COPIES or VIRTUALENV_ALWAYS_COPY will work) - by @gaborbernat https://github.com/gaborbernat. (#1763 https://github.com/pypa/virtualenv/issues/1763)
v20.0.16 (2020-04-04)
Bugfixes - 20.0.16
- •
- Allow seed wheel files inside the extra-search-dir <#extra-search-dir> folders that do not have Requires-Python metadata specified, these are considered compatible with all python versions - by @gaborbernat https://github.com/gaborbernat. (#1757 https://github.com/pypa/virtualenv/issues/1757)
v20.0.15 (2020-03-27)
Features - 20.0.15
- •
- Upgrade embedded setuptools to 46.1.3 from 46.1.1 - by @gaborbernat https://github.com/gaborbernat. (#1752 https://github.com/pypa/virtualenv/issues/1752)
v20.0.14 (2020-03-25)
Features - 20.0.14
- Remove __PYVENV_LAUNCHER__ on macOs for Python 3.7.(<8) and 3.8.(<3) on interpreter startup via pth file, this pulls in the upstream patch https://github.com/python/cpython/pull/9516 - by @gaborbernat https://github.com/gaborbernat. (#1704 https://github.com/pypa/virtualenv/issues/1704)
- Upgrade embedded setuptools for Python 3.5+ to 46.1.1, for Python 2.7 to 44.1.0 - by @gaborbernat https://github.com/gaborbernat. (#1745 https://github.com/pypa/virtualenv/issues/1745)
Bugfixes - 20.0.14
- •
- Fix discovery of interpreter by name from PATH that does not match a spec format - by @gaborbernat https://github.com/gaborbernat. (#1746 https://github.com/pypa/virtualenv/issues/1746)
v20.0.13 (2020-03-19)
Bugfixes - 20.0.13
- Do not fail when the pyc files is missing for the host Python 2 - by @gaborbernat https://github.com/gaborbernat. (#1738 https://github.com/pypa/virtualenv/issues/1738)
- Support broken Packaging pythons that put the include headers under distutils pattern rather than sysconfig one - by @gaborbernat https://github.com/gaborbernat. (#1739 https://github.com/pypa/virtualenv/issues/1739)
v20.0.12 (2020-03-19)
Bugfixes - 20.0.12
- •
- Fix relative path discovery of interpreters - by @gaborbernat https://github.com/gaborbernat. (#1734 https://github.com/pypa/virtualenv/issues/1734)
v20.0.11 (2020-03-18)
Features - 20.0.11
- •
- Improve error message when the host python does not satisfy invariants needed to create virtual environments (now we print which host files are incompatible/missing and for which creators when no supported creator can be matched, however we found creators that can describe the given Python interpreter - will still print no supported creator for Jython, however print exactly what host files do not allow creation of virtual environments in case of CPython/PyPy) - by @gaborbernat https://github.com/gaborbernat. (#1716 https://github.com/pypa/virtualenv/issues/1716)
Bugfixes - 20.0.11
- Support Python 3 Framework distributed via XCode in macOs Catalina and before - by @gaborbernat https://github.com/gaborbernat. (#1663 https://github.com/pypa/virtualenv/issues/1663)
- Fix Windows Store Python support, do not allow creation via symlink as that's not going to work by design - by @gaborbernat https://github.com/gaborbernat. (#1709 https://github.com/pypa/virtualenv/issues/1709)
- Fix activate_this.py throws AttributeError on Windows when virtual environment was created via cross python mechanism - by @gaborbernat https://github.com/gaborbernat. (#1710 https://github.com/pypa/virtualenv/issues/1710)
- Fix --no-pip, --no-setuptools, --no-wheel not being respected - by @gaborbernat https://github.com/gaborbernat. (#1712 https://github.com/pypa/virtualenv/issues/1712)
- Allow missing .py files if a compiled .pyc version is available - by @tucked https://github.com/tucked. (#1714 https://github.com/pypa/virtualenv/issues/1714)
- Do not fail if the distutils/setuptools patch happens on a C-extension loader (such as zipimporter on Python 3.7 or earlier) - by @gaborbernat https://github.com/gaborbernat. (#1715 https://github.com/pypa/virtualenv/issues/1715)
- Support Python 2 implementations that require the landmark files and site.py to be in platform standard library instead of the standard library path of the virtual environment (notably some RHEL ones, such as the Docker image amazonlinux:1) - by @gaborbernat https://github.com/gaborbernat. (#1719 https://github.com/pypa/virtualenv/issues/1719)
- Allow the test suite to pass even when called with the system Python - to help repackaging of the tool for Linux distributions - by @gaborbernat https://github.com/gaborbernat. (#1721 https://github.com/pypa/virtualenv/issues/1721)
- Also generate pipx.y console script beside pip-x.y to be compatible with how pip installs itself - by @gaborbernat https://github.com/gaborbernat. (#1723 https://github.com/pypa/virtualenv/issues/1723)
- Automatically create the application data folder if it does not exists - by @gaborbernat https://github.com/gaborbernat. (#1728 https://github.com/pypa/virtualenv/issues/1728)
Improved Documentation - 20.0.11
- •
- supports <#compatibility-requirements> details now explicitly what Python installations we support - by @gaborbernat https://github.com/gaborbernat. (#1714 https://github.com/pypa/virtualenv/issues/1714)
v20.0.10 (2020-03-10)
Bugfixes - 20.0.10
- Fix acquiring python information might be altered by distutils configuration files generating incorrect layout virtual environments - by @gaborbernat https://github.com/gaborbernat. (#1663 https://github.com/pypa/virtualenv/issues/1663)
- Upgrade embedded setuptools to 46.0.0 from 45.3.0 on Python 3.5+ - by @gaborbernat https://github.com/gaborbernat. (#1702 https://github.com/pypa/virtualenv/issues/1702)
Improved Documentation - 20.0.10
- Document requirements (pip + index server) when installing via pip under the installation section - by @gaborbernat https://github.com/gaborbernat. (#1618 https://github.com/pypa/virtualenv/issues/1618)
- Document installing from non PEP-518 systems - @gaborbernat https://github.com/gaborbernat. (#1619 https://github.com/pypa/virtualenv/issues/1619)
- Document installing latest unreleased version from Github - @gaborbernat https://github.com/gaborbernat. (#1620 https://github.com/pypa/virtualenv/issues/1620)
v20.0.9 (2020-03-08)
Bugfixes - 20.0.9
- pythonw.exe works as python.exe on Windows - by @gaborbernat https://github.com/gaborbernat. (#1686 https://github.com/pypa/virtualenv/issues/1686)
- Handle legacy loaders for virtualenv import hooks used to patch distutils configuration load - by @gaborbernat https://github.com/gaborbernat. (#1690 https://github.com/pypa/virtualenv/issues/1690)
- Support for python 2 platforms that store landmark files in platstdlib over stdlib (e.g. RHEL) - by @gaborbernat https://github.com/gaborbernat. (#1694 https://github.com/pypa/virtualenv/issues/1694)
- Upgrade embedded setuptools to 45.3.0 from 45.2.0 for Python 3.5+ - by @gaborbernat https://github.com/gaborbernat. (#1699 https://github.com/pypa/virtualenv/issues/1699)
v20.0.8 (2020-03-04)
Bugfixes - 20.0.8
- Having distutils configuration https://docs.python.org/3/install/index.html#distutils-configuration-files files that set prefix and install_scripts cause installation of packages in the wrong location - by @gaborbernat https://github.com/gaborbernat. (#1663 https://github.com/pypa/virtualenv/issues/1663)
- Fix PYTHONPATH being overridden on Python 2 — by @jd https://github.com/jd. (#1673 https://github.com/pypa/virtualenv/issues/1673)
- Fix list configuration value parsing from config file or environment variable - by @gaborbernat https://github.com/gaborbernat. (#1674 https://github.com/pypa/virtualenv/issues/1674)
- Fix Batch activation script shell prompt to display environment name by default - by @spetafree https://github.com/spetafree. (#1679 https://github.com/pypa/virtualenv/issues/1679)
- Fix startup on Python 2 is slower for virtualenv - this was due to setuptools calculating it's working set distribution - by @gaborbernat https://github.com/gaborbernat. (#1682 https://github.com/pypa/virtualenv/issues/1682)
- Fix entry points are not populated for editable installs on Python 2 due to setuptools working set being calculated before easy_install.pth runs - by @gaborbernat https://github.com/gaborbernat. (#1684 https://github.com/pypa/virtualenv/issues/1684)
- Fix attr: import fails for setuptools - by @gaborbernat https://github.com/gaborbernat. (#1685 https://github.com/pypa/virtualenv/issues/1685)
v20.0.7 (2020-02-26)
Bugfixes - 20.0.7
- •
- Disable distutils fixup for python 3 until pypa/pip #7778 https://github.com/pypa/pip/issues/7778 is fixed and released - by @gaborbernat https://github.com/gaborbernat. (#1669 https://github.com/pypa/virtualenv/issues/1669)
v20.0.6 (2020-02-26)
Bugfixes - 20.0.6
- Fix global site package always being added with bundled macOs python framework builds - by @gaborbernat https://github.com/gaborbernat. (#1561 https://github.com/pypa/virtualenv/issues/1561)
- Fix generated scripts use host version info rather than target - by @gaborbernat https://github.com/gaborbernat. (#1600 https://github.com/pypa/virtualenv/issues/1600)
- Fix circular prefix reference with single elements (accept these as if they were system executables, print a info about them referencing themselves) - by @gaborbernat https://github.com/gaborbernat. (#1632 https://github.com/pypa/virtualenv/issues/1632)
- Handle the case when the application data folder is read-only:
- the application data folder is now controllable via app-data <#app-data>,
- clear-app-data now cleans the entire application data folder, not just the app-data seeder path,
- check if the application data path passed in does not exist or is read-only, and fallback to a temporary directory,
- temporary directory application data is automatically cleaned up at the end of execution,
- symlink-app-data <#symlink-app-data> is always False when the application data is temporary
by @gaborbernat https://github.com/gaborbernat. (#1640 https://github.com/pypa/virtualenv/issues/1640)
- Fix PyPy 2 builtin modules are imported from standard library, rather than from builtin - by @gaborbernat https://github.com/gaborbernat. (#1652 https://github.com/pypa/virtualenv/issues/1652)
- Fix creation of entry points when path contains spaces - by @nsoranzo https://github.com/nsoranzo. (#1660 https://github.com/pypa/virtualenv/issues/1660)
- Fix relative paths for the zipapp (for python 3.7+) - by @gaborbernat https://github.com/gaborbernat. (#1666 https://github.com/pypa/virtualenv/issues/1666)
v20.0.5 (2020-02-21)
Features - 20.0.5
- Also create pythonX.X executables when creating pypy virtualenvs - by @asottile https://github.com/asottile (#1612 https://github.com/pypa/virtualenv/issues/1612)
- Fail with better error message if trying to install source with unsupported setuptools, allow setuptools-scm >= 2 and move to legacy setuptools-scm format to support better older platforms (CentOS 7 and such) - by @gaborbernat https://github.com/gaborbernat. (#1621 https://github.com/pypa/virtualenv/issues/1621)
- Report of the created virtual environment is now split across four short lines rather than one long - by @gaborbernat https://github.com/gaborbernat (#1641 https://github.com/pypa/virtualenv/issues/1641)
Bugfixes - 20.0.5
- Add macOs Python 2 Framework support (now we test it with the CI via brew) - by @gaborbernat https://github.com/gaborbernat (#1561 https://github.com/pypa/virtualenv/issues/1561)
- Fix losing of libpypy-c.so when the pypy executable is a symlink - by @asottile https://github.com/asottile (#1614 https://github.com/pypa/virtualenv/issues/1614)
- Discover python interpreter in a case insensitive manner - by @PrajwalM2212 https://github.com/PrajwalM2212 (#1624 https://github.com/pypa/virtualenv/issues/1624)
- Fix cross interpreter support when the host python sets sys.base_executable based on __PYVENV_LAUNCHER__ - by @cjolowicz https://github.com/cjolowicz (#1643 https://github.com/pypa/virtualenv/issues/1643)
v20.0.4 (2020-02-14)
Features - 20.0.4
- •
- When aliasing interpreters, use relative symlinks - by @asottile https://github.com/asottile. (#1596 https://github.com/pypa/virtualenv/issues/1596)
Bugfixes - 20.0.4
- Allow the use of / as pathname component separator on Windows - by vphilippon (#1582 https://github.com/pypa/virtualenv/issues/1582)
- Lower minimal version of six required to 1.9 - by ssbarnea (#1606 https://github.com/pypa/virtualenv/issues/1606)
v20.0.3 (2020-02-12)
Bugfixes - 20.0.3
- On Python 2 with Apple Framework builds the global site package is no longer added when the system-site-packages <#system-site-packages> is not specified - by @gaborbernat https://github.com/gaborbernat. (#1561 https://github.com/pypa/virtualenv/issues/1561)
- Fix system python discovery mechanism when prefixes contain relative parts (e.g. ..) by resolving paths within the python information query - by @gaborbernat https://github.com/gaborbernat. (#1583 https://github.com/pypa/virtualenv/issues/1583)
- Expose a programmatic API as from virtualenv import cli_run - by @gaborbernat https://github.com/gaborbernat. (#1585 https://github.com/pypa/virtualenv/issues/1585)
- Fix app-data seeder <#seeder> injects a extra .dist-info.virtualenv path that breaks importlib.metadata, now we inject an extra .virtualenv - by @gaborbernat https://github.com/gaborbernat. (#1589 https://github.com/pypa/virtualenv/issues/1589)
Improved Documentation - 20.0.3
- •
- Document a programmatic API as from virtualenv import cli_run under Python <#programmatic-api> - by @gaborbernat https://github.com/gaborbernat. (#1585 https://github.com/pypa/virtualenv/issues/1585)
v20.0.2 (2020-02-11)
Features - 20.0.2
- Print out a one line message about the created virtual environment when no verbose <#verbose> is set, this can now be silenced to get back the original behavior via the quiet <#quiet> flag - by @pradyunsg https://github.com/pradyunsg. (#1557 https://github.com/pypa/virtualenv/issues/1557)
- Allow virtualenv's app data cache to be overridden by VIRTUALENV_OVERRIDE_APP_DATA - by @asottile https://github.com/asottile. (#1559 https://github.com/pypa/virtualenv/issues/1559)
- Passing in the virtual environment name/path is now required (no longer defaults to venv) - by @gaborbernat https://github.com/gaborbernat. (#1568 https://github.com/pypa/virtualenv/issues/1568)
- Add a CLI flag with-traceback <#with-traceback> that allows displaying the stacktrace of the virtualenv when a failure occurs - by @gaborbernat https://github.com/gaborbernat. (#1572 https://github.com/pypa/virtualenv/issues/1572)
Bugfixes - 20.0.2
- Support long path names for generated virtual environment console entry points (such as pip) when using the app-data seeder <#seeder> - by @gaborbernat https://github.com/gaborbernat. (#997 https://github.com/pypa/virtualenv/issues/997)
- Improve python discovery mechanism:
- do not fail if there are executables that fail to query (e.g. for not having execute access to it) on the PATH,
- beside the prefix folder also try with the platform dependent binary folder within that,
by @gaborbernat https://github.com/gaborbernat. (#1545 https://github.com/pypa/virtualenv/issues/1545)
- When copying (either files or trees) do not copy the permission bits, last access time, last modification time, and flags as access to these might be forbidden (for example in case of the macOs Framework Python) and these are not needed for the user to use the virtual environment - by @gaborbernat https://github.com/gaborbernat. (#1561 https://github.com/pypa/virtualenv/issues/1561)
- While discovering a python executables interpreters that cannot be queried are now displayed with info level rather than warning, so now they're no longer shown by default (these can be just executables to which we don't have access or that are broken, don't warn if it's not the target Python we want) - by @gaborbernat https://github.com/gaborbernat. (#1574 https://github.com/pypa/virtualenv/issues/1574)
- The app-data seeder <#seeder> no longer symlinks the packages on UNIX and copies on Windows. Instead by default always copies, however now has the symlink-app-data <#symlink-app-data> flag allowing users to request this less robust but faster method - by @gaborbernat https://github.com/gaborbernat. (#1575 https://github.com/pypa/virtualenv/issues/1575)
Improved Documentation - 20.0.2
- Add link to the legacy documentation https://virtualenv.pypa.io/en/legacy for the changelog by @jezdez https://github.com/jezdez. (#1547 https://github.com/pypa/virtualenv/issues/1547)
- Fine tune the documentation layout: default width of theme, allow tables to wrap around, soft corners for code snippets - by @pradyunsg https://github.com/pradyunsg. (#1548 https://github.com/pypa/virtualenv/issues/1548)
v20.0.1 (2020-02-10)
Features - 20.0.1
- •
- upgrade embedded setuptools to 45.2.0 from 45.1.0 for Python 3.4+ - by @gaborbernat https://github.com/gaborbernat. (#1554 https://github.com/pypa/virtualenv/issues/1554)
Bugfixes - 20.0.1
- Virtual environments created via relative path on Windows creates bad console executables - by @gaborbernat https://github.com/gaborbernat. (#1552 https://github.com/pypa/virtualenv/issues/1552)
- Seems sometimes venvs created set their base executable to themselves; we accept these without question, so we handle virtual environments as system pythons causing issues - by @gaborbernat https://github.com/gaborbernat. (#1553 https://github.com/pypa/virtualenv/issues/1553)
v20.0.0. (2020-02-10)
Improved Documentation - 20.0.0.
- •
- Fixes typos, repeated words and inconsistent heading spacing. Rephrase parts of the development documentation and CLI documentation. Expands shorthands like env var and config to their full forms. Uses descriptions from respective documentation, for projects listed in related links - by @pradyunsg https://github.com/pradyunsg. (#1540 https://github.com/pypa/virtualenv/issues/1540)
v20.0.0b2 (2020-02-04)
Features - 20.0.0b2
- •
- Improve base executable discovery mechanism:
- print at debug level why we refuse some candidates,
- when no candidates match exactly, instead of hard failing fallback to the closest match where the priority of matching attributes is: python implementation, major version, minor version, architecture, patch version, release level and serial (this is to facilitate things to still work when the OS upgrade replace/upgrades the system python with a never version, than what the virtualenv host python was created with),
- always resolve system_executable information during the interpreter discovery, and the discovered environment is the system interpreter instead of the venv/virtualenv (this happened before lazily the first time we accessed, and caused reporting that the created virtual environment is of type of the virtualenv host python version, instead of the system pythons version - these two can differ if the OS upgraded the system python underneath and the virtualenv host was created via copy),
by @gaborbernat https://github.com/gaborbernat. (#1515 https://github.com/pypa/virtualenv/issues/1515)
- Generate bash and fish activators on Windows too (as these can be available with git bash, cygwin or mysys2) - by @gaborbernat https://github.com/gaborbernat. (#1527 https://github.com/pypa/virtualenv/issues/1527)
- Upgrade the bundled wheel package from 0.34.0 to 0.34.2 - by @gaborbernat https://github.com/gaborbernat. (#1531 https://github.com/pypa/virtualenv/issues/1531)
Bugfixes - 20.0.0b2
- Bash activation script should have no extensions instead of .sh (this fixes the virtualenvwrapper https://pypi.org/project/virtualenvwrapper integration) - by @gaborbernat https://github.com/gaborbernat. (#1508 https://github.com/pypa/virtualenv/issues/1508)
- Show less information when we run with a single verbosity (-v):
- no longer shows accepted interpreters information (as the last proposed one is always the accepted one),
- do not display the str_spec attribute for PythonSpec as these can be deduced from the other attributes,
- for the app-data seeder do not show the type of lock, only the path to the app data directory,
By @gaborbernat https://github.com/gaborbernat. (#1510 https://github.com/pypa/virtualenv/issues/1510)
- Fixed cannot discover a python interpreter that has already been discovered under a different path (such is the case when we have multiple symlinks to the same interpreter) - by @gaborbernat https://github.com/gaborbernat. (#1512 https://github.com/pypa/virtualenv/issues/1512)
- Support relative paths for -p - by @gaborbernat https://github.com/gaborbernat. (#1514 https://github.com/pypa/virtualenv/issues/1514)
- Creating virtual environments in parallel fail with cannot acquire lock within app data - by @gaborbernat https://github.com/gaborbernat. (#1516 https://github.com/pypa/virtualenv/issues/1516)
- pth files were not processed under Debian CPython2 interpreters - by @gaborbernat https://github.com/gaborbernat. (#1517 https://github.com/pypa/virtualenv/issues/1517)
- Fix prompt not displayed correctly with upcoming fish 3.10 due to us not preserving $pipestatus - by @krobelus https://github.com/krobelus. (#1530 https://github.com/pypa/virtualenv/issues/1530)
- Stable order within pyenv.cfg and add include-system-site-packages only for creators that reference a global Python - by user:gaborbernat. (#1535 https://github.com/pypa/virtualenv/issues/1535)
Improved Documentation - 20.0.0b2
- Create the first iteration of the new documentation - by @gaborbernat https://github.com/gaborbernat. (#1465 https://github.com/pypa/virtualenv/issues/1465)
- Project readme is now of type MarkDown instead of reStructuredText - by @gaborbernat https://github.com/gaborbernat. (#1531 https://github.com/pypa/virtualenv/issues/1531)
v20.0.0b1 (2020-01-28)
- First public release of the rewrite. Everything is brand new and just added.
- --download defaults to False
- No longer replaces builtin site module with custom version baked within virtualenv code itself https://github.com/pypa/virtualenv/blob/legacy/virtualenv_embedded/site.py. A simple shim module is used to fix up things on Python 2 only.
Warning:
Author
Author name not set
Copyright
2007-2026, PyPA, PyPA
| February 28, 2026 | 21.1 |