 |
|
| |
| VIRTUALENV(1) |
virtualenv |
VIRTUALENV(1) |
virtualenv - virtualenv 21.2.0 Latest version on
PyPI[image: PyPI - Implementation] [image] [image: PyPI - Python
Version] [image] Documentation statusDiscordPyPI -
DownloadsPyPI - LicenseOpen issuesOpen pull
requestsPackage popularity
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.
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
Several tools build on virtualenv to provide higher-level
workflows:
- virtualenvwrapper — Shell wrapper for creating and managing
multiple virtualenvs
- pew — Python Env Wrapper, a set of commands to manage
multiple virtual environments
- tox — Automate testing across multiple Python versions
- nox — Flexible test automation in Python
Learn more about virtualenv from these community resources:
- Corey Schafer’s virtualenv tutorial — Video
walkthrough for beginners
- Bernat Gabor’s status quo — Talk about the current
state of Python packaging
- Carl Meyer’s reverse-engineering — 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.
Before starting this tutorial, you need:
- Python 3.8 or later installed on your system. If you use a version manager
like pyenv, mise, or asdf, virtualenv will
automatically discover the Python version they manage.
- virtualenv installed (see Install virtualenv).
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.
To use your virtual environment, you can activate it. The
activation command differs by platform: [Linux/macOS]
$ source myproject/bin/activate
[Windows (PowerShell)]
PS> .\myproject\Scripts\Activate.ps1
[Windows (CMD)]
C:\> .\myproject\Scripts\activate.bat
After activation, your prompt changes to show the active
environment:
You can verify that Python is now running from inside the virtual
environment: [Linux/macOS]
(myproject) $ which python
/home/user/myproject/bin/python
[Windows (PowerShell)]
(myproject) PS> where.exe python
C:\Users\user\myproject\Scripts\python.exe
[Windows (CMD)]
(myproject) C:\> where.exe python
C:\Users\user\myproject\Scripts\python.exe
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.
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
[Windows (PowerShell)]
PS> .\myproject\Scripts\python.exe -c "import sys; print(sys.prefix)"
C:\Users\user\myproject
PS> .\myproject\Scripts\pip.exe install httpx
[Windows (CMD)]
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.
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.
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.
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 – fast, modern Python package manager. Use this if you
already have uv or are starting fresh.
- pipx – installs Python CLI tools in isolated environments.
Use this if you already have pipx set up.
- pip – the standard Python package installer. Use
--user to avoid modifying system packages. May not work on
distributions with externally-managed Python environments.
- zipapp – a self-contained executable requiring no
installation. Use this in CI or environments where you cannot install
packages.
[graph][uv] Install virtualenv as a uv tool:
$ uv tool install virtualenv
Install the development version:
$ uv tool install git+https://github.com/pypa/virtualenv.git@main
[pipx] Install virtualenv using pipx:
$ pipx install virtualenv
Install the development version:
$ pipx install git+https://github.com/pypa/virtualenv.git@main
[pip] Install virtualenv using pip:
$ python -m pip install --user virtualenv
Install the development version:
$ python -m pip install git+https://github.com/pypa/virtualenv.git@main
WARNING:
Some Linux distributions use system-managed Python
environments. If you encounter errors about externally-managed environments,
use uv tool or pipx instead.
[zipapp] Download the zipapp file and run it directly:
$ 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.
Check the installed version:
See Compatibility for supported Python versions.
By default, virtualenv uses the same Python version it runs under.
Override this with --python or -p.
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
Use PEP 440 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.
Create an environment with free-threading Python:
$ virtualenv -p 3.13t venv
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).
Specify the full path to a Python interpreter:
$ virtualenv -p /usr/bin/python3.9 venv
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.
virtualenv automatically resolves shims from pyenv,
mise, and asdf 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 the environment to modify your shell’s PATH and
environment variables. [Bash/Zsh]
$ source venv/bin/activate
[Fish]
$ source venv/bin/activate.fish
[PowerShell]
PS> .\venv\Scripts\Activate.ps1
NOTE:
If you encounter an execution policy error, run
Set-ExecutionPolicy RemoteSigned to allow local scripts.
[CMD]
> .\venv\Scripts\activate.bat
[Nushell]
$ overlay use venv/bin/activate.nu
Exit the virtual environment:
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
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.
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()
Use a configuration file to set default options for
virtualenv.
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.
Derive configuration keys from command-line options by stripping
leading - and replacing remaining - with _:
[virtualenv]
python = /opt/python-3.8/bin/python
Specify multiple values on separate lines:
[virtualenv]
extra_search_dir =
/path/to/dists
/path/to/other/dists
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.
Set the VIRTUALENV_OVERRIDE_APP_DATA environment variable
to override the default app-data cache directory location.
Options are resolved in this order (highest to lowest priority):
[graph].SS Control seed packages
Update the embedded wheel files to the latest versions:
$ virtualenv --upgrade-embed-wheels
Use custom wheel files from a local directory:
$ virtualenv --extra-search-dir /path/to/wheels venv
Download the latest versions of seed packages from PyPI:
$ virtualenv --download venv
Disable automatic periodic updates of seed packages:
$ virtualenv --no-periodic-update venv
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.
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.
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.
3.14 >= python_version >= 3.8
3.11 >= python_version >= 3.8
24.1 and later (Linux and macOS only).
Experimental support (Linux, macOS, and Windows).
RustPython implements Python 3.14.
- New versions are added close to their release date, typically
during the beta phase.
- Old versions are dropped 18 months after CPython EOL, giving
users plenty of time to migrate.
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.
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.
These Python distributions work on Linux, macOS, and Windows:
- Installations from python.org
- python-build-standalone builds (used by uv and
mise)
- Python versions managed by pyenv, mise, or asdf
(shims are automatically resolved to the real binary)
- Ubuntu 16.04 and later (both upstream and deadsnakes builds)
- Fedora
- RHEL and CentOS
- OpenSuse
- Arch Linux
- Python versions installed via Homebrew (works, but not
recommended – 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:
Framework builds do not support copy-based virtual
environments. Use symlink or hardlink creation methods instead.
- •
- Windows Store Python 3.8 and later
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.
virtualenv [OPTIONS]
| Named Arguments |
|
'==SUPPRESS==' |
display the version of the virtualenv package and its location, then
exit |
|
False |
on failure also display the stacktrace internals of virtualenv |
|
False |
use app data folder in read-only mode (write operations will fail with
error) |
|
platform specific application data
folder |
a data folder used as cache by the virtualenv |
|
False |
start with empty app data folder |
|
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 |
|
2 |
increase verbosity |
|
0 |
decrease verbosity |
| core ⇒ options shared
across all discovery |
|
'builtin' |
interpreter discovery method; choice of: builtin |
|
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 these interpreters before starting the discovery |
| core ⇒ options shared
across all 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 |
|
|
directory to create virtualenv at |
|
False |
remove the destination directory if exist before starting (will
overwrite files otherwise) |
|
False |
don't create VCS ignore directive in the destination directory |
|
False |
give the virtual environment access to the system site-packages dir |
|
True |
try to use symlinks rather than copies, when symlinks are not the
default for the platform |
|
False |
try to use copies rather than symlinks, even when symlinks are the
default for the platform |
| core ⇒ options shared
across all seeder |
|
'app-data' |
seed packages install method; choice of: app-data,
pip |
|
False |
do not install seed packages |
|
True |
pass to disable download of the latest pip/setuptools/wheel from
PyPI |
|
False |
pass to enable download of the latest pip/setuptools/wheel from
PyPI |
|
[] |
a path containing wheels to extend the internal wheel list (can be set
1+ times) |
|
'bundle' |
version of pip to install as seed: embed, bundle, none or exact
version |
|
'bundle' |
version of setuptools to install as seed: embed, bundle, none or exact
version |
|
False |
do not install pip |
|
False |
do not install setuptools |
|
False |
disable the periodic (once every 14 days) update of the embedded
wheels |
| app-data ⇒ options
specific to seeder app-data |
|
False |
symlink the python packages from the app-data folder (requires seed
pip>=19.3) |
| core ⇒ options shared
across all activators |
|
comma separated list of activators
supported |
activators to generate - default is all supported; choice of:
bash, batch, cshell, fish, nushell,
powershell, python |
|
|
provides an alternative prompt prefix for this environment (value of .
means name of the current working directory) |
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.cli_run(args,
options=None, setup_logging=True, env=None)
- Create a virtual environment given some command line interface
arguments.
- Parameters
- args (list[str]) -- the command line arguments
- options (Optional[VirtualEnvOptions]) -- passing in a
VirtualEnvOptions object allows return of the parsed options
- setup_logging (bool) -- True if setup logging
handlers, False to use handlers already registered
- env (Optional[MutableMapping[str,
str]]) -- 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.
- Parameters
- args (list[str]) -- the command line arguments
- options (Optional[VirtualEnvOptions]) -- passing in a
VirtualEnvOptions object allows return of the parsed options
- setup_logging (bool) -- True if setup logging
handlers, False to use handlers already registered
- env (Optional[MutableMapping[str,
str]]) -- 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)
The Session class represents a virtualenv creation session
and provides access to the created environment's properties.
Options namespace passed to plugin constructors, populated from
the CLI, environment variables, and configuration files.
- class
virtualenv.config.cli.parser.VirtualEnvOptions(**kwargs)
- set_src(key,
value, src)
- Set an option value and record where it came from.
- Parameters
- key (str) -- the option name
- value (Any) -- the option value
- src (str) -- the source of the value (e.g.
"cli", "env var",
"default")
- Return
type
- None
- get_source(key)
- Return the source that provided a given option value.
- Parameters
- key (str) -- the option name
- Return
type
- Optional[str]
- Returns
- the source string (e.g. "cli", "env
var", "default"), or None if not
tracked
- property
verbosity: int | 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
This page explains the design decisions and concepts behind
virtualenv. It focuses on understanding why things work the way they do.
Since Python 3.3, the standard library includes the venv
module, which provides basic virtual environment creation following PEP
405. uv 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 |
| Performance |
Slowest (60s+); spawns pip 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. |
Independent via its own release cycle. |
| Programmatic API |
Basic create() function
only. |
Full Python API; can describe
environments without creating them. Used by tox, poetry,
pipx, etc. |
Command line only. |
| Type annotations |
No py.typed marker; limited
annotations. |
Fully typed with PEP 561
py.typed marker; checked by ty. |
Not applicable (Rust binary). |
| Best for |
Zero dependencies, basic needs. |
Plugin extensibility, programmatic
API, tool compatibility (tox, virtualenvwrapper). |
Maximum speed, already using uv for package management. |
[graph].SS How virtualenv works
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:
If you upgrade your system Python, existing virtual
environments will still report the old version (the version number is embedded
in the Python executable itself), but they will use the new version’s
standard library and binary extensions. This normally works without issues,
but be aware that the environment is effectively running a hybrid of old and
new Python versions.
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.
- 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 managers like pyenv, mise, and asdf
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:
Virtual environments typically reference the system
Python’s standard library. If you upgrade the system Python, the
virtual environment will report the old version (embedded in its Python
executable) but will actually use the new version’s standard library
content. This can cause confusion when debugging version-specific behavior.
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 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. 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.
[graph]
virtualenv defaults to using the builtin creator if one is
available for the target environment, falling back to the venv creator
otherwise.
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.
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).
- 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.
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.
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.
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 (activate)
- Fish (activate.fish)
- Csh/Tcsh (activate.csh)
- PowerShell (activate.ps1)
- Windows Batch (activate.bat)
- Nushell (activate.nu)
- Python (activate_this.py) – for programmatic activation from
within a running Python process, see Programmatic activation
NOTE:
On Windows 7 and later, PowerShell’s default
execution policy is Restricted, which prevents running the
activate.ps1 script. You can allow locally-generated scripts to run by
changing the execution policy:
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, which explains how virtualenv uses PATH and
PYTHONHOME to isolate virtual environments.
- Use virtualenv - Practical guides for common virtualenv tasks.
- Command line - Complete CLI reference documentation.
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.
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.
This tutorial walks through creating a simple discovery plugin
that locates Python interpreters managed by pyenv.
Set up a new Python package with the following structure:
virtualenv-pyenv/
├── pyproject.toml
└── src/
└── virtualenv_pyenv/
└── __init__.py
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"
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 your plugin in development mode alongside virtualenv:
$ pip install -e virtualenv-pyenv/
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
This page provides task-oriented guides for creating each type of
virtualenv 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
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
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
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
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
This page documents the interfaces that plugins must
implement.
Discovery plugins locate Python interpreters for creating virtual
environments.
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.
- sysconfig_path(key,
config_var=None, sep='/')
- Return the sysconfig install path for a scheme key, optionally
substituting config variables.
- Parameters
- key (str) -- sysconfig path key (e.g.
"purelib", "include").
- config_var (Optional[dict[str, str]])
-- replacement mapping for sysconfig variables; when None uses the
interpreter's own values.
- sep (str) -- path separator to use in the result.
- Return
type
- str
- property
machine: str
- Return the instruction set architecture (ISA) derived from
sysconfig.get_platform().
- property
spec: str
- A specification string identifying this interpreter (e.g.
CPython3.13.2-64-arm64).
- satisfies(spec,
*, impl_must_match)
- Check if a given specification can be satisfied by this python interpreter
instance.
- Parameters
- spec (PythonSpec) -- the specification to check
against.
- impl_must_match (bool) -- when True, the
implementation name must match exactly.
- Return
type
- bool
- to_json()
- Serialize this interpreter information to a JSON string.
- to_dict()
- Convert this interpreter information to a plain dictionary.
- discover_exe(cache,
prefix, *, exact=True, env=None)
- Discover a matching Python executable under a given prefix
directory.
- Parameters
- cache (PyInfoCache) -- interpreter metadata cache.
- prefix (str) -- directory prefix to search under.
- exact (bool) -- when True, require an exact version
match.
- env (Optional[Mapping[str, str]]) --
environment mapping; defaults to os.environ.
- Return
type
- PythonInfo
The application data interface used by plugins for caching.
- class
virtualenv.app_data.base.AppData
- Abstract storage interface for the virtualenv application.
- Ensure a path is available on disk, extracting from zipapp if needed.
- Parameters
- path (Path) -- the path to ensure is available
- to_folder (Optional[Path]) -- optional target
directory for extraction
- Return
type
- Generator[Path]
- Returns
- yields the usable path on disk
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.
- Parameters
- options (VirtualEnvOptions) --
- interpreter (PythonInfo) --
Construct a new virtual environment creator.
- Parameters
- options (VirtualEnvOptions) -- the CLI option as parsed from
add_parser_arguments()
- interpreter (PythonInfo) -- the interpreter to create
virtual environment from
Seeder plugins install initial packages (like pip, setuptools,
wheel) into the virtual environment.
Activator plugins generate shell-specific activation scripts.
This page explains how virtualenv’s plugin system works
internally.
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.
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
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.
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.
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.
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 about it on the issue tracker.
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 to set it up.
- tox: to automatically get the projects development dependencies and
run the test suite. We recommend installing it using pipx.
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
virtualenv’s tests are written using the pytest test
framework. tox is used to automate the setup and execution of
virtualenv’s tests.
To run tests locally execute:
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. 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.
virtualenv uses 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:
NOTE:
Avoid using # noqa comments to suppress linter
warnings - wherever possible, warnings should be fixed instead. # noqa
comments are reserved for rare cases where the recommended style causes severe
readability problems.
virtualenv ships a PEP 561 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:
This uses ty (Astral’s Rust-based type checker) to
validate annotations against Python 3.14. A second environment checks
compatibility with the minimum supported version:
Both environments validate that annotations are consistent and
correct.
- 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.
virtualenv’s documentation is built using Sphinx.
The documentation is written in reStructuredText. To build it locally,
run:
The built documentation can be found in the .tox/docs_out
folder and may be viewed by opening index.html within that
folder.
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).
A full release publishes to PyPI, creates a GitHub
Release with the zipapp attached, and updates get-virtualenv so
that https://bootstrap.pypa.io/virtualenv.pyz serves the new
version.
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
which builds the sdist, wheel, and zipapp, publishes to PyPI via trusted
publisher, creates a GitHub Release with the zipapp attached, and
updates get-virtualenv. If publish fails, a rollback job
automatically reverts everything.
Via GitHub Actions (recommended)
- 1.
- Go to the Pre-release workflow on GitHub.
- 2.
- Click Run workflow and select the bump type (auto,
major, minor, or patch).
Locally
Pass --version <bump> to override the default
auto behavior (e.g. --version minor).
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 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 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.
All pull requests and merges to ‘main’ branch are
tested using GitHub 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.
The changelog.rst file is managed using 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 will deduplicate them.
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.
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.
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:
Upon becoming a maintainer, a person should be given
access to various virtualenv-related tooling across multiple platforms. These
are noted here for future reference by the maintainers:
- GitHub Push Access
- PyPI Publishing Access
- CI Administration capabilities
- ReadTheDocs Administration capabilities
- •
- Update embed wheel generator (tasks/upgrade_wheels.py) to include
type annotations in generated output - by @rahuldevikar.
(#3075)
- Pass --without-scm-ignore-files to subprocess venv on Python 3.13+
so virtualenv controls .gitignore creation, fixing flaky
test_create_no_seed and --no-vcs-ignore being ignored in
subprocess path - by @gaborbernat. (#3089)
- Use BASH_SOURCE[0] instead of $0 in the bash activate script
relocation fallback, fixing incorrect PATH when sourcing the
activate script from a different directory - by @gaborbernat.
(#3090)
- •
- Add comprehensive type annotations across the entire codebase and ship a
PEP 561 py.typed marker so downstream consumers and type checkers
recognize virtualenv as an inline-typed package - by @rahuldevikar.
(#3075)
- •
- The Python discovery logic has been extracted into a standalone
python-discovery package on PyPI (documentation) and is now
consumed as a dependency. If you previously imported discovery internals
directly (e.g. from virtualenv.discovery.py_info import
PythonInfo), switch to from python_discovery import
PythonInfo. Backward-compatibility re-export shims are provided at
virtualenv.discovery.py_info, virtualenv.discovery.py_spec,
and virtualenv.discovery.cached_py_info, however these are
considered unsupported and may be removed in a future release - by
@gaborbernat. (#3070)
- •
- Add support for creating virtual environments with RustPython - by
@elmjag. (#3010)
- Automatically resolve version manager shims (pyenv, mise, asdf) to the
real Python binary during discovery, preventing incorrect interpreter
selection when shims are on PATH - by @gaborbernat.
(#3049)
- Add architecture (ISA) awareness to Python discovery — users can
now specify a CPU architecture suffix in the --python spec string
(e.g. cpython3.12-64-arm64) to distinguish between interpreters
that share the same version and bitness but target different
architectures. Uses sysconfig.get_platform() as the data source,
with cross-platform normalization (amd64 ↔ x86_64,
aarch64 ↔ arm64). Omitting the suffix preserves
existing behavior - by @rahuldevikar. (#3059)
- Store app data (pip/setuptools/wheel caches) under the OS cache directory
(platformdirs.user_cache_dir) instead of the data directory
(platformdirs.user_data_dir). Existing app data at the old location
is automatically migrated on first use. This ensures cached files that can
be redownloaded are placed in the standard cache location (e.g.
~/.cache on Linux, ~/Library/Caches on macOS) where they are
excluded from backups and can be cleaned by system tools - by
@rahuldevikar. (#1884) (#1884)
- Add PKG_CONFIG_PATH environment variable support to all activation
scripts (Bash, Batch, PowerShell, Fish, C Shell, Nushell, and Python). The
virtualenv’s lib/pkgconfig directory is now automatically
prepended to PKG_CONFIG_PATH on activation and restored on
deactivation, enabling packages that use pkg-config during
build/install to find their configuration files - by @rahuldevikar.
(#2637)
- Upgrade embedded pip to 26.0.1 from 25.3 and setuptools to
82.0.0, 75.3.4 from 75.3.2, 80.9.0 - by
@rahuldevikar. (#3027)
- Replace ty: ignore comments with proper type narrowing using
assertions and explicit None checks - by @rahuldevikar.
(#3029)
- 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. (#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. Fixes
#2770. (#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. (#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. (#3044)
- Gracefully handle corrupted on-disk cache and invalid JSON from Python
interrogation subprocess instead of crashing with unhandled
JSONDecodeError or KeyError - by @gaborbernat.
(#3054)
- •
- Fix TOCTOU vulnerabilities in app_data and lock directory creation that
could be exploited via symlink attacks - reported by @tsigouris007,
fixed by @gaborbernat. (#3013)
- •
- 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)
- Fix race condition in _virtualenv.py when file is overwritten
during import, preventing NameError when _DISTUTILS_PATCH is
accessed - by @gracetyy. (#2969)
- Upgrade embedded wheels:
- •
- pip to 25.3 from 25.2 (#2989)
- •
- Accept RuntimeError in test_too_many_open_files, by @esafak
(#2935)
- •
- Revert out changes related to the extraction of the discovery module - by
@gaborbernat. (#2978)
- Patch get_interpreter to handle missing cache and app_data - by
@esafak (#2972)
- Fix backwards incompatible changes to PythonInfo - by
@gaborbernat. (#2975)
- Add AppData and Cache protocols to discovery for decoupling - by
@esafak. (#2074)
- Ensure python3.exe and python3 on Windows for Python 3 - by
@esafak. (#2774)
- Replaced direct references to tcl/tk library paths with getattr - by
@esafak (#2944)
- Restore absolute import of fs_is_case_sensitive - by @esafak.
(#2955)
- Abstract out caching in discovery - by @esafak. Decouple
FileCache from py_info (discovery) - by @esafak.
Remove references to py_info in FileCache - by @esafak. Decouple
discovery from creator plugins - by @esafak. Decouple discovery by
duplicating info utils - by @esafak. (#2074)
- Add PyPy 3.11 support. Contributed by @esafak. (#2932)
- Upgrade embedded wheel pip to 25.2 from 25.1.1 - by
@gaborbernat. (#2333)
- Accept RuntimeError in test_too_many_open_files, by @esafak
(#2935)
- Python in PATH takes precedence over uv-managed python. Contributed by
@edgarrmondragon. (#2952)
- Correctly unpack _get_tcl_tk_libs() response in PythonInfo. Contributed by
@esafak. (#2930)
- Restore py_info.py timestamp in
test_py_info_cache_invalidation_on_py_info_change Contributed by
@esafak. (#2933)
- •
- Added support for Tcl and Tkinter. You’re welcome. Contributed by
@esafak. (#425)
- Prevent logging setup when –help is passed, fixing a flaky test.
Contributed by @esafak. (#u)
- Fix cache invalidation for PythonInfo by hashing py_info.py.
Contributed by @esafak. (#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. (#2493)
- Stop –try-first-with overriding absolute
–python paths. Contributed by @esafak.
(#2659)
- Force UTF-8 encoding for pip download Contributed by @esafak.
(#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. (#2786)
- Add a note to the user guide recommending the use of a specific Python
version when creating virtual environments. Contributed by @esafak.
(#2808)
- Fix ‘Too many open files’ error due to a file descriptor
leak in virtualenv’s locking mechanism. Contributed by
@esafak. (#2834)
- Support renamed Windows venv redirector (venvlauncher.exe and
venvwlauncher.exe) on Python 3.13 Contributed by @esafak.
(#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. (#2910)
- Warn on incorrect invocation of Nushell activation script - by
@esafak. (#nushell_activation)
- Discover uv-managed Python installations (#2901)
- Ignore missing absolute paths for python discovery - by @esafak
(#2870)
- Upgrade embedded setuptools to 80.9.0 from 80.3.1 - by
@gaborbernat. (#2900)
- •
- Upgrade embedded wheels:
- pip to 25.1.1 from 25.1
- setuptools to 80.3.1 from 78.1.0 (#2880)
- •
- No longer bundle wheel wheels (except on Python 3.8),
setuptools includes native bdist_wheel support. Update
pip to 25.1. (#2868)
- get_embed_wheel() no longer fails with a TypeError when it
is called with an unknown distribution. (#2877)
- Fix HelpFormatter error with Python 3.14.0b1. (#2878)
- •
- Add support for GraalPy. (#2832)
- •
- Upgrade embedded wheels:
- •
- setuptools to 78.1.0 from 75.3.2 (#2863)
- •
- Ignore unreadable directories in PATH. (#2794)
- Remove old virtualenv wheel from the source distribution - by
@gaborbernat. (#2841)
- Upgrade embedded wheel pip to 25.0.1 from 24.3.1 - by
@gaborbernat. (#2843)
- •
- Fix PyInfo cache incompatibility warnings - by @robsdedude.
(#2827)
- •
- Add support for selecting free-threaded Python interpreters, e.g.,
python3.13t. (#2809)
- •
- Upgrade embedded wheels:
- •
- setuptools to 75.8.0 from 75.6.0 (#2823)
- •
- Skip tcsh tests on broken tcsh versions - by @gaborbernat.
(#2814)
- •
- Write CACHEDIR.TAG file on creation - by “user:neilramsay.
(#2803)
- •
- Upgrade embedded wheels:
- •
- setuptools to 75.3.0 from 75.2.0 (#2798)
- •
- Upgrade embedded wheels:
- wheel to 0.45.0 from 0.44.0
- setuptools to 75.5.0 (#2800)
- no longer forcibly echo off during windows batch activation
(#2801)
- Upgrade embedded wheels:
- setuptools to 75.6.0 from 75.5.0
- wheel to 0.45.1 from 0.45.0 (#2804)
- •
- Upgrade embedded wheels:
- •
- pip to 24.3.1 from 24.2 (#2789)
- •
- Drop 3.7 support as the CI environments no longer allow it running - by
@gaborbernat. (#2758)
- When a $PATH entry cannot be checked for existence, skip it instead
of terminating - by @hroncok. (#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. (#2783)
- •
- Fix zipapp is broken on Windows post distlib 0.3.9 - by
@gaborbernat. (#2784)
- •
- Properly quote string placeholders in activation script templates to
mitigate potential command injection - by @y5c4l3.
(#2768)
- •
- Upgrade embedded wheels: setuptools to 75.1.0 from 74.1.2 -
by @gaborbernat. (#2765)
- no longer create () output in console during activation of a
virtualenv by .bat file. (#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)
- •
- Upgrade embedded wheels:
- setuptools to 70.1.0 from 69.5.1
- pip to 24.1 from 24.0 (#2741)
- virtualenv.pyz no longer fails when zipapp path contains a symlink
- by @HandSonic and @petamas. (#1949)
- Fix bad return code from activate.sh if hashing is disabled - by
:user:’fenkes-ibm’. (#2717)
- •
- fix PATH-based Python discovery on Windows - by @ofek.
(#2712)
- •
- allow builtin discovery to discover specific interpreters (e.g.
python3.12) given an unspecific spec (e.g. python3) - by
@flying-sheep. (#2709)
- •
- Python 3.13.0a6 renamed pathmod to parser. (#2702)
- •
- Upgrade embedded wheels:
- setuptools of 69.1.0 to 69.5.1
- wheel of 0.42.0 to 0.43.0 (#2699)
- •
- Upgrade embedded wheels:
- setuptools to 69.0.3 from 69.0.2
- pip to 23.3.2 from 23.3.1 (#2681)
- •
- Upgrade embedded wheels:
- pip 23.3.2 to 24.0,
- setuptools 69.0.3 to 69.1.0. (#2691)
- •
- The tests now pass on the CI with Python 3.13.0a2 - by @hroncok.
(#2673)
- •
- Upgrade embedded wheels:
- •
- wheel to 0.41.3 from 0.41.2 (#2665)
- •
- Upgrade embedded wheels:
- wheel to 0.42.0 from 0.41.3
- setuptools to 69.0.2 from 68.2.2 (#2669)
- Use get_hookimpls method instead of the private attribute in tests.
(#2649)
- Upgrade embedded wheels:
- setuptools to 68.2.2 from 68.2.0
- pip to 23.3.1 from 23.2.1 (#2656)
- Declare PyPy 3.10 support - by @cclauss. (#2638)
- Brew on macOS no longer allows copy builds - disallow choosing this by
@gaborbernat. (#2640)
- Upgrade embedded wheels:
- •
- setuptools to 68.2.0 from 68.1.2 (#2642)
- •
- 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)
- Fixed ResourceWarning on exit caused by periodic update subprocess
(#2472)
- Upgrade embedded wheels:
- •
- wheel to 0.41.1 from 0.41.0 (#2622)
- •
- Upgrade embedded wheels:
- pip to 23.2.1 from 23.2
- wheel to 0.41.0 from 0.40.0 (#2614)
- •
- Upgrade embedded wheels:
- •
- pip to 23.2 from 23.1.2 - by @arielkirkwood
(#2611)
- •
- Export the prompt prefix as VIRTUAL_ENV_PROMPT when activating a
virtual environment - by @jimporter. (#2194)
- Fix test suite - by @gaborbernat. (#2592)
- Upgrade embedded wheels:
- •
- setuptools to 68.0.0 from 67.8.0 (#2607)
- update and simplify nushell activation script, fixes an issue on Windows
resulting in consecutive command not found - by @melMass.
(#2572)
- Upgrade embedded wheels:
- •
- setuptools to 67.8.0 from 67.7.2 (#2588)
- •
- 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. (#2487)
- •
- 3.12 support - by @gaborbernat. (#2558)
- Prevent PermissionError when using venv creator on systems that
deliver files without user write permission - by @kulikjak.
(#2543)
- Upgrade setuptools to 67.7.2 from 67.6.1 and pip to
23.1.2 from 23.1 - by @szleb. (#2560)
- •
- 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. (#2548)
- Add tox.ini to sdist - by @mtelka. (#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)
- 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)
- 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)
- •
- Make closure syntax explicitly starts with {||. (#2512)
- 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)
- Do not assume the default encoding. (#2515)
- Make ReentrantFileLock thread-safe and, thereby, fix race condition
in virtualenv.cli_run - by @radoering. (#2516)
- •
- Change environment variable existence check in Nushell activation script
to not use deprecated command. (#2506)
- Discover CPython implementations distributed on Windows by any
organization - by @faph. (#2504)
- Upgrade embedded setuptools to 67.4.0 from 67.1.0 and pip to
23.0.1 from 23.0 - by @gaborbernat.
(#2510)
- •
- Allow platformdirs version 3 - by @cdce8p.
(#2499)
- •
- Drop 3.6 runtime support (can still create 2.7+) - by
@gaborbernat. (#2489)
- Fix broken prompt in Nushell when activating virtual environment - by
@kubouc. (#2481)
- Bump embedded pip to 23.0 and setuptools to 67.1 - by
@gaborbernat. (#2489)
- A py or python spec means any Python rather than
CPython - by @gaborbernat. (#2460)
- Make activate.nu respect VIRTUAL_ENV_DISABLE_PROMPT and not
set the prompt if requested - by @m-lima. (#2461)
- Change Nushell activation script to be a module meant to be activated as
an overlay. (#2422)
- Update operator used in Nushell activation script to be compatible with
future versions. (#2450)
- Do not use deprecated API from importlib.resources on Python 3.10
or later - by @gaborbernat. (#2448)
- Upgrade embedded setuptools to 65.6.3 from 65.5.1 - by
@gaborbernat. (#2451)
- Use parent directory of python executable for pyvenv.cfg
“home” value per PEP 405 - by @vfazio.
(#2440)
- In POSIX virtual environments, try alternate binary names if
sys._base_executable does not exist - by @vfazio.
(#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. (#2443)
- •
- Drop unneeded shims for PyPy3 directory structure (#2426)
- 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. (#2350)
- Allow the test suite to pass even with the original C shell (rather than
tcsh) - by @kulikjak. (#2418)
- Fix fallback handling of downloading wheels for bundled packages - by
@schaap. (#2429)
- Upgrade embedded setuptools to 65.5.0 from 65.3.0 and pip to
22.3 from 22.2.2 - by @gaborbernat.
(#2434)
- •
- Do not turn echo off for subsequent commands in batch activators
(activate.bat and deactivate.bat) - by
@pawelszramowski. (#2411)
- •
- Bump embed setuptools to 65.3 - by @gaborbernat.
(#2405)
- •
- Upgrade embedded pip to 22.2.2 from 22.2.1 and setuptools to
63.4.1 from 63.2.0 - by @gaborbernat.
(#2395)
- •
- Bump embedded pip from 22.2 to 22.2.1 - by
@gaborbernat. (#2391)
- •
- Update Nushell activation scripts to version 0.67 - by @kubouch.
(#2386)
- Drop support for running under Python 2 (still can generate Python 2
environments) - by @gaborbernat. (#2382)
- Upgrade embedded pip to 22.2 from 22.1.2 and setuptools to
63.2.0 from 62.6.0 - by @gaborbernat.
(#2383)
- Fix the incorrect operation when setuptools plugins output
something into stdout. (#2335)
- CPython3Windows creator ignores missing DLLs dir.
(#2368)
- •
- Support for Windows embeddable Python package: includes
python<VERSION>.zip in the creator sources - by
@reksarka. (#1774)
- Upgrade embedded setuptools to 62.3.3 from 62.6.0 and pip to
22.1.2 from 22.0.4 - by @gaborbernat.
(#2348)
- Use shlex.quote instead of deprecated pipes.quote in Python
3 - by @frenzymadness. (#2351)
- Fix Windows PyPy 3.6 - by @reksarka. (#2363)
- •
- Support for creating a virtual environment from a Python 2.7 framework on
macOS 12 - by @nickhutchinson. (#2284)
- •
- Upgrade embedded setuptools to 62.1.0 from 61.0.0 - by
@gaborbernat. (#2327)
- •
- Support Nushell activation scripts with nu version 0.60 - by
@kubouch. (#2321)
- •
- Upgrade embedded setuptools to 61.0.0 from 60.10.0 - by
@gaborbernat. (#2322)
- Improve performance of python startup inside created virtualenvs - by
@asottile. (#2317)
- Upgrade embedded setuptools to 60.10.0 from 60.9.3 - by
@gaborbernat. (#2320)
- Avoid symlinking the contents of /usr into PyPy3.8+ virtualenvs -
by @stefanor. (#2310)
- Bump embed pip from 22.0.3 to 22.0.4 - by
@gaborbernat. (#2311)
- •
- Upgrade embedded setuptools to 60.9.3 from 60.6.0 - by
@gaborbernat. (#2306)
- fix “execv() arg 2 must contain only strings” error on M1
MacOS (#2282)
- Upgrade embedded setuptools to 60.5.0 from 60.2.0 - by
@asottile. (#2289)
- Upgrade embedded pip to 22.0.3 and setuptools to 60.6.0 - by
@gaborbernat and @asottile. (#2294)
- •
- Add downloaded wheel information in the relevant JSON embed file to
prevent additional downloads of the same wheel. - by @mayeut.
(#2268)
- Fix AttributeError: 'bool' object has no attribute 'error' when
creating a Python 2.x virtualenv on macOS - by moreati.
(#2269)
- Fix PermissionError: [Errno 1] Operation not permitted when
creating a Python 2.x virtualenv on macOS/arm64 - by moreati.
(#2271)
- Try using previous updates of pip, setuptools &
wheel when inside an update grace period rather than always falling
back to embedded wheels - by @mayeut. (#2265)
- New patch versions of pip, setuptools & wheel are
now returned in the expected timeframe. - by @mayeut.
(#2266)
- Manual upgrades of pip, setuptools & wheel are
not discarded by a periodic update - by @mayeut.
(#2267)
- •
- Sign the python2 exe on Darwin arm64 - by @tmspicer.
(#2233)
- Fix --download option - by @mayeut. (#2120)
- Upgrade embedded setuptools to 60.2.0 from 60.1.1 - by
@gaborbernat. (#2263)
- •
- Fix installation of pinned versions of pip, setuptools &
wheel - by @mayeut. (#2203)
- •
- Bump embed setuptools to 60.1.1 from 60.1.0 - by
@gaborbernat. (#2258)
- Avoid deprecation warning from py-filelock argument - by @ofek.
(#2237)
- Upgrade embedded setuptools to 61.1.0 from 58.3.0 - by
@gaborbernat. (#2240)
- Drop the runtime dependency of backports.entry-points-selectable -
by @hroncok. (#2246)
- Fish: PATH variables should not be quoted when being set - by
@d3dave. (#2248)
- 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 - by
hroncok (#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)
- •
- Fix broken prompt set up by activate.bat - by @SiggyBar.
(#2225)
- Special-case --prompt . to the name of the current directory - by
@rkm. (#2220)
- Add libffi-8.dll to pypy windows #2218 - by @mattip
- Fixed path collision that could lead to a PermissionError or writing to
system directories when using PyPy3.8 - by @mgorny.
(#2182)
- Upgrade embedded setuptools to 58.3.0 from 58.1.0 and pip to
21.3.1 from 21.2.4 - by @gaborbernat.
(#2205)
- Remove stray closing parenthesis in activate.bat - by @SiggyBar.
(#2221)
- 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 (#2185)
- Bump embed setuptools from 58.0.4 to 58.1.0 - by
@gaborbernat. (#2195)
- 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
- •
- Upgrade embedded pip to 21.2.3 from 21.2.2 and wheel to
0.37.0 from 0.36.2 - by @gaborbernat.
(#2168)
- •
- Fix unpacking dictionary items in PythonInfo.install_path
(#2165)
- •
- upgrade embedded pip to 21.2.2 from 21.1.3 and setuptools to
57.4.0 from 57.1.0 - by @gaborbernat
(#2159)
- •
- 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 - by
@gaborbernat. (#2160)
- •
- Support Python interpreters without distutils (fallback to
syconfig in these cases) - by @gaborbernat.
(#1910)
- Plugins now use ‘selectable’ entry points - by
@jaraco. (#2093)
- add libffi-7.dll to the hard-coded list of dlls for PyPy
(#2141)
- Use the better maintained platformdirs instead of appdirs -
by @gaborbernat. (#2142)
- •
- Bump pip the embedded pip 21.1.3 and setuptools to 57.1.0 -
by @gaborbernat. (#2135)
- •
- Drop python 3.4 support as it has been over 2 years since EOL - by
@gaborbernat. (#2141)
- •
- Upgrade embedded pip to 21.1.2 and setuptools to 57.0.0 - by
@gaborbernat. (#2123)
- •
- Fix site.getsitepackages() broken on python2 on debian - by
@freundTech. (#2105)
- Bump pip to 21.1.1 from 21.0.1 - by @gaborbernat.
(#2104)
- Fix site.getsitepackages() ignoring --system-site-packages
on python2 - by @freundTech. (#2106)
- Built in discovery class is always preferred over plugin supplied classes.
(#2087)
- Upgrade embedded setuptools to 56.0.0 by @gaborbernat.
(#2094)
- Bump embedded setuptools from 52.0.0 to 54.1.2 - by
@gaborbernat (#2069)
- Fix PyPy3 stdlib on Windows is incorrect - by @gaborbernat.
(#2071)
- •
- Running virtualenv --upgrade-embed-wheels crashes - by
@gaborbernat. (#2058)
- •
- Bump embedded pip and setuptools packages to latest upstream supported
(21.0.1 and 52.0.0) - by @gaborbernat.
(#2060)
- •
- On the programmatic API allow passing in the environment variable
dictionary to use, defaults to os.environ if not specified - by
@gaborbernat. (#2054)
- •
- Upgrade embedded setuptools to 51.3.3 from 51.1.2 - by
@gaborbernat. (#2055)
- Bump embed pip to 20.3.3, setuptools to 51.1.1 and wheel to
0.36.2 - by @gaborbernat. (#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. (#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. (#2050)
- •
- 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. (#2046)
- On Windows python 3.7+ distributions where the exe shim is missing
fallback to the old ways - by @gaborbernat. (#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. (#2046)
- •
- Bump pip to 20.3.1, setuptools to 51.0.0 and wheel to
0.36.1 - by @gaborbernat. (#2029)
- Optionally skip VCS ignore directive for entire virtualenv directory,
using option no-vcs-ignore, by default False.
(#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. (#2009)
- •
- Fix processing of the VIRTUALENV_PYTHON environment variable and
make it multi-value as well (separated by comma) - by @pneff.
(#1998)
- •
- The python specification can now take one or more values, first found is
used to create the virtual environment - by @gaborbernat.
(#1995)
- Bump embedded setuptools from 50.3.0 to 50.3.1 - by
@gaborbernat. (#1982)
- After importing virtualenv passing cwd to a subprocess calls breaks with
invalid directory - by @gaborbernat. (#1983)
- Align with venv module when creating virtual environments with builtin
creator on Windows 3.7 and later - by @gaborbernat.
(#1782)
- Handle Cygwin path conversion in the activation script - by
@davidcoghlan. (#1969)
- Fix None type error in cygwin if POSIX path in dest - by
@danyeaw. (#1962)
- Fix Python 3.4 incompatibilities (added back to the CI) - by
@gaborbernat. (#1963)
- For activation scripts always use UNIX line endings (unless it’s
BATCH shell related) - by @saytosid. (#1818)
- Upgrade embedded pip to 20.2.1 and setuptools to 49.4.0 - by
@gaborbernat. (#1918)
- Avoid spawning new windows when doing seed package upgrades in the
background on Windows - by @gaborbernat. (#1928)
- Fix a bug that reading and writing on the same file may cause race on
multiple processes. (#1938)
- Upgrade embedded setuptools to 50.2.0 and pip to 20.2.3 - by
@gaborbernat. (#1939)
- Provide correct path for bash activator in cygwin or msys2 - by
@danyeaw. (#1940)
- Relax importlib requirement to allow version<3 - by @usamasadiq
(#1953)
- pth files were not processed on CPython2 if $PYTHONPATH was pointing to
site-packages/ - by @navytux. (#1959) (#1960)
- •
- Upgrade embedded pip to 20.2.1, setuptools to 49.6.0 and
wheel to 0.35.1 - by @gaborbernat. (#1918)
- •
- Upgrade pip to 20.2.1 and setuptools to 49.2.1 - by
@gaborbernat. (#1915)
- •
- Upgrade embedded pip from version 20.1.2 to 20.2 - by
@gaborbernat. (#1909)
- Fix test suite failing if run from system Python - by @gaborbernat.
(#1882)
- Provide setup_logging flag to python API so that users can bypass
logging handling if their application already performs this - by
@gaborbernat. (#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. (#1905)
- No longer preimport threading to fix support for gpython and
gevent - by @navytux. (#1897)
- Upgrade setuptools from 49.2.0 on Python 3.5+ - by
@gaborbernat. (#1898)
- Bump dependency distutils >= 0.3.1 - by @gaborbernat.
(#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. (#1883)
- Do not print error message if the application exists with
SystemExit(0) - by @gaborbernat. (#1885)
- Upgrade embedded setuptools from 47.3.1 to 49.1.0 for Python
3.5+ - by @gaborbernat. (#1887)
- •
- 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. (#1869)
- •
- 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
- 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)
More details under Wheel acquisition - by
@gaborbernat. (#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. (#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. (#1864)
- Do not generate/overwrite .gitignore if it already exists at
destination path - by @gaborbernat. (#1862)
- Improve error message for no .dist-info inside the app-data
copy seeder - by @gaborbernat. (#1867)
- How seeding mechanisms discover (and automatically keep it up to date)
wheels at Wheel acquisition - by @gaborbernat.
(#1821)
- How distributions should handle shipping their own embedded wheels at
Distribution maintainer patching - by @gaborbernat.
(#1840)
- •
- Fix typo in setup.cfg - by @RowdyHowell. (#1857)
- Relax importlib.resources requirement to also allow version 2 - by
@asottile. (#1846)
- Upgrade embedded setuptools to 44.1.1 for python 2 and
47.1.1 for python3.5+ - by @gaborbernat. (#1855)
- •
- 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.
(#1806)
- Fix virtualenv fails sometimes when run concurrently,
--clear-app-data conflicts with 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 - by
@gaborbernat. (#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. (#1827)
- Seeder pip now correctly handles --extra-search-dir - by
@frenzymadness. (#1834)
- Fix download fails with python 3.4 - by @gaborbernat.
(#1809)
- Fixes older CPython2 versions use _get_makefile_filename instead of
get_makefile_filename on sysconfig - by @ianw.
(#1810)
- Fix download is True by default - by @gaborbernat.
(#1813)
- Fail app-data seed operation when wheel download fails and better
error message - by @gaborbernat. (#1814)
- Fix generating a Python 2 environment from Python 3 creates invalid python
activator - by @gaborbernat. (#1776)
- Fix pinning seed packages via app-data seeder raised Invalid
Requirement - by @gaborbernat. (#1779)
- Do not stop interpreter discovery if we fail to find the system
interpreter for a executable during discovery - by @gaborbernat.
(#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.
(#1783)
- Better handling of options copies and 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. (#1784)
- Upgrade pip for Python 2.7 and 3.5+ from 20.0.2 to
20.1 - by @gaborbernat. (#1793)
- Fix CPython is not discovered from Windows registry, and discover pythons
from Windows registry in decreasing order by version - by
@gaborbernat. (#1796)
- Fix symlink detection for creators - by @asottile
(#1803)
- •
- Importing setuptools before cli_run could cause our python information
query to fail due to setuptools patching
distutils.dist.Distribution - by @gaborbernat.
(#1771)
- •
- Extend environment variables checked for configuration to also check
aliases (e.g. setting either VIRTUALENV_COPIES or
VIRTUALENV_ALWAYS_COPY will work) - by @gaborbernat.
(#1763)
- •
- Allow seed wheel files inside the extra-search-dir folders that do
not have Requires-Python metadata specified, these are considered
compatible with all python versions - by @gaborbernat.
(#1757)
- •
- Upgrade embedded setuptools to 46.1.3 from 46.1.1 - by
@gaborbernat. (#1752)
- 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 - by @gaborbernat.
(#1704)
- Upgrade embedded setuptools for Python 3.5+ to 46.1.1, for
Python 2.7 to 44.1.0 - by @gaborbernat.
(#1745)
- •
- Fix discovery of interpreter by name from PATH that does not match
a spec format - by @gaborbernat. (#1746)
- Do not fail when the pyc files is missing for the host Python 2 - by
@gaborbernat. (#1738)
- Support broken Packaging pythons that put the include headers under
distutils pattern rather than sysconfig one - by @gaborbernat.
(#1739)
- •
- Fix relative path discovery of interpreters - by @gaborbernat.
(#1734)
- •
- 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.
(#1716)
- Support Python 3 Framework distributed via XCode in macOs Catalina and
before - by @gaborbernat. (#1663)
- Fix Windows Store Python support, do not allow creation via symlink as
that’s not going to work by design - by @gaborbernat.
(#1709)
- Fix activate_this.py throws AttributeError on Windows when
virtual environment was created via cross python mechanism - by
@gaborbernat. (#1710)
- Fix --no-pip, --no-setuptools, --no-wheel not being
respected - by @gaborbernat. (#1712)
- Allow missing .py files if a compiled .pyc version is
available - by @tucked. (#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. (#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.
(#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. (#1721)
- Also generate pipx.y console script beside pip-x.y to be
compatible with how pip installs itself - by @gaborbernat.
(#1723)
- Automatically create the application data folder if it does not exists -
by @gaborbernat. (#1728)
- •
- supports details now explicitly what Python installations we
support - by @gaborbernat. (#1714)
- Fix acquiring python information might be altered by distutils
configuration files generating incorrect layout virtual environments - by
@gaborbernat. (#1663)
- Upgrade embedded setuptools to 46.0.0 from 45.3.0 on Python
3.5+ - by @gaborbernat. (#1702)
- Document requirements (pip + index server) when installing via pip under
the installation section - by @gaborbernat. (#1618)
- Document installing from non PEP-518 systems - @gaborbernat.
(#1619)
- Document installing latest unreleased version from Github -
@gaborbernat. (#1620)
- pythonw.exe works as python.exe on Windows - by
@gaborbernat. (#1686)
- Handle legacy loaders for virtualenv import hooks used to patch distutils
configuration load - by @gaborbernat. (#1690)
- Support for python 2 platforms that store landmark files in
platstdlib over stdlib (e.g. RHEL) - by @gaborbernat.
(#1694)
- Upgrade embedded setuptools to 45.3.0 from 45.2.0 for Python
3.5+ - by @gaborbernat. (#1699)
- Having distutils configuration files that set prefix and
install_scripts cause installation of packages in the wrong
location - by @gaborbernat. (#1663)
- Fix PYTHONPATH being overridden on Python 2 — by @jd.
(#1673)
- Fix list configuration value parsing from config file or environment
variable - by @gaborbernat. (#1674)
- Fix Batch activation script shell prompt to display environment name by
default - by @spetafree. (#1679)
- Fix startup on Python 2 is slower for virtualenv - this was due to
setuptools calculating it’s working set distribution - by
@gaborbernat. (#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. (#1684)
- Fix attr: import fails for setuptools - by @gaborbernat.
(#1685)
- •
- Disable distutils fixup for python 3 until pypa/pip #7778 is fixed
and released - by @gaborbernat. (#1669)
- Fix global site package always being added with bundled macOs python
framework builds - by @gaborbernat. (#1561)
- Fix generated scripts use host version info rather than target - by
@gaborbernat. (#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. (#1632)
- Handle the case when the application data folder is read-only:
- the application data folder is now controllable via 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 is always False when the application data
is temporary
by @gaborbernat. (#1640)
- Fix PyPy 2 builtin modules are imported from standard library, rather than
from builtin - by @gaborbernat. (#1652)
- Fix creation of entry points when path contains spaces - by
@nsoranzo. (#1660)
- Fix relative paths for the zipapp (for python 3.7+) - by
@gaborbernat. (#1666)
- Also create pythonX.X executables when creating pypy virtualenvs -
by @asottile (#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.
(#1621)
- Report of the created virtual environment is now split across four short
lines rather than one long - by @gaborbernat (#1641)
- Add macOs Python 2 Framework support (now we test it with the CI via brew)
- by @gaborbernat (#1561)
- Fix losing of libpypy-c.so when the pypy executable is a symlink - by
@asottile (#1614)
- Discover python interpreter in a case insensitive manner - by
@PrajwalM2212 (#1624)
- Fix cross interpreter support when the host python sets
sys.base_executable based on __PYVENV_LAUNCHER__ - by
@cjolowicz (#1643)
- •
- When aliasing interpreters, use relative symlinks - by @asottile.
(#1596)
- Allow the use of / as pathname component separator on Windows - by
vphilippon (#1582)
- Lower minimal version of six required to 1.9 - by ssbarnea
(#1606)
- On Python 2 with Apple Framework builds the global site package is no
longer added when the system-site-packages is not specified - by
@gaborbernat. (#1561)
- Fix system python discovery mechanism when prefixes contain relative parts
(e.g. ..) by resolving paths within the python information query -
by @gaborbernat. (#1583)
- Expose a programmatic API as from virtualenv import cli_run - by
@gaborbernat. (#1585)
- Fix app-data seeder injects a extra
.dist-info.virtualenv path that breaks importlib.metadata,
now we inject an extra .virtualenv - by @gaborbernat.
(#1589)
- •
- Document a programmatic API as from virtualenv import cli_run under
Python - by @gaborbernat. (#1585)
- Print out a one line message about the created virtual environment when no
verbose is set, this can now be silenced to get back the original
behavior via the quiet flag - by @pradyunsg.
(#1557)
- Allow virtualenv’s app data cache to be overridden by
VIRTUALENV_OVERRIDE_APP_DATA - by @asottile.
(#1559)
- Passing in the virtual environment name/path is now required (no longer
defaults to venv) - by @gaborbernat. (#1568)
- Add a CLI flag with-traceback that allows displaying the stacktrace
of the virtualenv when a failure occurs - by @gaborbernat.
(#1572)
- Support long path names for generated virtual environment console entry
points (such as pip) when using the app-data seeder -
by @gaborbernat. (#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. (#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. (#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.
(#1574)
- The app-data seeder no longer symlinks the packages on UNIX
and copies on Windows. Instead by default always copies, however now has
the symlink-app-data flag allowing users to request this less
robust but faster method - by @gaborbernat. (#1575)
- Add link to the legacy documentation for the changelog by
@jezdez. (#1547)
- Fine tune the documentation layout: default width of theme, allow tables
to wrap around, soft corners for code snippets - by @pradyunsg.
(#1548)
- •
- upgrade embedded setuptools to 45.2.0 from 45.1.0 for Python
3.4+ - by @gaborbernat. (#1554)
- Virtual environments created via relative path on Windows creates bad
console executables - by @gaborbernat. (#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. (#1553)
- •
- 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. (#1540)
- •
- 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. (#1515)
- Generate bash and fish activators on Windows too (as these
can be available with git bash, cygwin or mysys2) - by
@gaborbernat. (#1527)
- Upgrade the bundled wheel package from 0.34.0 to
0.34.2 - by @gaborbernat. (#1531)
- Bash activation script should have no extensions instead of .sh
(this fixes the virtualenvwrapper integration) - by
@gaborbernat. (#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. (#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.
(#1512)
- Support relative paths for -p - by @gaborbernat.
(#1514)
- Creating virtual environments in parallel fail with cannot acquire lock
within app data - by @gaborbernat. (#1516)
- pth files were not processed under Debian CPython2 interpreters - by
@gaborbernat. (#1517)
- Fix prompt not displayed correctly with upcoming fish 3.10 due to us not
preserving $pipestatus - by @krobelus. (#1530)
- Stable order within pyenv.cfg and add
include-system-site-packages only for creators that reference a
global Python - by user:gaborbernat. (#1535)
- Create the first iteration of the new documentation - by
@gaborbernat. (#1465)
- Project readme is now of type MarkDown instead of reStructuredText - by
@gaborbernat. (#1531)
- 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. A simple shim module is used to fix up
things on Python 2 only.
WARNING:
The current virtualenv is the second iteration of
implementation. From version 0.8 all the way to 16.7.9 we
numbered the first iteration. Version 20.0.0b1 is a complete rewrite of
the package, and as such this release history starts from there. The old
changelog is still available in the legacy branch documentation.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
|