Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
VIRTUALENV(1)			  virtualenv			 VIRTUALENV(1)

NAME
       virtualenv - virtualenv 21.2.0 Latest version on	PyPI[image: PyPI - Im-
       plementation]   [image]	 [image:   PyPI	  -  Python  Version]  [image]
       Documentation statusDiscordPyPI - DownloadsPyPI -  LicenseOpen  issues-
       Open 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  li-
       brary  under the	venv module. For how virtualenv	compares to the	stdlib
       venv module, see	Explanation.

QUICK NAVIGATION
       Tutorials - Learn by doing

        Getting started  Create your first virtual environment	and learn  the
	 basic workflow

       How-to guides - Solve specific problems

        Install virtualenv  Install virtualenv	on your	system

        Use  virtualenv   Select Python versions, activate environments, con-
	 figure	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 activa-
	 tors

RELATED	PROJECTS
       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

EXTERNAL RESOURCES
       Learn more about	virtualenv from	these community	resources:

        Corey Schafers	virtualenv tutorial  Video walkthrough for beginners

        Bernat	 Gabors	 status	 quo   Talk  about the current state of	Python
	 packaging

        Carl Meyers reverse-engineering Deep dive into	how  virtualenv	 works
	 internally

   Getting started
       This  tutorial will teach you the basics	of virtualenv through hands-on
       practice. Youll create your first virtual  environment,	install	 pack-
       ages, and learn how to manage project dependencies.

   Prerequisites
       Before starting this tutorial, you need:

        Python	 3.8  or  later	installed on your system. If you use a version
	 manager like pyenv, mise, or asdf, virtualenv will automatically dis-
	 cover the Python version they manage.

        virtualenv installed (see Install virtualenv).

   Create your first virtual environment
       Lets create a virtual environment called	myproject:

	  $ virtualenv myproject
	  created virtual environment CPython3.13.2.final.0-64 in 200ms
	    creator CPython3Posix(dest=/home/user/myproject, clear=False, no_vcs_ignore=False, global=False)
	    seeder FromAppData(download=False, pip=bundle, setuptools=bundle, via=copy,	app_data_dir=/home/user/.cache/virtualenv)
	    activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

       This creates a new directory called myproject  containing  a  complete,
       isolated	Python environment with	its own	copy of	Python,	pip, and other
       tools.

   Activate the	environment
       To  use	your  virtual environment, you can activate it.	The activation
       command differs by platform: [Linux/macOS]

	  $ source myproject/bin/activate
       [Windows	(PowerShell)]

	  PS> .\myproject\Scripts\Activate.ps1
       [Windows	(CMD)]

	  C:\> .\myproject\Scripts\activate.bat

       After activation, your prompt changes to	show the active	environment:

	  (myproject) $

       You can verify that Python is now running from inside the virtual envi-
       ronment:	[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

   Install a package
       With the	environment activated, install a package using pip:

	  (myproject) $	pip install requests
	  Collecting requests
	    Using cached requests-2.32.3-py3-none-any.whl (64 kB)
	  Installing collected packages: requests
	  Successfully installed requests-2.32.3

       Verify that the package is installed only inside	your virtual  environ-
       ment:

	  (myproject) $	python -c "import requests; print(requests.__file__)"
	  /home/user/myproject/lib/python3.13/site-packages/requests/__init__.py

       The  path  shows	that requests is installed in the virtual environment,
       not in your system Python.

   Deactivate
       When youre 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 exe-
       cutable 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.

   Set up a real project
       Now lets	apply what youve 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 projects 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.  Lets  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. Heres the complete
       workflow: [graph].SS What you learned

       In this tutorial, you learned how to:

        Create	a virtual environment with virtualenv.

        Activate and deactivate virtual environments on different platforms.

        Install packages in isolation from your system	Python.

        Save project dependencies with	pip freeze.

        Reproduce environments	using requirements.txt.

   Next	steps
       Now that	you understand the basics, explore these topics:

        Use virtualenv	for selecting specific	Python	versions,  configuring
	 defaults, and advanced	usage patterns.

        Explanation for understanding how virtualenv works under the hood and
	 how it	compares to venv.

        Command line for all available	command	line options and flags.

   Install virtualenv
       virtualenv is a command-line tool, so it	should be installed in an iso-
       lated  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 modi-
	 fying system packages.	May not	 work  on  distributions  with	exter-
	 nally-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.

   Verify installation
       Check the installed version:

	  $ virtualenv --version

       See Compatibility for supported Python versions.

   Use virtualenv
   Select a Python version
       By default, virtualenv uses the same  Python  version  it  runs	under.
       Override	this with --python or -p.

   Using version specifiers
       Specify a Python	version	by name	or version number:

	  $ virtualenv -p python3.8 venv
	  $ virtualenv -p 3.10 venv
	  $ virtualenv -p pypy3	venv
	  $ virtualenv -p rustpython venv

   Using PEP 440 specifiers
       Use PEP 440 version specifiers to match Python versions:

	  $ virtualenv --python	">=3.12" venv
	  $ virtualenv --python	"~=3.11.0" venv
	  $ virtualenv --python	"cpython>=3.10"	venv

        >=3.12	 any Python 3.12 or later.

        ~=3.11.0   compatible	release,  equivalent to	>=3.11.0, <3.12.0 (any
	 3.11.x	patch).

        cpython>=3.10	restrict to CPython implementation, 3.10 or later.

   Using free-threading	Python
       Create an environment with free-threading Python:

	  $ virtualenv -p 3.13t	venv

   Targeting a specific	CPU architecture
       On machines that	support	multiple architectures	such as	Apple  Silicon
       (arm64  +  x86_64 via Rosetta) or Windows on ARM	you can	request	a spe-
       cific CPU architecture by appending it to the spec string:

	  $ virtualenv -p cpython3.12-64-arm64 venv
	  $ virtualenv -p 3.11-64-x86_64 venv

       Cross-platform aliases  are  normalized	automatically,	so  amd64  and
       x86_64 are treated as equivalent, as are	aarch64	and arm64. If omitted,
       any architecture	matches	(preserving existing behavior).

   Using absolute paths
       Specify the full	path to	a Python interpreter:

	  $ virtualenv -p /usr/bin/python3.9 venv

   Using --try-first-with
       Use  --try-first-with  to  provide  a  hint about which Python to check
       first. Unlike --python, this is a hint rather than a rule.  The	inter-
       preter  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  be-
       cause it	does not satisfy the >=3.10 constraint.

   Using version managers (pyenv, mise,	asdf)
       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 a virtual environment
       Activate	 the  environment  to  modify your shells 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

   Deactivate the environment
       Exit the	virtual	environment:

	  $ deactivate

   Use without activation
       Use  the	 environment without activating	it by calling executables with
       their full paths:

	  $ venv/bin/python script.py
	  $ venv/bin/pip install package

   Customize prompt
       Set a custom prompt prefix:

	  $ virtualenv --prompt	myproject venv

       Disable	the  prompt  modification  by  setting	the   VIRTUAL_ENV_DIS-
       ABLE_PROMPT environment variable.

       Access  the  prompt string via the VIRTUAL_ENV_PROMPT environment vari-
       able.

   Programmatic	activation
       Activate	the environment	from within a running Python process using ac-
       tivate_this.py. This modifies sys.path and environment variables	in the
       current process so that subsequent imports resolve from the virtual en-
       vironment.

	  import runpy

	  runpy.run_path("venv/bin/activate_this.py")

       A common	use case is web	applications  served  by  a  system-wide  WSGI
       server  (such  as  mod_wsgi or uWSGI) that need to load packages	from a
       virtual environment:

	  import runpy
	  from pathlib import Path

	  runpy.run_path(str(Path("/var/www/myapp/venv/bin/activate_this.py")))

	  from myapp import create_app	# noqa:	E402

	  application =	create_app()

   Configure defaults
       Use a configuration file	to set default options for virtualenv.

   Configuration file location
       The configuration file is named virtualenv.ini and located in the plat-
       formdirs	app config directory. Run virtualenv --help to see  the	 exact
       location	for your system.

       Override	the location with the VIRTUALENV_CONFIG_FILE environment vari-
       able.

   Configuration format
       Derive  configuration keys from command-line options by stripping lead-
       ing - and replacing remaining - with _:

	  [virtualenv]
	  python = /opt/python-3.8/bin/python

   Multi-value options
       Specify multiple	values on separate lines:

	  [virtualenv]
	  extra_search_dir =
	      /path/to/dists
	      /path/to/other/dists

   Environment variables
       Set options using environment variables with the	VIRTUALENV_ prefix and
       uppercase key names:

	  $ export VIRTUALENV_PYTHON=/opt/python-3.8/bin/python

       For multi-value options,	separate values	with commas or newlines.

   Override app-data location
       Set the VIRTUALENV_OVERRIDE_APP_DATA environment	variable  to  override
       the default app-data cache directory location.

   Configuration priority
       Options	are  resolved  in  this	 order	(highest  to lowest priority):
       [graph].SS Control seed packages

   Upgrade embedded wheels
       Update the embedded wheel files to the latest versions:

	  $ virtualenv --upgrade-embed-wheels

   Provide custom wheels
       Use custom wheel	files from a local directory:

	  $ virtualenv --extra-search-dir /path/to/wheels venv

   Download latest from	PyPI
       Download	the latest versions of seed packages from PyPI:

	  $ virtualenv --download venv

   Disable periodic updates
       Disable automatic periodic updates of seed packages:

	  $ virtualenv --no-periodic-update venv

   For distribution maintainers
       Patch the  virtualenv.seed.wheels.embed	module	and  set  PERIODIC_UP-
       DATE_ON_BY_DEFAULT to False to disable periodic updates by default. See
       Explanation for implementation details.

   Use from Python code
       Call virtualenv from Python code	using the cli_run function:

	  from virtualenv import cli_run

	  cli_run(["venv"])

       Pass options as list elements:

	  cli_run(["-p", "python3.8", "--without-pip", "myenv"])

       Use the returned	session	object to access environment details:

	  result = cli_run(["venv"])
	  print(result.creator.dest)  #	path to	created	environment
	  print(result.creator.exe)  # path to python executable

       Use session_via_cli to describe the environment without creating	it:

	  from virtualenv import session_via_cli

	  session = session_via_cli(["venv"])
	  # inspect session.creator, session.seeder, session.activators

       See Python for complete API documentation.

   Compatibility
   Supported Python implementations
       virtualenv works	with the following Python interpreter implementations.
       Only the	latest patch version of	each minor version is fully supported;
       previous	patch versions work on a best effort basis.

   CPython
       3.14 >= python_version >= 3.8

   PyPy
       3.11 >= python_version >= 3.8

   GraalPy
       24.1 and	later (Linux and macOS only).

   RustPython
       Experimental support (Linux, macOS, and Windows). RustPython implements
       Python 3.14.

   Support policy
        New  versions are added close to their	release	date, typically	during
	 the beta phase.

        Old versions are dropped 18 months after CPython  EOL,	 giving	 users
	 plenty	of time	to migrate.

   Version support timeline
       Major version support changes:

        20.27.0  (2024-10-17):	 dropped  support for running under Python 3.7
	 and earlier.

        20.22.0 (2023-04-19): dropped support for creating  environments  for
	 Python	3.6 and	earlier.

        20.18.0  (2023-02-06):	 dropped  support for running under Python 3.6
	 and earlier.

   Supported operating systems
       CPython is shipped in multiple forms, and each OS repackages it,	 often
       applying	some customization. The	platforms listed below are tested. Un-
       listed  platforms may work but are not explicitly supported. If you en-
       counter issues on unlisted platforms, please open a feature request.

   Cross-platform
       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  automati-
	 cally resolved	to the real binary)

   Linux
        Ubuntu	16.04 and later	(both upstream and deadsnakes builds)

        Fedora

        RHEL and CentOS

        OpenSuse

        Arch Linux

   macOS
        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/Frame-
	 works/Python3.framework/)

       NOTE:
	  Framework builds do not support copy-based virtual environments. Use
	  symlink or hardlink creation methods instead.

   Windows
        Windows Store Python 3.8 and later

   Command line
       virtualenv is primarily a command line application.  All	 options  have
       sensible	defaults, and there is one required argument: the name or path
       of the virtual environment to create.

       See  Use	 virtualenv  for  how to select	Python versions, configure de-
       faults, and use environment variables.

   Command line	options
       virtualenv [OPTIONS]
	  +-----------------+---------------------+---------------------+
	  | Named Arguments |			  |			|
	  +-----------------+---------------------+---------------------+
	  |		    | '==SUPPRESS=='	  | display the	version	|
	  |		    |			  | of	the  virtualenv	|
	  |		    |			  | package and	its lo-	|
	  |		    |			  | cation, then exit	|
	  +-----------------+---------------------+---------------------+
	  |		    | False		  | on	 failure   also	|
	  |		    |			  | display the	 stack-	|
	  |		    |			  | trace  internals of	|
	  |		    |			  | virtualenv		|
	  +-----------------+---------------------+---------------------+
	  |		    | False		  | use	app data folder	|
	  |		    |			  | in	read-only  mode	|
	  |		    |			  | (write   operations	|
	  |		    |			  | will fail with  er-	|
	  |		    |			  | ror)		|
	  +-----------------+---------------------+---------------------+
	  |		    | platform	 specific | a  data folder used	|
	  |		    | application    data | as	cache  by   the	|
	  |		    | folder		  | virtualenv		|
	  +-----------------+---------------------+---------------------+
	  |		    | False		  | start   with  empty	|
	  |		    |			  | app	data folder	|
	  +-----------------+---------------------+---------------------+
	  |		    | False		  | trigger  a	 manual	|
	  |		    |			  | update  of	the em-	|
	  |		    |			  | bedded wheels	|
	  +-----------------+---------------------+---------------------+
		  +---------------------+---+--------------------+
		  | verbosity	   ver-	|   |			 |
		  | bosity  = verbose -	|   |			 |
		  | quiet,	default	|   |			 |
		  | INFO,   mapping  =>	|   |			 |
		  | CRITICAL=0,	    ER-	|   |			 |
		  | ROR=1,   WARNING=2,	|   |			 |
		  | INFO=3,    DEBUG=4,	|   |			 |
		  | NOTSET=5		|   |			 |
		  +---------------------+---+--------------------+
		  |			| 2 | increase verbosity |
		  +---------------------+---+--------------------+
		  |			| 0 | decrease verbosity |
		  +---------------------+---+--------------------+

   discovery
	+---------------------+---------------------+---------------------+
	| core	      options |			    |			  |
	| shared  across  all |			    |			  |
	| discovery	      |			    |			  |
	+---------------------+---------------------+---------------------+
	|		      |	'builtin'	    | interpreter discov- |
	|		      |			    | ery  method; choice |
	|		      |			    | of: builtin	  |
	+---------------------+---------------------+---------------------+
	|		      |	the   python   exe- | interpreter   based |
	|		      |	cutable	 virtualenv | on  what	to create |
	|		      |	is installed into   | environment	  |
	|		      |			    | (path/identi-	  |
	|		      |			    | fier/version-speci- |
	|		      |			    | fier) - 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 in- |
	|		      |			    | terpreters   before |
	|		      |			    | starting	the  dis- |
	|		      |			    | covery		  |
	+---------------------+---------------------+---------------------+

   creator
	+---------------------+---------------------+---------------------+
	| core	      options |			    |			  |
	| shared  across  all |			    |			  |
	| creator	      |			    |			  |
	+---------------------+---------------------+---------------------+
	|		      |	builtin	 if  exist, | create  environment |
	|		      |	else venv	    | via;   choice   of: |
	|		      |			    | cpython3-mac-brew,  |
	|		      |			    | cpython3-mac-frame- |
	|		      |			    | work,		  |
	|		      |			    | cpython3-posix,	  |
	|		      |			    | cpython3-win,	  |
	|		      |			    | graalpy-posix,	  |
	|		      |			    | graalpy-win,	  |
	|		      |			    | pypy3-posix,	  |
	|		      |			    | pypy3-win,    rust- |
	|		      |			    | python-posix, rust- |
	|		      |			    | python-win, venv	  |
	+---------------------+---------------------+---------------------+
	|		      |			    | directory	to create |
	|		      |			    | virtualenv at	  |
	+---------------------+---------------------+---------------------+
	|		      |	False		    | remove the destina- |
	|		      |			    | tion  directory  if |
	|		      |			    | exist before start- |
	|		      |			    | ing (will	overwrite |
	|		      |			    | files otherwise)	  |
	+---------------------+---------------------+---------------------+
	|		      |	False		    | don't   create  VCS |
	|		      |			    | ignore directive in |
	|		      |			    | the destination di- |
	|		      |			    | rectory		  |
	+---------------------+---------------------+---------------------+
	|		      |	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  sym- |
	|		      |			    | links,  even   when |
	|		      |			    | symlinks	 are  the |
	|		      |			    | default	for   the |
	|		      |			    | platform		  |
	+---------------------+---------------------+---------------------+

   seeder
	     +---------------------+------------+---------------------+
	     | core	   options |		|		      |
	     | shared  across  all |		|		      |
	     | seeder		   |		|		      |
	     +---------------------+------------+---------------------+
	     |			   | 'app-data'	| seed	packages  in- |
	     |			   |		| stall	      method; |
	     |			   |		| choice	  of: |
	     |			   |		| app-data, pip	      |
	     +---------------------+------------+---------------------+
	     |			   | False	| do not install seed |
	     |			   |		| packages	      |
	     +---------------------+------------+---------------------+
	     |			   | True	| pass	 to   disable |
	     |			   |		| download   of	  the |
	     |			   |		| latest   pip/setup- |
	     |			   |		| tools/wheel	 from |
	     |			   |		| PyPI		      |
	     +---------------------+------------+---------------------+
	     |			   | False	| pass	 to    enable |
	     |			   |		| download   of	  the |
	     |			   |		| latest   pip/setup- |
	     |			   |		| tools/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  setup- |
	     |			   |		| tools	to install as |
	     |			   |		| seed:	 embed,	 bun- |
	     |			   |		| dle,	none or	exact |
	     |			   |		| version	      |
	     +---------------------+------------+---------------------+
	     |			   | False	| do not install pip  |
	     +---------------------+------------+---------------------+
	     |			   | False	| do not install  se- |
	     |			   |		| tuptools	      |
	     +---------------------+------------+---------------------+
	     |			   | False	| disable  the	peri- |
	     |			   |		| odic (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)	   |
	       +---------------------+-------+---------------------+

   activators
	+---------------------+---------------------+---------------------+
	| core	      options |			    |			  |
	| shared  across  all |			    |			  |
	| activators	      |			    |			  |
	+---------------------+---------------------+---------------------+
	|		      |	comma	  separated | activators  to gen- |
	|		      |	list of	 activators | erate - default  is |
	|		      |	supported	    | all      supported; |
	|		      |			    | choice  of:   bash, |
	|		      |			    | batch,	  cshell, |
	|		      |			    | fish, nushell, pow- |
	|		      |			    | ershell, python	  |
	+---------------------+---------------------+---------------------+
	|		      |			    | provides an  alter- |
	|		      |			    | native  prompt pre- |
	|		      |			    | fix for this  envi- |
	|		      |			    | ronment (value of	. |
	|		      |			    | means  name  of the |
	|		      |			    | current working di- |
	|		      |			    | rectory)		  |
	+---------------------+---------------------+---------------------+

   Python
       The primary interface to	virtualenv is the  command  line  application.
       However,	  it   can   also   be	used  programmatically	via  the  vir-
       tualenv.cli_run function	and the	Session	class.

       See Use virtualenv for usage examples.

   virtualenv module
       virtualenv.cli_run(args,	options=None, setup_logging=True, env=None)
	      Create a virtual environment given some command  line  interface
	      arguments.

	      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)

   Session class
       The Session class represents a virtualenv creation session and provides
       access to the created environment's properties.

       class virtualenv.run.session.Session(verbosity, app_data, interpreter,
       creator,	seeder,	activators)
	      Represents a virtual environment creation	session.

	      Parameters

		      verbosity (int) --

		      app_data	(AppData) --

		      interpreter (PythonInfo)	--

		      creator (Creator) --

		      seeder (Seeder) --

		      activators (list[Activator]) --

	      property verbosity: int
		     The verbosity of the run.

	      property interpreter: PythonInfo
		     Create  a virtual environment based on this reference in-
		     terpreter.

	      property creator:	Creator
		     The creator used to build the virtual  environment	 (must
		     be	compatible with	the interpreter).

	      property seeder: Seeder
		     The mechanism used	to provide the seed packages (pip, se-
		     tuptools, wheel).

	      property activators: list[-
	      virtualenv.activation.activator.Activator]
		     Activators	used to	generate activations scripts.

   VirtualEnvOptions
       Options	namespace  passed  to  plugin constructors, populated from the
       CLI, environment	variables, and configuration files.

       class virtualenv.config.cli.parser.VirtualEnvOptions(**kwargs)

	      Parameters
		     kwargs (Any) --

	      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", "de-
			    fault"), 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

   Explanation
       This page explains the design decisions and concepts behind virtualenv.
       It focuses on understanding why things work the way they	do.

   virtualenv vs venv vs uv
       Since  Python 3.3, the standard library includes	the venv module, which
       provides	basic virtual environment creation following PEP 405. 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+);	| Fast;	    caches    |	Fastest;    Rust |
  |		     | spawns  pip as a	| pre-built    in-    |	implementation,	 |
  |		     | subprocess    to	| stall	   images,    |	milliseconds.	 |
  |		     | seed.		| subsequent  cre-    |	Does   not  seed |
  |		     |			| ation	 <  1 sec-    |	pip/setuptools	 |
  |		     |			| ond.		      |	by default.	 |
  +------------------+------------------+---------------------+------------------+
  | Extensibility    | No  plugin  sys-	| Plugin    system    |	No  plugin  sys- |
  |		     | tem.		| for	discovery,    |	tem.		 |
  |		     |			| creation,  seed-    |			 |
  |		     |			| ing, and activa-    |			 |
  |		     |			| tion.		      |			 |
  +------------------+------------------+---------------------+------------------+
  | Cross-version    | Only  the Python	| Any	 installed    |	Any installed or |
  |		     | version it  runs	| Python       via    |	uv-managed	 |
  |		     | under.		| auto-discovery      |	Python.		 |
  |		     |			| (registry,	      |			 |
  |		     |			| uv-managed,	      |			 |
  |		     |			| PATH).	      |			 |
  +------------------+------------------+---------------------+------------------+
  | Upgradeability   | Tied  to	 Python	| Independent  via    |	Independent  via |
  |		     | releases.	| PyPI.		      |	its own	 release |
  |		     |			|		      |	cycle.		 |
  +------------------+------------------+---------------------+------------------+
  | Programmatic API | Basic   create()	| Full Python API;    |	Command	    line |
  |		     | function	only.	| can describe en-    |	only.		 |
  |		     |			| vironments with-    |			 |
  |		     |			| out	  creating    |			 |
  |		     |			| them.	  Used	by    |			 |
  |		     |			| tox,	   poetry,    |			 |
  |		     |			| pipx,	etc.	      |			 |
  +------------------+------------------+---------------------+------------------+
  | Type annotations | No      py.typed	| Fully	typed with    |	Not   applicable |
  |		     | marker;	limited	| PEP 561 py.typed    |	(Rust binary).	 |
  |		     | annotations.	| marker;  checked    |			 |
  |		     |			| by ty.	      |			 |
  +------------------+------------------+---------------------+------------------+
  | Best for	     | Zero   dependen-	| Plugin  extensi-    |	Maximum	  speed, |
  |		     | cies,	  basic	| bility, program-    |	already	using uv |
  |		     | needs.		| matic	 API, tool    |	for package man- |
  |		     |			| compatibility	(-    |	agement.	 |
  |		     |			| tox,		      |			 |
  |		     |			| virtualenvwrapper). |			 |
  +------------------+------------------+---------------------+------------------+
       [graph].SS How virtualenv works

       Python  packaging often faces a fundamental problem: different applica-
       tions require different versions	of the same library. If	Application  A
       needs  requests==2.25.1	but  Application B needs requests==2.28.0, in-
       stalling	both into the global site-packages directory  creates  a  con-
       flict. 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 dif-
	      ferent 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 Gits .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 en-
vironments are lightweight shells that borrow most  content  from  the	system
Python.	They contain only whats	needed to redirect Pythons 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  environ-
	 ments,	 since	they reference the system Pythons 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  versions
	  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.

   Python discovery
       Before  creating	a virtual environment, virtualenv must locate a	Python
       interpreter. The	interpreter determines the virtual environments	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}{archi-
	      tecture}{machine}	where:

	      	Implementation is alphabetic characters	(python	means any  im-
		plementation; 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 architec-
		ture).

	      	Machine	is the CPU instruction set architecture, e.g.  -arm64,
		-x86_64, -aarch64 (if omitted, means any machine). Cross-plat-
		form  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 architec-
		ture

	      	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	inter-
       preters using this strategy: [graph].INDENT 0.0

       1. Windows Registry (Windows only): Check registered  Python  installa-
	  tions	per PEP	514.

       2. uv-managed  installations:  Check the	UV_PYTHON_INSTALL_DIR environ-
	  ment variable	or platform-specific uv	Python directories for managed
	  Python installations.

       3. PATH search: Search for executables on the PATH environment variable
	  with names matching the specification.

   Version manager shim	resolution
       Version managers	like pyenv, mise,  and	asdf  place  lightweight  shim
       scripts	on  PATH  that	delegate  to the real Python binary. When vir-
       tualenv discovers a Python interpreter by running it as	a  subprocess,
       shims  may  resolve  to	the wrong Python version (typically the	system
       Python) because the shims resolution logic depends on shell environment
       state that doesnt 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  de-
       tected, virtualenv bypasses it and locates the real binary directly un-
       der  the	 version managers 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	direc-
	  tory.

       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 Pythons 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 versions	standard library content. This
	  can cause confusion when debugging version-specific behavior.

	  If you use a virtual environments Python as the target for  creating
	  another  virtual  environment,  virtualenv  will  detect  the	system
	  Python version and create an environment matching  the  actual  (up-
	  graded)  version,  not  the version reported by the virtual environ-
	  ment.

   Creators
       Creators	are  responsible  for  constructing  the  virtual  environment
       structure. virtualenv supports two types	of creators:

       venv creator
	      This  creator delegates the entire creation process to the stan-
	      dard librarys 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  Win-
	      dows 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 special-
	      ized creators for	different combinations of  Python  implementa-
	      tion (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	dont  require  subprocess  invocation,
	      theyre 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.

   Seeders
       After creating the virtual environment structure,  virtualenv  installs
       seed  packages  that  enable package management within the environment.
       The seed	packages are:

        pip - The package installer for Python	(always	installed).

        setuptools - Package development and installation  library  (disabled
	 by default on Python 3.12+).

        wheel	-  Support for the wheel binary	package	format (only installed
	 by default on Python 3.8).

       virtualenv supports two seeding	methods	 with  dramatically  different
       performance characteristics:

       pip seeder
	      This  method uses	the bundled pip	wheel to install seed packages
	      by spawning a child pip process. The subprocess performs a  full
	      installation,  including	unpacking  wheels and generating meta-
	      data. 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 applica-
	      tion 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 environments 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_OVER-
	      RIDE_APP_DATA environment	variable.

   Wheel acquisition
       Both  seeding  methods  require wheel files for the seed	packages. vir-
       tualenv 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 pro-
	      vide a baseline set of seed packages. Different Python  versions
	      require different	package	versions, so virtualenv	bundles	multi-
	      ple wheels to support its	wide Python version range.

       Upgraded	embedded wheels
	      Users  can  manually upgrade the embedded	wheels by running vir-
	      tualenv 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 be-
	      low).

       Extra search directories
	      Users can	specify	additional directories containing wheels using
	      the --extra-search-dir flag. This	is useful in air-gapped	 envi-
	      ronments or when using custom package builds.

       PyPI download
	      If  no suitable wheel is found in	the above locations, or	if the
	      --download flag is set, virtualenv will use pip to download  the
	      latest compatible	version	from PyPI.

   Periodic update mechanism
       To keep the seed	packages reasonably current without requiring users to
       manually	 upgrade  virtualenv or	run --upgrade-embed-wheels, virtualenv
       implements a periodic automatic update system: [graph]

       The 28-day waiting period protects users	 from  automatically  adopting
       newly  released packages	that might contain bugs.  The 1-hour delay af-
       ter download ensures continuous integration systems  dont  start	 using
       different  package  versions  mid-run, which could cause	confusing test
       failures.

       You can disable the  periodic  update  mechanism	 with  the  --no-peri-
       odic-update flag.

   Distribution	maintainer patching
       Operating  system  distributions	and package managers sometimes need to
       customize which seed package versions virtualenv	 uses.	They  want  to
       align virtualenvs bundled packages with system package versions.

       Distributions  can  patch  the virtualenv.seed.wheels.embed module, re-
       placing the get_embed_wheel function with their own implementation that
       returns distribution-provided wheels. If	they want to  use  virtualenvs
       test  suite for validation, they	should also provide the	BUNDLE_FOLDER,
       BUNDLE_SUPPORT, and MAX variables.

       Distributions  should  also   consider	patching   virtualenv.seed.em-
       bed.base_embed.PERIODIC_UPDATE_ON_BY_DEFAULT  to	 False,	 allowing  the
       system package manager to control seed package updates rather than vir-
       tualenvs	periodic update	mechanism. Users can  still  manually  request
       upgrades	 via --upgrade-embed-wheels, but automatic updates wont	inter-
       fere with system-managed	packages.

   Activators
       Activation scripts modify the current shell environment	to  prioritize
       the  virtual  environments  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 environments bin di-
	      rectory (Scripts on Windows) to the PATH	environment  variable.
	      This  ensures  that  when	you run	python,	pip, or	other executa-
	      bles, the	shell finds the	virtual	environments versions first.

       Environment variables
	      Activation sets several environment variables:

	      	VIRTUAL_ENV - Absolute path to the virtual environment	direc-
		tory.

	      	VIRTUAL_ENV_PROMPT  -  The prompt prefix (the environment name
		or custom value	from --prompt).

	      	PKG_CONFIG_PATH	- Modified to include the virtual environments
		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  environ-
	      ment  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  re-
	      verses  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, PowerShells default execution policy	is Re-
	  stricted, 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  environ-
	  ment,	 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  equiva-
       lent:

	  # 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
       Kapturs	blog  post Theres no magic: virtualenv edition,	which explains
       how virtualenv uses PATH	and PYTHONHOME	to  isolate  virtual  environ-
       ments.

   See also
        Use virtualenv	- Practical guides for common virtualenv tasks.

        Command line -	Complete CLI reference documentation.

   Plugins
       virtualenv can be extended via plugins using Python entry points. Plug-
       ins are automatically discovered	from the Python	environment where vir-
       tualenv	is  installed,	allowing you to	customize how virtual environ-
       ments are created, seeded, and activated.

   Extension points
       virtualenv provides four	extension points through entry point groups:

       virtualenv.discovery
	      Python interpreter discovery plugins. These plugins  locate  and
	      identify	Python	interpreters that will be used as the base for
	      creating virtual environments.

       virtualenv.create
	      Virtual environment creator plugins. These  plugins  handle  the
	      actual  creation of the virtual environment structure, including
	      copying or symlinking the	Python interpreter  and	 standard  li-
	      brary.

       virtualenv.seed
	      Seed  package  installer	plugins. These plugins install initial
	      packages (like pip, setuptools, wheel) into newly	 created  vir-
	      tual 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 reg-
       istered entry points, builds CLI	options	from them,  and	 executes  the
       selected	implementations	during environment creation.

   Your	first plugin
       This tutorial walks through creating a simple discovery plugin that lo-
       cates Python interpreters managed by pyenv.

   Create the package structure
       Set up a	new Python package with	the following structure:

	  virtualenv-pyenv/
	   pyproject.toml
	   src/
	       virtualenv_pyenv/
		   __init__.py

   Configure the entry point
       In pyproject.toml, declare your plugin as an entry point	under the vir-
       tualenv.discovery group:

	  [project]
	  name = "virtualenv-pyenv"
	  version = "0.1.0"
	  dependencies = ["virtualenv>=20"]

	  [project.entry-points."virtualenv.discovery"]
	  pyenv	= "virtualenv_pyenv:PyEnvDiscovery"

	  [build-system]
	  requires = ["setuptools>=61"]
	  build-backend	= "setuptools.build_meta"

   Implement the plugin
       In  src/virtualenv_pyenv/__init__.py, implement the discovery plugin by
       subclassing Discover:

	  from __future__ import annotations

	  import subprocess
	  from pathlib import Path

	  from virtualenv.discovery.discover import Discover
	  from virtualenv.discovery.py_info import PythonInfo

	  class	PyEnvDiscovery(Discover):
	      def __init__(self, options):
		  super().__init__(options)
		  self.python_spec = options.python if options.python else "python"

	      @classmethod
	      def add_parser_arguments(cls, parser):
		  parser.add_argument(
		      "--python",
		      dest="python",
		      metavar="py",
		      type=str,
		      default=None,
		      help="pyenv Python version to use	(e.g., 3.11.0)",
		  )

	      def run(self):
		  try:
		      result = subprocess.run(
			  ["pyenv", "which", "python"],
			  capture_output=True,
			  text=True,
			  check=True,
		      )
		      python_path = Path(result.stdout.strip())
		      return PythonInfo.from_exe(str(python_path))
		  except (subprocess.CalledProcessError, FileNotFoundError) as e:
		      raise RuntimeError(f"Failed to locate pyenv Python: {e}")

   Install the plugin
       Install your plugin in development mode alongside virtualenv:

	  $ pip	install	-e virtualenv-pyenv/

   Verify the plugin
       Check that virtualenv recognizes	your plugin by running:

	  $ virtualenv --discovery help

       The output should list pyenv as an available discovery  mechanism.  You
       can now use it:

	  $ virtualenv --discovery=pyenv myenv
	  created virtual environment CPython3.11.0.final.0-64 in 234ms
	    creator CPython3Posix(dest=/path/to/myenv, clear=False, no_vcs_ignore=False, global=False)
	    seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/path)
	      added seed packages: pip==23.0, setuptools==65.5.0, wheel==0.38.4
	    activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

   Plugin how-to guides
       This  page provides task-oriented guides	for creating each type of vir-
       tualenv plugin.

   Create a discovery plugin
       Discovery plugins locate	Python interpreters. Register your plugin  un-
       der the virtualenv.discovery entry point	group.

       Implement the Discover interface:

	  from virtualenv.discovery.discover import Discover
	  from virtualenv.discovery.py_info import PythonInfo

	  class	CustomDiscovery(Discover):
	      @classmethod
	      def add_parser_arguments(cls, parser):
		  parser.add_argument("--custom-opt", help="custom discovery option")

	      def __init__(self, options):
		  super().__init__(options)
		  self.custom_opt = options.custom_opt

	      def run(self):
		  # Locate Python interpreter and return PythonInfo
		  python_exe = self._find_python()
		  return PythonInfo.from_exe(str(python_exe))

	      def _find_python(self):
		  # Implementation-specific logic
		  pass

       Register	the entry point:

	  [virtualenv.discovery]
	  custom = your_package.discovery:CustomDiscovery

   Create a creator plugin
       Creator plugins build the virtual environment structure.	Register under
       virtualenv.create.

       Implement the Creator interface:

	  from virtualenv.create.creator import	Creator

	  class	CustomCreator(Creator):
	      @classmethod
	      def add_parser_arguments(cls, parser, interpreter):
		  parser.add_argument("--custom-creator-opt", help="custom creator option")

	      def __init__(self, options, interpreter):
		  super().__init__(options, interpreter)
		  self.custom_opt = options.custom_creator_opt

	      def create(self):
		  # Create directory structure
		  self.bin_dir.mkdir(parents=True, exist_ok=True)
		  # Copy or symlink Python executable
		  self.install_python()
		  # Set	up site-packages
		  self.install_site_packages()
		  # Write pyvenv.cfg
		  self.set_pyenv_cfg()

       Register	 the  entry point using	a naming pattern that matches platform
       and Python version:

	  [virtualenv.create]
	  cpython3-posix = virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Posix
	  cpython3-win = virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Windows

   Create a seeder plugin
       Seeder plugins install initial packages into the	 virtual  environment.
       Register	under virtualenv.seed.

       Implement the Seeder interface:

	  from virtualenv.seed.seeder import Seeder

	  class	CustomSeeder(Seeder):
	      @classmethod
	      def add_parser_arguments(cls, parser, interpreter, app_data):
		  parser.add_argument("--custom-seed-opt", help="custom	seeder option")

	      def __init__(self, options, enabled, app_data):
		  super().__init__(options, enabled, app_data)
		  self.custom_opt = options.custom_seed_opt

	      def run(self, creator):
		  # Install packages into creator.bin_dir / creator.script("pip")
		  self._install_packages(creator)

	      def _install_packages(self, creator):
		  # Implementation-specific logic
		  pass

       Register	the entry point:

	  [virtualenv.seed]
	  custom = your_package.seed:CustomSeeder

   Create an activator plugin
       Activator  plugins  generate  shell  activation scripts.	Register under
       virtualenv.activate.

       Implement the Activator interface:

	  from virtualenv.activation.activator import Activator

	  class	CustomShellActivator(Activator):
	      def generate(self, creator):
		  # Generate activation	script content
		  script_content = self._render_template(creator)
		  # Write to activation	directory
		  dest = creator.bin_dir / self.script_name
		  dest.write_text(script_content)

	      def _render_template(self, creator):
		  # Return activation script content
		  return f"""
		  # Custom shell activation script
		  export VIRTUAL_ENV="{creator.dest}"
		  export PATH="{creator.bin_dir}:$PATH"
		  """

	      @property
	      def script_name(self):
		  return "activate.custom"

       Register	the entry point:

	  [virtualenv.activate]
	  bash = virtualenv.activation.bash:BashActivator
	  fish = virtualenv.activation.fish:FishActivator
	  custom = your_package.activation:CustomShellActivator

   Package and distribute a plugin
       Use pyproject.toml to declare entry points:

	  [project]
	  name = "virtualenv-custom-plugin"
	  version = "1.0.0"
	  dependencies = ["virtualenv>=20.0.0"]

	  [project.entry-points."virtualenv.discovery"]
	  custom = "virtualenv_custom.discovery:CustomDiscovery"

	  [project.entry-points."virtualenv.create"]
	  custom-posix = "virtualenv_custom.creator:CustomCreator"

	  [project.entry-points."virtualenv.seed"]
	  custom = "virtualenv_custom.seeder:CustomSeeder"

	  [project.entry-points."virtualenv.activate"]
	  custom = "virtualenv_custom.activator:CustomActivator"

	  [build-system]
	  requires = ["setuptools>=61"]
	  build-backend	= "setuptools.build_meta"

       Install your plugin alongside virtualenv:

	  $ pip	install	virtualenv-custom-plugin

       Or in development mode:

	  $ pip	install	-e /path/to/virtualenv-custom-plugin

       Test your plugin	by creating a virtual environment:

	  $ virtualenv --discovery=custom --creator=custom-posix --seeder=custom --activators=custom test-env

   Plugin API reference
       This page documents the interfaces that plugins must implement.

   Discovery
       Discovery plugins locate	Python interpreters for	creating virtual envi-
       ronments.

       class virtualenv.discovery.discover.Discover(options)

	      Parameters
		     options (VirtualEnvOptions) --

	      classmethod add_parser_arguments(parser)

		     Parameters
			    parser (ArgumentParser) --

		     Return type
			    None

	      abstract run()

		     Return type
			    Optional[PythonInfo]

	      property interpreter: python_discovery._py_info.PythonInfo |
	      None

		     Returns
			    the	interpreter as returned	by run(), cached

   PythonInfo
       Discovery plugins return	a PythonInfo object describing the located in-
       terpreter.

       class virtualenv.discovery.py_info.PythonInfo
	      Contains information for a Python	interpreter.

	      install_path(key)
		     Return the	relative installation path for a given instal-
		     lation scheme key.

		     Parameters
			    key	(str) --  sysconfig  installation  scheme  key
			    (e.g. "scripts", "purelib").

		     Return type
			    str

	      property version_str: str
		     The   full	 version  as  major.minor.micro	 string	 (e.g.
		     3.13.2).

	      property version_release_str: str
		     The release version as major.minor	string (e.g. 3.13).

	      property python_name: str
		     The   python   executable	 name	as   pythonX.Y	 (e.g.
		     python3.13).

	      property is_old_virtualenv: bool
		     True  if  this  interpreter runs inside an	old-style vir-
		     tualenv (has real_prefix).

	      property is_venv:	bool
		     True if this interpreter runs inside a PEP	405 venv  (has
		     base_prefix).

	      sysconfig_path(key, config_var=None, sep='/')
		     Return  the  sysconfig install path for a scheme key, op-
		     tionally substituting config variables.

		     Parameters

			     key (str)	-- sysconfig path key (e.g. "purelib",
			      "include").

			     config_var  (Optional[dict[str,  str]])  --  re-
			      placement	 mapping for sysconfig variables; when
			      None uses	the interpreter's own values.

			     sep (str)	-- path	separator to use  in  the  re-
			      sult.

		     Return type
			    str

	      property system_include: str
		     The path to the system include directory for C headers.

	      property system_prefix: str
		     The prefix	of the system Python this interpreter is based
		     on.

	      property system_exec_prefix: str
		     The  exec prefix of the system Python this	interpreter is
		     based on.

	      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).

	      classmethod clear_cache(cache)
		     Clear all cached interpreter information from cache.

		     Parameters
			    cache (PyInfoCache)	-- the cache store to clear.

		     Return type
			    None

	      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	imple-
			      mentation	name must match	exactly.

		     Return type
			    bool

	      classmethod current(cache=None)
		     Locate the	current	host interpreter information.

		     Parameters
			    cache (Optional[PyInfoCache]) -- interpreter meta-
			    data cache;	when None results are not cached.

		     Return type
			    PythonInfo

	      classmethod current_system(cache=None)
		     Locate the	current	system	interpreter  information,  re-
		     solving through any virtualenv layers.

		     Parameters
			    cache (Optional[PyInfoCache]) -- interpreter meta-
			    data cache;	when None results are not cached.

		     Return type
			    PythonInfo

	      to_json()
		     Serialize this interpreter	information to a JSON string.

		     Return type
			    str

	      to_dict()
		     Convert  this  interpreter	information to a plain dictio-
		     nary.

		     Return type
			    dict[str, object]

	      classmethod from_exe(exe,	cache=None, *, raise_on_error=True,
	      ignore_cache=False, resolve_to_host=True,	env=None)
		     Get the python information	for a given executable path.

		     Parameters

			     exe (str)	-- path	to the Python executable.

			     cache  (Optional[PyInfoCache])  --   interpreter
			      metadata	 cache;	 when  None  results  are  not
			      cached.

			     raise_on_error (bool) -- raise  on  failure  in-
			      stead of returning None.

			     ignore_cache  (bool)  --	bypass	the  cache and
			      re-query the interpreter.

			     resolve_to_host (bool) --	resolve	 through  vir-
			      tualenv layers to	the system interpreter.

			     env (Optional[Mapping[str, str]])	-- environment
			      mapping; defaults	to os.environ.

		     Return type
			    Optional[PythonInfo]

	      classmethod from_json(payload)
		     Deserialize interpreter information from a	JSON string.

		     Parameters
			    payload (str) -- JSON produced by to_json().

		     Return type
			    PythonInfo

	      classmethod from_dict(data)
		     Reconstruct a PythonInfo from a plain dictionary.

		     Parameters
			    data (dict[str, object]) --	dictionary produced by
			    to_dict().

		     Return type
			    PythonInfo

	      classmethod resolve_to_system(cache, target)
		     Walk virtualenv/venv prefix chains	to find	the underlying
		     system interpreter.

		     Parameters

			     cache   (Optional[PyInfoCache])  --  interpreter
			      metadata	cache;	when  None  results  are   not
			      cached.

			     target  (PythonInfo)  --	the interpreter	to re-
			      solve.

		     Return type
			    PythonInfo

	      discover_exe(cache, prefix, *, exact=True, env=None)
		     Discover a	matching Python	executable under a given  pre-
		     fix directory.

		     Parameters

			     cache   (PyInfoCache)  --	 interpreter  metadata
			      cache.

			     prefix (str) -- directory	prefix to  search  un-
			      der.

			     exact (bool) -- when True, require an exact ver-
			      sion match.

			     env (Optional[Mapping[str, str]])	-- environment
			      mapping; defaults	to os.environ.

		     Return type
			    PythonInfo

   App data
       The application data interface used by plugins for caching.

       class virtualenv.app_data.base.AppData
	      Abstract storage interface for the virtualenv application.

	      abstract close()
		     Called before virtualenv exits.

		     Return type
			    None

	      abstract reset()
		     Called when the user passes in the	reset app data.

		     Return type
			    None

	      abstract py_info(path)
		     Return a content store for	cached interpreter information
		     at	the given path.

		     Parameters
			    path (Path)	-- the interpreter executable path

		     Return type
			    ContentStore

		     Returns
			    a content store for	the cached data

	      abstract py_info_clear()
		     Clear all cached interpreter information.

		     Return type
			    None

	      property can_update: bool
		     True if this app data store supports updating cached con-
		     tent.

	      abstract embed_update_log(distribution, for_py_version)
		     Return a content store for	the embed update log of	a dis-
		     tribution.

		     Parameters

			     distribution  (str)  --  the  package name (e.g.
			      pip)

			     for_py_version (str) -- the target  Python  ver-
			      sion string

		     Return type
			    ContentStore

		     Returns
			    a content store for	the update log

	      property house: Path
		     The root directory	of the application data	store.

	      property transient: bool
		     True  if  this  app  data store is	transient and does not
		     persist across runs.

	      abstract wheel_image(for_py_version, name)
		     Return the	path to	a cached wheel image.

		     Parameters

			     for_py_version (str) -- the target  Python  ver-
			      sion string

			     name (str) -- the	package	name

		     Return type
			    Path

		     Returns
			    the	path to	the cached wheel

	      ensure_extracted(path, to_folder=None)
		     Ensure  a	path is	available on disk, extracting from zi-
		     papp 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

	      abstract extract(path, to_folder)
		     Extract a path from the zipapp to a location on disk.

		     Parameters

			     path (Path) -- the path to extract

			     to_folder	 (Optional[Path])  --  optional	target
			      directory

		     Return type
			    Generator[Path]

		     Returns
			    yields the extracted path

	      abstract locked(path)
		     Acquire an	exclusive lock on the given path.

		     Parameters
			    path (Path)	-- the path to lock

		     Return type
			    Generator[None]

   Creators
       Creator plugins build the virtual environment directory	structure  and
       install the Python interpreter.

       class virtualenv.create.creator.CreatorMeta

       class virtualenv.create.creator.Creator(options,	interpreter)
	      A	 class that given a python Interpreter creates a virtual envi-
	      ronment.

	      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

	      classmethod can_create(interpreter)
		     Determine if we can create	a virtual environment.

		     Parameters
			    interpreter	 (PythonInfo)  --  the	interpreter in
			    question

		     Return type
			    Optional[CreatorMeta]

		     Returns
			    None if we can't create, any other	object	other-
			    wise     that     will     be     forwarded	    to
			    add_parser_arguments()

	      classmethod add_parser_arguments(parser, interpreter, meta,
	      app_data)
		     Add CLI arguments for the creator.

		     Parameters

			     parser (ArgumentParser) -- the CLI parser

			     app_data	(AppData)  --  the  application	  data
			      folder

			     interpreter   (PythonInfo)  --  the  interpreter
			      we're asked to create virtual environment	for

			     meta  (CreatorMeta)  --  value  as  returned  by
			      can_create()

		     Return type
			    None

	      abstract create()
		     Perform the virtual environment creation.

		     Return type
			    None

	      add_cachedir_tag()
		     Generate  a  file indicating that this is not meant to be
		     backed up.

		     Return type
			    None

	      setup_ignore_vcs()
		     Generate ignore instructions for version control systems.

		     Return type
			    None

   Seeders
       Seeder plugins install initial packages (like pip,  setuptools,	wheel)
       into the	virtual	environment.

       class virtualenv.seed.seeder.Seeder(options, enabled)
	      A	seeder will install some seed packages into a virtual environ-
	      ment.

	      Parameters

		      options (VirtualEnvOptions) --

		      enabled (bool) --

	      Create.

	      Parameters

		      options	(VirtualEnvOptions)  --	 the parsed options as
		       defined within add_parser_arguments()

		      enabled (bool) -- a flag	weather	the seeder is  enabled
		       or not

	      classmethod add_parser_arguments(parser, interpreter, app_data)
		     Add CLI arguments for this	seed mechanisms.

		     Parameters

			     parser (ArgumentParser) -- the CLI parser

			     app_data (AppData) -- the	CLI parser

			     interpreter (PythonInfo) -- the interpreter this
			      virtual environment is based of

		     Return type
			    None

	      abstract run(creator)
		     Perform the seed operation.

		     Parameters
			    creator   (Creator)	  --  the  creator  (based  of
			    virtualenv.create.creator.Creator) we used to cre-
			    ate	this virtual environment

		     Return type
			    None

   Activators
       Activator plugins generate shell-specific activation scripts.

       class virtualenv.activation.activator.Activator(options)
	      Generates	activate script	for the	virtual	environment.

	      Parameters
		     options (VirtualEnvOptions) --

	      Create a new activator generator.

	      Parameters
		     options (VirtualEnvOptions) -- the	parsed options as  de-
		     fined within add_parser_arguments()

	      classmethod supports(interpreter)
		     Check  if the activation script is	supported in the given
		     interpreter.

		     Parameters
			    interpreter	(PythonInfo)  --  the  interpreter  we
			    need to support

		     Return type
			    bool

		     Returns
			    True if supported, False otherwise

	      classmethod add_parser_arguments(parser, interpreter)
		     Add CLI arguments for this	activation script.

		     Parameters

			     parser (ArgumentParser) -- the CLI parser

			     interpreter (PythonInfo) -- the interpreter this
			      virtual environment is based of

		     Return type
			    None

	      abstract generate(creator)
		     Generate activate script for the given creator.

		     Parameters
			    creator   (Creator)	  --  the  creator  (based  of
			    virtualenv.create.creator.Creator) we used to cre-
			    ate	this virtual environment

		     Return type
			    list[Path]

   Plugin architecture
       This page explains how virtualenvs plugin system	works internally.

   Entry points
       virtualenv uses Python entry points (setuptools	/  importlib.metadata)
       to  discover  plugins.  Each  plugin  registers under one of four entry
       point groups:

        virtualenv.discovery

        virtualenv.create

        virtualenv.seed

        virtualenv.activate

       At startup, virtualenv loads all	registered  entry  points  from	 these
       groups  and  makes them available as CLI	options.  Built-in implementa-
       tions  are  registered  in  virtualenvs	 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	 envi-
       ronment as virtualenv, the plugins become immediately available without
       additional configuration.

   Plugin lifecycle
       The  following  diagram	shows how plugins are discovered and executed:
       [graph]

       The lifecycle follows these stages:

       1. virtualenv starts and	discovers all entry points from	the four  plu-
	  gin 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	 acti-
	  vate

       5. Each stage passes its	output to the next stage

   Extension point design
       Each extension point follows a consistent pattern:

       Base abstract class
	      Each extension point defines a base  abstract  class  (Discover,
	      Creator, Seeder, Activator) that specifies the interface plugins
	      must implement.

       Built-in	implementations
	      virtualenv includes built-in implementations registered as entry
	      points  in  its  own  pyproject.toml.  For example, the built-in
	      CPython creator is registered as cpython3-posix.

       Third-party plugins
	      External packages	implement  the	base  interface	 and  register
	      their  own  entry	 points	 under the same	group. When installed,
	      they appear alongside built-in options.

       CLI selection
	      Command-line flags (--discovery, --creator, --seeder,  --activa-
	      tors)  allow users to select which implementation	to use.	Multi-
	      ple activators can be selected simultaneously.

       Parser integration
	      Each  plugin  can	  contribute   CLI   arguments	 through   the
	      add_parser_arguments classmethod.	These arguments	appear in vir-
	      tualenv --help and are available when the	plugin is selected.

   How plugins interact
       Plugins	execute	in a pipeline where each stage depends on the previous
       one:

       Discovery  Creator
	      The discovery plugin produces a PythonInfo object	describing the
	      source Python interpreter. This object contains  metadata	 about
	      the  Python version, platform, paths, and	capabilities. The cre-
	      ator 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
	      environments  bin	 directory,  site-packages,  and  Python  exe-
	      cutable. The seeder plugin uses these paths to install packages.

       Seeder  Activator
	      After seeding completes, activator plugins use the  Creator  ob-
	      ject  to generate	shell activation scripts. These	scripts	refer-
	      ence the environments 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  activa-
       tors.

   Plugin isolation
       Plugins	within	the  same  extension  point  do	not interact with each
       other. Only one discovery and one creator plugin	can  run  per  invoca-
       tion, though multiple activators	can run	simultaneously.	This isolation
       keeps plugins simple and	focused	on their specific task.

   Development
   Getting started
       virtualenv is a volunteer maintained open source	project	and we welcome
       contributions  of  all  forms.  The  sections  below  will help you get
       started with development, testing, and documentation. Were 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.

   Setup
       virtualenv is a command line application	written	in Python. To work  on
       it, youll need:

       

	 Source	code: available	on GitHub. You can use git to clone the
		repository:

	    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.

   Running from	source tree
       The  easiest way	to do this is to generate the development tox environ-
       ment, and then invoke virtualenv	from under the .tox/dev	folder

	  tox -e dev
	  .tox/dev/bin/virtualenv  # on	Linux
	  .tox/dev/Scripts/virtualenv  # on Windows

   Running tests
       virtualenvs tests are written using the pytest test framework.  tox  is
       used to automate	the setup and execution	of virtualenvs tests.

       To run tests locally execute:

	  tox -e py

       This will run the test suite for	the same Python	version	as under which
       tox  is	installed. Alternatively you can specify a specific version of
       python by using the pyNN	format,	such as: py38, pypy3, etc.

       tox has been configured to forward any additional arguments it is given
       to pytest. This enables the use of pytests 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 vari-
       ous shell activators (bash, fish, powershell, etc).  These  tests  will
       automatically be	skipped	if these are not present, note however that in
       CI  all	tests  are  run; so even if all	tests succeed locally for you,
       they may	still fail in the CI.

   Running linters
       virtualenv uses	pre-commit  for	 managing  linting  of	the  codebase.
       pre-commit  performs various checks on all files	in virtualenv and uses
       tools that help follow a	consistent code	style within the codebase.  To
       use linters locally, run:

	  tox -e fix

       NOTE:
	  Avoid	 using	# noqa comments	to suppress linter warnings - wherever
	  possible, warnings should be fixed instead.  # noqa comments are re-
	  served for rare cases	where  the  recommended	 style	causes	severe
	  readability problems.

   Type	checking
       virtualenv  ships  a PEP	561 py.typed marker and	has comprehensive type
       annotations across the entire codebase.	 This  means  downstream  con-
       sumers  and  type checkers automatically	recognize virtualenv as	an in-
       line-typed package.

       All new code must include complete type annotations for function	 para-
       meters and return types.	To verify annotations locally, run:

	  tox -e type

       This  uses ty (Astrals Rust-based type checker) to validate annotations
       against Python 3.14. A second environment checks	compatibility with the
       minimum supported version:

	  tox -e type-3.8

       Both environments validate that annotations are consistent and correct.

   Annotation guidelines
        Use from __future__ import annotations	at the	top  of	 every	module
	 (enforced by ruffs required-imports setting).

        Place	imports	 that  are  only needed	for type checking inside an if
	 TYPE_CHECKING:	block to avoid runtime overhead.

        Ruffs 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] com-
	 ment and a brief justification.

   Building documentation
       virtualenvs documentation is built using	Sphinx.	The  documentation  is
       written in reStructuredText. To build it	locally, run:

	  tox -e docs

       The  built  documentation  can be found in the .tox/docs_out folder and
       may be viewed by	opening	index.html within that folder.

   Release
       virtualenvs release schedule is tied to pip and setuptools.  We	bundle
       the latest version of these libraries so	each time theres a new version
       of  any of these, there will be a new virtualenv	release	shortly	after-
       wards (we usually wait just a few days to avoid pulling in  any	broken
       releases).

   Performing a	release
       A full release publishes	to PyPI, creates a GitHub Release with the zi-
       papp   attached,	 and  updates  get-virtualenv  so  that	 https://boot-
       strap.pypa.io/virtualenv.pyz serves the new version.

   Version bumping
       The --version argument to tox r -e release controls the version.	It de-
       faults 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, cre-
       ates  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

	  tox r	-e release

       Pass  --version	<bump>	to  override  the  default auto	behavior (e.g.
       --version minor).

   Contributing
   Submitting pull requests
       Submit pull requests against the	main branch, providing a good descrip-
       tion of what youre doing	and why. You must  have	 legal	permission  to
       distribute  any code you	contribute to virtualenv and it	must be	avail-
       able under the MIT License. Provide tests that cover your  changes  and
       run  the	 tests locally first. virtualenv supports multiple Python ver-
       sions 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-con-
       tained, 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  hap-
       pening  within  the  PR.	 Instead, the feature should be	broken up into
       smaller,	independent parts which	can be reviewed	and  merged  individu-
       ally.

       Additionally,  avoid  including	cosmetic changes to code that is unre-
       lated to	your change, as	these make reviewing the  PR  more  difficult.
       Examples	include	re-flowing text	in comments or documentation, or addi-
       tion or removal of blank	lines or whitespace within lines. Such changes
       can be made separately, as a formatting cleanup PR, if needed.

   Automated testing
       All pull	requests and merges to main branch are tested using GitHub Ac-
       tions  (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 GitHubs Web UI for the pull request. You can also find links
       to the CI services pages	for the	specific builds	in the form of Details
       links, in case the CI run fails and you wish to view the	output.

       To trigger CI to	run again for a	pull request, you can close  and  open
       the  pull  request  or  submit  another	change to the pull request. If
       needed, project	maintainers  can  manually  trigger  a	restart	 of  a
       job/build.

   NEWS	entries
       The  changelog.rst  file	is managed using towncrier 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  is-
       sues/PRs	 you may create	a file for each	of them	with the same contents
       and towncrier will deduplicate them.

   Contents of a NEWS entry
       The contents of this file are reStructuredText formatted	text that will
       be used as the content of the news file entry.  You do not need to ref-
       erence 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 rele-
       vant to an end user.

   Choosing the	type of	NEWS entry
       A trivial change	is anything that does not warrant an entry in the news
       file. Some examples are:	code refactors that dont  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  ran-
       domly  named,  empty  file to the news/ directory with the extension of
       .trivial.

   Becoming a maintainer
       If you want to become an	official maintainer, start by helping out.  As
       a  first	 step,	we  welcome  you to triage issues on virtualenvs issue
       tracker.	virtualenv maintainers provide triage abilities	 to  contribu-
       tors  once  they	 have  been around for some time and contributed posi-
       tively to the project. This is optional and highly recommended for  be-
       coming  a virtualenv maintainer.	Later, when you	think youre 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 vari-
	  ous  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

   Release History
   v[UNRELEASED	DRAFT] (2026-06-11)
       No significant changes.

   v21.2.0 (2026-03-09)
   Features - 21.2.0
        Update	embed wheel  generator	(tasks/upgrade_wheels.py)  to  include
	 type annotations in generated output -	by @rahuldevikar. (#3075)

   Bugfixes - 21.2.0
        Pass --without-scm-ignore-files to subprocess venv on Python 3.13+ so
	 virtualenv  controls  .gitignore  creation,  fixing  flaky  test_cre-
	 ate_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  reloca-
	 tion  fallback,  fixing  incorrect  PATH  when	 sourcing the activate
	 script	from a different directory - by	@gaborbernat. (#3090)

   v21.1.0 (2026-02-27)
   Features - 21.1.0
        Add comprehensive type	annotations across  the	 entire	 codebase  and
	 ship  a  PEP  561  py.typed  marker  so downstream consumers and type
	 checkers  recognize  virtualenv  as  an  inline-typed	package	 -  by
	 @rahuldevikar.	(#3075)

   v21.0.0 (2026-02-25)
   Deprecations	and Removals - 21.0.0
        The  Python  discovery	 logic	has  been  extracted into a standalone
	 python-discovery package on PyPI (documentation) and is now  consumed
	 as  a	dependency. If you previously imported discovery internals di-
	 rectly	(e.g. from  virtualenv.discovery.py_info  import  PythonInfo),
	 switch	 to from python_discovery import PythonInfo. Backward-compati-
	 bility	re-export shims	are provided at	 virtualenv.discovery.py_info,
	 virtualenv.discovery.py_spec,		and	    virtualenv.discov-
	 ery.cached_py_info, however these are considered unsupported and  may
	 be removed in a future	release	- by @gaborbernat.  (#3070)

   v20.39.1 (2026-02-25)
   Features - 20.39.1
        Add  support  for  creating virtual environments with RustPython - by
	 @elmjag. (#3010)

   v20.39.0 (2026-02-23)
   Features - 20.39.0
        Automatically resolve version manager shims (pyenv,  mise,  asdf)  to
	 the  real Python binary during	discovery, preventing incorrect	inter-
	 preter	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 nor-
	 malization  (amd64  x86_64, aarch64  arm64). Omitting the suffix pre-
	 serves	existing behavior - by @rahuldevikar. (#3059)

   v20.38.0 (2026-02-19)
   Features - 20.38.0
        Store app data	(pip/setuptools/wheel caches) under the	OS  cache  di-
	 rectory  (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 virtualenvs lib/pkgconfig	directory is now automatically
	 prepended  to PKG_CONFIG_PATH on activation and restored on deactiva-
	 tion, 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	asser-
	 tions and explicit None checks	- by @rahuldevikar. (#3029)

   Bugfixes - 20.38.0
        Exclude  pywin32  DLLs	 (pywintypes*.dll,  pythoncom*.dll) from being
	 copied	to the Scripts directory during	virtualenv  creation  on  Win-
	 dows. 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_CON-
	 FIG_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)

   v20.36.1 (2026-01-09)
   Bugfixes - 20.36.1
        Fix TOCTOU vulnerabilities in app_data	and  lock  directory  creation
	 that	could	be   exploited	via  symlink  attacks  -  reported  by
	 @tsigouris007,	fixed by @gaborbernat. (#3013)

   v20.36.0 (2026-01-07)
   Features - 20.36.0
        Add support for PEP 440 version  specifiers  in  the  --python	 flag.
	 Users	can  now  specify Python versions using	operators like >=, <=,
	 ~=, etc. For example:	virtualenv  --python=">=3.12"  myenv  .	 (:is-
	 sue:`2994)

   v20.35.4 (2025-10-28)
   Bugfixes - 20.35.4
        Fix  race condition in	_virtualenv.py when file is overwritten	during
	 import, preventing NameError when _DISTUTILS_PATCH is accessed	 -  by
	 @gracetyy. (#2969)

        Upgrade embedded wheels:

	  pip to 25.3 from 25.2 (#2989)

   v20.35.3 (2025-10-10)
   Bugfixes - 20.35.3
        Accept	RuntimeError in	test_too_many_open_files, by @esafak (#2935)

   v20.35.2 (2025-10-10)
   Bugfixes - 20.35.2
        Revert	 out changes related to	the extraction of the discovery	module
	 - by @gaborbernat. (#2978)

   v20.35.1 (2025-10-09)
   Bugfixes - 20.35.1
        Patch get_interpreter to handle  missing  cache  and  app_data	 -  by
	 @esafak (#2972)

        Fix  backwards	 incompatible changes to PythonInfo - by @gaborbernat.
	 (#2975)

   v20.35.0 (2025-10-08)
   Features - 20.35.0
        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)

   Bugfixes - 20.35.0
        Replaced direct references to tcl/tk library paths with getattr -  by
	 @esafak (#2944)

        Restore absolute import of fs_is_case_sensitive - by @esafak. (#2955)

   v20.34.0 (2025-08-13)
   Features - 20.34.0
        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)

   Bugfixes - 20.34.0
        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)

   v20.33.1 (2025-08-05)
   Bugfixes - 20.33.1
        Correctly  unpack  _get_tcl_tk_libs()	response  in  PythonInfo. Con-
	 tributed by @esafak. (#2930)

        Restore   py_info.py	timestamp   in	  test_py_info_cache_invalida-
	 tion_on_py_info_change	Contributed by @esafak.	 (#2933)

   v20.33.0 (2025-08-03)
   Features - 20.33.0
        Added	support	 for  Tcl  and	Tkinter. Youre welcome.	Contributed by
	 @esafak. (#425)

   Bugfixes - 20.33.0
        Prevent logging setup when help is passed, fixing a flaky test.  Con-
	 tributed by @esafak. (#u)

        Fix  cache  invalidation  for	PythonInfo by hashing py_info.py. Con-
	 tributed 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-sup-
	 port  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  vir-
	 tualenvs locking mechanism. Contributed by @esafak. (#2834)

        Support  renamed  Windows  venv redirector (venvlauncher.exe and ven-
	 vwlauncher.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)

   v20.32.0 (2025-07-20)
   Features - 20.32.0
        Warn  on  incorrect  invocation  of  Nushell  activation  script - by
	 @esafak. (#nushell_activation)

        Discover uv-managed Python installations (#2901)

   Bugfixes - 20.32.0
        Ignore	missing	absolute paths for python discovery -  by  @esafak  (-
	 #2870)

        Upgrade  embedded setuptools to 80.9.0	from 80.3.1 - by @gaborbernat.
	 (#2900)

   v20.31.2 (2025-05-08)
       No significant changes.

   v20.31.1 (2025-05-05)
   Bugfixes - 20.31.1
        Upgrade embedded wheels:

	  pip to 25.1.1 from 25.1

	  setuptools to 80.3.1	from 78.1.0 (#2880)

   v20.31.0 (2025-05-05)
   Features - 20.31.0
        No longer bundle wheel	wheels (except on Python 3.8), setuptools  in-
	 cludes	native bdist_wheel support.  Update pip	to 25.1. (#2868)

   Bugfixes - 20.31.0
        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)

   v20.30.0 (2025-03-31)
   Features - 20.30.0
        Add support for GraalPy. (#2832)

   Bugfixes - 20.30.0
        Upgrade embedded wheels:

	  setuptools to 78.1.0	from 75.3.2 (#2863)

   v20.29.3 (2025-03-06)
   Bugfixes - 20.29.3
        Ignore	unreadable directories in PATH.	(#2794)

   v20.29.2 (2025-02-10)
   Bugfixes - 20.29.2
        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)

   v20.29.1 (2025-01-17)
   Bugfixes - 20.29.1
        Fix PyInfo cache incompatibility warnings - by	@robsdedude. (#2827)

   v20.29.0 (2025-01-15)
   Features - 20.29.0
        Add support for selecting free-threaded  Python  interpreters,	 e.g.,
	 python3.13t. (#2809)

   Bugfixes - 20.29.0
        Upgrade embedded wheels:

	  setuptools to 75.8.0	from 75.6.0 (#2823)

   v20.28.1 (2025-01-02)
   Bugfixes - 20.28.1
        Skip tcsh tests on broken tcsh	versions - by @gaborbernat. (#2814)

   v20.28.0 (2024-11-25)
   Features - 20.28.0
        Write CACHEDIR.TAG file on creation - by user:neilramsay. (#2803)

   v20.27.2 (2024-11-25)
   Bugfixes - 20.27.2
        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)

   v20.27.1 (2024-10-28)
   Bugfixes - 20.27.1
        Upgrade embedded wheels:

	  pip to 24.3.1 from 24.2 (#2789)

   v20.27.0 (2024-10-17)
   Features - 20.27.0
        Drop  3.7 support as the CI environments no longer allow it running -
	 by @gaborbernat. (#2758)

   Bugfixes - 20.27.0
        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)

   v20.26.6 (2024-09-27)
   Bugfixes - 20.26.6
        Properly  quote string	placeholders in	activation script templates to
	 mitigate potential command injection -	by @y5c4l3. (#2768)

   v20.26.5 (2024-09-17)
   Bugfixes - 20.26.5
        Upgrade embedded wheels:  setuptools  to  75.1.0  from	 74.1.2	 -  by
	 @gaborbernat. (#2765)

   v20.26.4 (2024-09-07)
   Bugfixes - 20.26.4
        no  longer  create  ()	 output	in console during activation of	a vir-
	 tualenv 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)

   v20.26.3 (2024-06-21)
   Bugfixes - 20.26.3
        Upgrade embedded wheels:

	  setuptools to 70.1.0	from 69.5.1

	  pip to 24.1 from 24.0 (#2741)

   v20.26.2 (2024-05-13)
   Bugfixes - 20.26.2
        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)

   v20.26.1 (2024-04-29)
   Bugfixes - 20.26.1
        fix PATH-based	Python discovery on Windows - by @ofek.	(#2712)

   v20.26.0 (2024-04-23)
   Bugfixes - 20.26.0
        allow builtin	discovery  to  discover	 specific  interpreters	 (e.g.
	 python3.12)   given   an   unspecific	 spec  (e.g.   python3)	 -  by
	 @flying-sheep.	(#2709)

   v20.25.3 (2024-04-17)
   Bugfixes - 20.25.3
        Python	3.13.0a6 renamed pathmod to parser. (#2702)

   v20.25.2 (2024-04-16)
   Bugfixes - 20.25.2
        Upgrade embedded wheels:

	  setuptools of 69.1.0	to 69.5.1

	  wheel of 0.42.0 to 0.43.0 (#2699)

   v20.25.1 (2024-02-21)
   Bugfixes - 20.25.1
        Upgrade embedded wheels:

	  setuptools to 69.0.3	from 69.0.2

	  pip to 23.3.2 from 23.3.1 (#2681)

        Upgrade embedded wheels:

	  pip 23.3.2 to 24.0,

	  setuptools 69.0.3 to	69.1.0.	(#2691)

   Misc	- 20.25.1
        #2688

   v20.25.0 (2023-12-01)
   Features - 20.25.0
        The tests now pass on the CI with Python 3.13.0a2 - by	 @hroncok.  (-
	 #2673)

   Bugfixes - 20.25.0
        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)

   v20.24.6 (2023-10-23)
   Bugfixes - 20.24.6
        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)

   v20.24.5 (2023-09-08)
   Bugfixes - 20.24.5
        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)

   v20.24.4 (2023-08-30)
   Bugfixes - 20.24.4
        Upgrade embedded wheels:

	  setuptools to 68.1.2	from 68.1.0 on 3.8+

	  wheel to 0.41.2 from	0.41.1 on 3.7+ (#2628)

   v20.24.3 (2023-08-11)
   Bugfixes - 20.24.3
        Fixed ResourceWarning on exit caused by periodic update subprocess (-
	 #2472)

        Upgrade embedded wheels:

	  wheel to 0.41.1 from	0.41.0 (#2622)

   Misc	- 20.24.3
        #2610

   v20.24.2 (2023-07-24)
   Bugfixes - 20.24.2
        Upgrade embedded wheels:

	  pip to 23.2.1 from 23.2

	  wheel to 0.41.0 from	0.40.0 (#2614)

   v20.24.1 (2023-07-19)
   Bugfixes - 20.24.1
        Upgrade embedded wheels:

	  pip to 23.2 from 23.1.2 - by	@arielkirkwood (#2611)

   v20.24.0 (2023-07-14)
   Features - 20.24.0
        Export	the prompt prefix as VIRTUAL_ENV_PROMPT	when activating	a vir-
	 tual environment - by @jimporter.  (#2194)

   Bugfixes - 20.24.0
        Fix test suite	- by @gaborbernat. (#2592)

        Upgrade embedded wheels:

	  setuptools to 68.0.0	from 67.8.0 (#2607)

   v20.23.1 (2023-06-16)
   Bugfixes - 20.23.1
        update	and simplify nushell activation	script,	fixes an issue on Win-
	 dows  resulting  in  consecutive  command not found - by @melMass. (-
	 #2572)

        Upgrade embedded wheels:

	  setuptools to 67.8.0	from 67.7.2 (#2588)

   v20.23.0 (2023-04-27)
   Features - 20.23.0
        Do not	install	wheel and setuptools seed packages for	Python	3.12+.
	 To restore the	old behavior use:

	  for	wheel  use  VIRTUALENV_WHEEL=bundle  environment  variable  or
	   --wheel=bundle CLI flag,

	  for setuptools use VIRTUALENV_SETUPTOOLS=bundle  environment	 vari-
	   able	or --setuptools=bundle CLI flag.

	 By @chrysle. (#2487)

        3.12 support -	by @gaborbernat. (#2558)

   Bugfixes - 20.23.0
        Prevent  PermissionError  when	using venv creator on systems that de-
	 liver 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)

   v20.22.0 (2023-04-19)
   Features - 20.22.0
        Drop  support	for  creating Python <=3.6 (including 2) interpreters.
	 Removed pip of	20.3.4,	21.3.1;	wheel of 0.37.1; setuptools of 59.6.0,
	 44.1.1, 50.3.2- by @gaborbernat. (#2548)

   v20.21.1 (2023-04-19)
   Bugfixes - 20.21.1
        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)

   v20.21.0 (2023-03-12)
   Features - 20.21.0
        Make closure syntax explicitly	starts with {||. (#2512)

   Bugfixes - 20.21.0
        Add  print  command  to  nushell print_prompt to ensure compatibility
	 with future release of	nushell, where intermediate commands no	longer
	 print their result to stdout. (#2514)

        Do not	assume the default encoding. (#2515)

        Make ReentrantFileLock	thread-safe and, thereby, fix  race  condition
	 in virtualenv.cli_run - by @radoering.	(#2516)

   v20.20.0 (2023-02-28)
   Features - 20.20.0
        Change	 environment  variable	existence  check in Nushell activation
	 script	to not use deprecated command.	(#2506)

   Bugfixes - 20.20.0
        Discover CPython implementations distributed on Windows by any	 orga-
	 nization - 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)

   v20.19.0 (2023-02-07)
   Features - 20.19.0
        Allow platformdirs version 3 -	by @cdce8p. (#2499)

   v20.18.0 (2023-02-06)
   Features - 20.18.0
        Drop 3.6 runtime support (can still create 2.7+) -  by	 @gaborbernat.
	 (#2489)

   Bugfixes - 20.18.0
        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)

   v20.17.1 (2022-12-05)
   Bugfixes - 20.17.1
        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)

   v20.17.0 (2022-11-27)
   Features - 20.17.0
        Change	Nushell	activation script to be	a module meant to be activated
	 as an overlay.	(#2422)

        Update	operator used in Nushell activation script  to	be  compatible
	 with future versions. (#2450)

   Bugfixes - 20.17.0
        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)

   v20.16.7 (2022-11-12)
   Bugfixes - 20.16.7
        Use  parent  directory	of python executable for pyvenv.cfg home value
	 per PEP 405 - by @vfazio. (#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 se-
	 tuptools to 65.5.1 from 65.5.0	- by @gaborbernat. (#2443)

   v20.16.6 (2022-10-25)
   Features - 20.16.6
        Drop unneeded shims for PyPy3 directory structure (#2426)

   Bugfixes - 20.16.6
        Fix selected scheme  on  debian  derivatives  for  python  3.10  when
	 python3-distutils  is	not installed or the venv scheme is not	avail-
	 able -	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)

   v20.16.5 (2022-09-07)
   Bugfixes - 20.16.5
        Do not	turn echo off for subsequent commands in batch activators (ac-
	 tivate.bat and	deactivate.bat)	- by @pawelszramowski. (#2411)

   v20.16.4 (2022-08-29)
   Bugfixes - 20.16.4
        Bump embed setuptools to 65.3 - by @gaborbernat. (#2405)

   v20.16.3 (2022-08-04)
   Bugfixes - 20.16.3
        Upgrade embedded pip to 22.2.2	from 22.2.1 and	setuptools  to	63.4.1
	 from 63.2.0 - by @gaborbernat.	(#2395)

   v20.16.2 (2022-07-27)
   Bugfixes - 20.16.2
        Bump embedded pip from	22.2 to	22.2.1 - by @gaborbernat. (#2391)

   v20.16.1 (2022-07-26)
   Features - 20.16.1
        Update	 Nushell  activation scripts to	version	0.67 - by @kubouch. (-
	 #2386)

   v20.16.0 (2022-07-25)
   Features - 20.16.0
        Drop support for running under	Python 2 (still	can generate Python  2
	 environments) - by @gaborbernat. (#2382)

        Upgrade  embedded  pip	 to  22.2 from 22.1.2 and setuptools to	63.2.0
	 from 62.6.0 - by @gaborbernat.	(#2383)

   v20.15.1 (2022-06-28)
   Bugfixes - 20.15.1
        Fix the incorrect operation when setuptools plugins output  something
	 into stdout. (#2335)

        CPython3Windows creator ignores missing DLLs dir. (#2368)

   v20.15.0 (2022-06-25)
   Features - 20.15.0
        Support  for  Windows embeddable Python package: includes python<VER-
	 SION>.zip in the creator sources - by @reksarka. (#1774)

   Bugfixes - 20.15.0
        Upgrade embedded setuptools to	62.3.3 from 62.6.0 and pip  to	22.1.2
	 from 22.0.4 - by @gaborbernat.	(#2348)

        Use  shlex.quote  instead  of deprecated pipes.quote in Python	3 - by
	 @frenzymadness. (#2351)

        Fix Windows PyPy 3.6 -	by @reksarka. (#2363)

   v20.14.1 (2022-04-11)
   Features - 20.14.1
        Support for creating a	virtual	environment from a Python  2.7	frame-
	 work on macOS 12 - by @nickhutchinson.	 (#2284)

   Bugfixes - 20.14.1
        Upgrade  embedded setuptools to 62.1.0	from 61.0.0 - by @gaborbernat.
	 (#2327)

   v20.14.0 (2022-03-25)
   Features - 20.14.0
        Support  Nushell  activation  scripts	with  nu  version  0.60	 -  by
	 @kubouch. (#2321)

   Bugfixes - 20.14.0
        Upgrade embedded setuptools to	61.0.0 from 60.10.0 - by @gaborbernat.
	 (#2322)

   v20.13.4 (2022-03-18)
   Bugfixes - 20.13.4
        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)

   v20.13.3 (2022-03-07)
   Bugfixes - 20.13.3
        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)

   v20.13.2 (2022-02-24)
   Bugfixes - 20.13.2
        Upgrade embedded setuptools to	60.9.3 from 60.6.0 - by	 @gaborbernat.
	 (#2306)

   v20.13.1 (2022-02-05)
   Bugfixes - 20.13.1
        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)

   v20.13.0 (2022-01-02)
   Features - 20.13.0
        Add  downloaded  wheel	information in the relevant JSON embed file to
	 prevent additional downloads of the same wheel. - by @mayeut. (#2268)

   Bugfixes - 20.13.0
        Fix AttributeError: 'bool' object has no attribute 'error' when  cre-
	 ating 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)

   v20.12.1 (2022-01-01)
   Bugfixes - 20.12.1
        Try using previous updates of pip, setuptools & wheel when inside  an
	 update	 grace	period	rather	than  always  falling back to embedded
	 wheels	- by @mayeut. (#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 pe-
	 riodic	update - by @mayeut.  (#2267)

   v20.12.0 (2021-12-31)
   Features - 20.12.0
        Sign the python2 exe on Darwin	arm64 -	by @tmspicer. (#2233)

   Bugfixes - 20.12.0
        Fix --download	option - by @mayeut. (#2120)

        Upgrade embedded setuptools to	60.2.0 from 60.1.1 - by	 @gaborbernat.
	 (#2263)

   v20.11.2 (2021-12-29)
   Bugfixes - 20.11.2
        Fix  installation  of pinned versions of pip, setuptools & wheel - by
	 @mayeut. (#2203)

   v20.11.1 (2021-12-29)
   Bugfixes - 20.11.1
        Bump embed setuptools to 60.1.1 from 60.1.0  -	 by  @gaborbernat.  (-
	 #2258)

   v20.11.0 (2021-12-28)
   Features - 20.11.0
        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)

   v20.10.0 (2021-11-01)
   Features - 20.10.0
        If a "venv" install scheme exists in sysconfig, virtualenv  now  uses
	 it  to	create new virtual environments.  This allows Python distribu-
	 tors, 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
	 virtualenvs behavior on par with venv.	(#2224)

   Bugfixes - 20.10.0
        Fix broken prompt set up by activate.bat - by @SiggyBar. (#2225)

   v20.9.0 (2021-10-23)
   Features - 20.9.0
        Special-case  --prompt	 .  to	the name of the	current	directory - by
	 @rkm. (#2220)

        Add libffi-8.dll to pypy windows #2218	- by @mattip

   Bugfixes - 20.9.0
        Fixed path collision that could lead to a PermissionError or  writing
	 to system directories when using PyPy3.8 - by @mgorny.	(#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)

   v20.8.1 (2021-09-24)
   Bugfixes - 20.8.1
        Fixed	a  bug	where while creating a venv on top of an existing one,
	 without cleaning, when	seeded wheel version mismatch occurred,	multi-
	 ple .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)

   Misc	- 20.8.1
        #2189

   v20.8.0 (2021-09-16)
        upgrade embedded setuptools to	58.0.4 from 57.4.0 and pip  to	21.2.4
	 from 21.2.3

        Add nushell activation	script

   v20.7.2 (2021-08-10)
   Bugfixes - 20.7.2
        Upgrade  embedded  pip	to 21.2.3 from 21.2.2 and wheel	to 0.37.0 from
	 0.36.2	- by @gaborbernat.  (#2168)

   v20.7.1 (2021-08-09)
   Bugfixes - 20.7.1
        Fix unpacking dictionary items	in PythonInfo.install_path (#2165)

   v20.7.0 (2021-07-31)
   Bugfixes - 20.7.0
        upgrade embedded pip to 21.2.2	from 21.1.3 and	setuptools  to	57.4.0
	 from 57.1.0 - by @gaborbernat (#2159)

   Deprecations	and Removals - 20.7.0
        Removed  xonsh	activator due to this breaking fairly often the	CI and
	 lack of support from those packages maintainers, upstream is  encour-
	 aged	to   continue	supporting  the	 project  as  a	 plugin	 -  by
	 @gaborbernat. (#2160)

   v20.6.0 (2021-07-14)
   Features - 20.6.0
        Support Python	interpreters without distutils (fallback  to  syconfig
	 in these cases) - by @gaborbernat.  (#1910)

   v20.5.0 (2021-07-13)
   Features - 20.5.0
        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)

   Bugfixes - 20.5.0
        Bump pip the embedded pip  21.1.3  and	 setuptools  to	 57.1.0	 -  by
	 @gaborbernat. (#2135)

   Deprecations	and Removals - 20.5.0
        Drop  python  3.4  support as it has been over	2 years	since EOL - by
	 @gaborbernat. (#2141)

   v20.4.7 (2021-05-24)
   Bugfixes - 20.4.7
        Upgrade embedded  pip	to  21.1.2  and	 setuptools  to	 57.0.0	 -  by
	 @gaborbernat. (#2123)

   v20.4.6 (2021-05-05)
   Bugfixes - 20.4.6
        Fix   site.getsitepackages()	broken	on  python2  on	 debian	 -  by
	 @freundTech. (#2105)

   v20.4.5 (2021-05-05)
   Bugfixes - 20.4.5
        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)

   v20.4.4 (2021-04-20)
   Bugfixes - 20.4.4
        Built in discovery class is always  preferred	over  plugin  supplied
	 classes. (#2087)

        Upgrade embedded setuptools to	56.0.0 by @gaborbernat.	(#2094)

   v20.4.3 (2021-03-16)
   Bugfixes - 20.4.3
        Bump  embedded	 setuptools from 52.0.0	to 54.1.2 - by @gaborbernat (-
	 #2069)

        Fix PyPy3 stdlib on Windows is	incorrect - by @gaborbernat. (#2071)

   v20.4.2 (2021-02-01)
   Bugfixes - 20.4.2
        Running virtualenv --upgrade-embed-wheels crashes - by	 @gaborbernat.
	 (#2058)

   v20.4.1 (2021-01-31)
   Bugfixes - 20.4.1
        Bump  embedded	 pip  and  setuptools packages to latest upstream sup-
	 ported	(21.0.1	and 52.0.0) - by @gaborbernat. (#2060)

   v20.4.0 (2021-01-19)
   Features - 20.4.0
        On the	programmatic API allow passing	in  the	 environment  variable
	 dictionary  to	 use,  defaults	 to  os.environ	 if not	specified - by
	 @gaborbernat. (#2054)

   Bugfixes - 20.4.0
        Upgrade embedded setuptools to	51.3.3 from 51.1.2 - by	 @gaborbernat.
	 (#2055)

   v20.3.1 (2021-01-13)
   Bugfixes - 20.3.1
        Bump  embed pip to 20.3.3, setuptools to 51.1.1 and wheel to 0.36.2 -
	 by @gaborbernat. (#2036)

        Allow unfunctioning of	pydoc to fail freely so	that  virtualenvs  can
	 be  activated under Zsh with set -e (since otherwise unset -f and un-
	 function 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 ex-
	 ecutable  is  replaced	 -  such  is  the  case	 with  pyenv)	-   by
	 @gaborbernat. (#2050)

   v20.3.0 (2021-01-10)
   Features - 20.3.0
        The  builtin  discovery  takes	now a --try-first-with argument	and is
	 first attempted as valid interpreters.	One can	use this to force dis-
	 covery	of a given python executable when the  discovery  order/mecha-
	 nism raises errors - by @gaborbernat. (#2046)

   Bugfixes - 20.3.0
        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)

   v20.2.2 (2020-12-07)
   Bugfixes - 20.2.2
        Bump  pip  to	20.3.1,	 setuptools to 51.0.0 and wheel	to 0.36.1 - by
	 @gaborbernat. (#2029)

   v20.2.1 (2020-11-23)
       No significant changes.

   v20.2.0 (2020-11-21)
   Features - 20.2.0
        Optionally skip VCS ignore directive for entire virtualenv directory,
	 using option no-vcs-ignore, by	default	False. (#2003)

        Add --read-only-app-data option to allow for creation based on	an ex-
	 isting	app data cache which is	non-writable.  This may	be useful (for
	 example) to produce a docker image where the  app-data	 is  pre-popu-
	 lated.

	    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)

   Bugfixes - 20.2.0
        Fix processing	of the VIRTUALENV_PYTHON environment variable and make
	 it multi-value	as well	(separated by comma) - by @pneff. (#1998)

   v20.1.0 (2020-10-25)
   Features - 20.1.0
        The python specification can now take one or more values, first found
	 is used to create the virtual environment - by	@gaborbernat. (#1995)

   v20.0.35 (2020-10-15)
   Bugfixes - 20.0.35
        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)

   v20.0.34 (2020-10-12)
   Bugfixes - 20.0.34
        Align	with  venv  module  when  creating  virtual  environments with
	 builtin creator on Windows 3.7	and later - by @gaborbernat. (#1782)

        Handle	 Cygwin	 path  conversion  in  the  activation	script	-   by
	 @davidcoghlan.	(#1969)

   v20.0.33 (2020-10-04)
   Bugfixes - 20.0.33
        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)

   v20.0.32 (2020-10-01)
   Bugfixes - 20.0.32
        For activation	scripts	always use UNIX	line endings (unless its 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)

   v20.0.31 (2020-08-17)
   Bugfixes - 20.0.31
        Upgrade embedded pip to 20.2.1, setuptools to	49.6.0	and  wheel  to
	 0.35.1	- by @gaborbernat. (#1918)

   v20.0.30 (2020-08-04)
   Bugfixes - 20.0.30
        Upgrade  pip to 20.2.1	and setuptools to 49.2.1 - by @gaborbernat. (-
	 #1915)

   v20.0.29 (2020-07-31)
   Bugfixes - 20.0.29
        Upgrade embedded pip from version 20.1.2 to 20.2 -  by	 @gaborbernat.
	 (#1909)

   v20.0.28 (2020-07-24)
   Bugfixes - 20.0.28
        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)

   v20.0.27 (2020-07-15)
   Bugfixes - 20.0.27
        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)

   v20.0.26 (2020-07-07)
   Bugfixes - 20.0.26
        Bump dependency distutils >= 0.3.1 - by @gaborbernat. (#1880)

        Improve periodic update handling:

	  better  logging  output  while  running and enable logging on back-
	   ground 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	Syste-
	 mExit(0) - by @gaborbernat. (#1885)

        Upgrade  embedded  setuptools from 47.3.1 to 49.1.0 for Python	3.5+ -
	 by @gaborbernat. (#1887)

   v20.0.25 (2020-06-23)
   Bugfixes - 20.0.25
        Fix that when the app-data seeders image creation fails the exception
	 is silently ignored. Avoid two	virtual	environment creations to  step
	 on  each  others toes by using	a lock while creating the base images.
	 By @gaborbernat. (#1869)

   v20.0.24 (2020-06-22)
   Features - 20.0.24
        Ensure	that the seeded	packages do not	get too	much out of date:

	  add a CLI flag that	triggers  upgrade  of  embedded	 wheels	 under
	   upgrade-embed-wheels

	  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 out-
	 put, 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)

   Bugfixes - 20.0.24
        Do not	generate/overwrite .gitignore if it already exists at destina-
	 tion path - by	@gaborbernat. (#1862)

        Improve  error	 message  for  no  .dist-info inside the app-data copy
	 seeder	- by @gaborbernat. (#1867)

   Improved Documentation - 20.0.24
        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)

   v20.0.23 (2020-06-12)
   Bugfixes - 20.0.23
        Fix typo in setup.cfg - by @RowdyHowell. (#1857)

   v20.0.22 (2020-06-12)
   Bugfixes - 20.0.22
        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)

   v20.0.21 (2020-05-20)
   Features - 20.0.21
        Generate  ignore  file	 for version control systems to	avoid tracking
	 virtual environments by default. Users	should remove these  files  if
	 still	want to	track. For now we support only git by @gaborbernat. (-
	 #1806)

   Bugfixes - 20.0.21
        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)

   v20.0.20 (2020-05-04)
   Bugfixes - 20.0.20
        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 er-
	 ror message - by @gaborbernat.	(#1814)

   v20.0.19 (2020-05-03)
   Bugfixes - 20.0.19
        Fix generating	a Python 2 environment from Python 3  creates  invalid
	 python	activator - by @gaborbernat. (#1776)

        Fix pinning seed packages via app-data	seeder raised Invalid Require-
	 ment -	by @gaborbernat. (#1779)

        Do  not  stop interpreter discovery if	we fail	to find	the system in-
	 terpreter for a executable during discovery  -	 by  @gaborbernat.  (-
	 #1781)

        On CPython2 POSIX platforms ensure syconfig.get_makefile_filename ex-
	 ists 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)

   v20.0.18 (2020-04-16)
   Bugfixes - 20.0.18
        Importing  setuptools	before cli_run could cause our python informa-
	 tion query to fail due	to setuptools patching distutils.dist.Distrib-
	 ution - by @gaborbernat. (#1771)

   v20.0.17 (2020-04-09)
   Features - 20.0.17
        Extend	environment variables checked for configuration	to also	 check
	 aliases  (e.g.	 setting  either  VIRTUALENV_COPIES  or	VIRTUALENV_AL-
	 WAYS_COPY will	work) -	by @gaborbernat. (#1763)

   v20.0.16 (2020-04-04)
   Bugfixes - 20.0.16
        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)

   v20.0.15 (2020-03-27)
   Features - 20.0.15
        Upgrade embedded setuptools to	46.1.3 from 46.1.1 - by	 @gaborbernat.
	 (#1752)

   v20.0.14 (2020-03-25)
   Features - 20.0.14
        Remove	 __PYVENV_LAUNCHER__ on	macOs for Python 3.7.(<8) and 3.8.(<3)
	 on interpreter	startup	via pth	file, this pulls in the	upstream patch
	 - 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)

   Bugfixes - 20.0.14
        Fix discovery of interpreter by name from PATH	that does not match  a
	 spec format - by @gaborbernat.	(#1746)

   v20.0.13 (2020-03-19)
   Bugfixes - 20.0.13
        Do  not fail when the pyc files is missing for	the host Python	2 - by
	 @gaborbernat. (#1738)

        Support broken	Packaging pythons that put the include	headers	 under
	 distutils  pattern  rather  than  sysconfig one - by @gaborbernat. (-
	 #1739)

   v20.0.12 (2020-03-19)
   Bugfixes - 20.0.12
        Fix relative path discovery of	interpreters  -	 by  @gaborbernat.  (-
	 #1734)

   v20.0.11 (2020-03-18)
   Features - 20.0.11
        Improve  error	 message when the host python does not satisfy invari-
	 ants needed to	create virtual environments (now we print  which  host
	 files	are  incompatible/missing  and for which creators when no sup-
	 ported	creator	can be matched,	however	we found creators that can de-
	 scribe	the given Python interpreter - will still print	 no  supported
	 creator  for Jython, however print exactly what host files do not al-
	 low creation of virtual environments in case of  CPython/PyPy)	 -  by
	 @gaborbernat. (#1716)

   Bugfixes - 20.0.11
        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 thats 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-exten-
	 sion  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 ex-
	 ists -	by @gaborbernat. (#1728)

   Improved Documentation - 20.0.11
        supports details now explicitly what Python installations we  support
	 - by @gaborbernat. (#1714)

   v20.0.10 (2020-03-10)
   Bugfixes - 20.0.10
        Fix  acquiring	 python	information might be altered by	distutils con-
	 figuration 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)

   Improved Documentation - 20.0.10
        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)

   v20.0.9 (2020-03-08)
   Bugfixes - 20.0.9
        pythonw.exe works as python.exe on Windows - by @gaborbernat. (#1686)

        Handle	 legacy	loaders	for virtualenv import hooks used to patch dis-
	 tutils	configuration load - by	@gaborbernat.  (#1690)

        Support for python 2 platforms	that store landmark files  in  platst-
	 dlib 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)

   v20.0.8 (2020-03-04)
   Bugfixes - 20.0.8
        Having	 distutils  configuration  files  that	set  prefix  and   in-
	 stall_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   its	  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_in-
	 stall.pth runs	- by @gaborbernat. (#1684)

        Fix attr: import fails	for setuptools - by @gaborbernat. (#1685)

   v20.0.7 (2020-02-26)
   Bugfixes - 20.0.7
        Disable distutils fixup for python 3 until pypa/pip  #7778  is	 fixed
	 and released -	by @gaborbernat. (#1669)

   v20.0.6 (2020-02-26)
   Bugfixes - 20.0.6
        Fix  global site package always being added with bundled macOs	python
	 framework builds - by @gaborbernat.  (#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 tem-
	   porary

	 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)

   v20.0.5 (2020-02-21)
   Features - 20.0.5
        Also create pythonX.X executables when	creating pypy virtualenvs - by
	 @asottile (#1612)

        Fail with better error	message	if trying to install source  with  un-
	 supported  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)

   Bugfixes - 20.0.5
        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_exe-
	 cutable based on __PYVENV_LAUNCHER__ -	by @cjolowicz (#1643)

   v20.0.4 (2020-02-14)
   Features - 20.0.4
        When  aliasing	interpreters, use relative symlinks - by @asottile. (-
	 #1596)

   Bugfixes - 20.0.4
        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)

   v20.0.3 (2020-02-12)
   Bugfixes - 20.0.3
        On Python 2 with Apple	Framework builds the global site package is no
	 longer	 added	when  the  system-site-packages	 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)

   Improved Documentation - 20.0.3
        Document  a  programmatic API as from virtualenv import cli_run under
	 Python	- by @gaborbernat. (#1585)

   v20.0.2 (2020-02-11)
   Features - 20.0.2
        Print out a one line message about the	 created  virtual  environment
	 when  no  verbose  is	set,  this can now be silenced to get back the
	 original behavior via the quiet flag -	by @pradyunsg. (#1557)

        Allow virtualenvs app data cache to be	overridden by VIRTUALENV_OVER-
	 RIDE_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)

   Bugfixes - 20.0.2
        Support long path names for generated virtual environment console en-
	 try 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  bi-
	   nary	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 en-
	 vironment - by	@gaborbernat. (#1561)

        While discovering a python executables	interpreters  that  cannot  be
	 queried are now displayed with	info level rather than warning,	so now
	 theyre	 no  longer shown by default (these can	be just	executables to
	 which we dont have access or that are broken, dont warn  if  its  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)

   Improved Documentation - 20.0.2
        Add link to the legacy	documentation for the  changelog  by  @jezdez.
	 (#1547)

        Fine tune the documentation layout: default width of theme, allow ta-
	 bles  to wrap around, soft corners for	code snippets -	by @pradyunsg.
	 (#1548)

   v20.0.1 (2020-02-10)
   Features - 20.0.1
        upgrade embedded setuptools to	45.2.0 from 45.1.0 for Python  3.4+  -
	 by @gaborbernat. (#1554)

   Bugfixes - 20.0.1
        Virtual environments created via relative path	on Windows creates bad
	 console executables - by @gaborbernat.	 (#1552)

        Seems	sometimes  venvs  created  set	their base executable to them-
	 selves; we accept these without question, so we handle	virtual	 envi-
	 ronments as system pythons causing issues - by	@gaborbernat. (#1553)

   v20.0.0. (2020-02-10)
   Improved Documentation - 20.0.0.
        Fixes	 typos,	 repeated  words  and  inconsistent  heading  spacing.
	 Rephrase parts	of the development documentation  and  CLI  documenta-
	 tion. 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)

   v20.0.0b2 (2020-02-04)
   Features - 20.0.0b2
        Improve base executable discovery mechanism:

	  print at debug level	why we refuse some candidates,

	  when	no candidates match exactly, instead of	hard failing  fallback
	   to  the closest match where the priority of matching	attributes is:
	   python implementation, major	version, minor version,	 architecture,
	   patch  version,  release  level  and	 serial	(this is to facilitate
	   things to still work	when the OS upgrade replace/upgrades the  sys-
	   tem	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 vir-
	   tual	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)

   Bugfixes - 20.0.0b2
        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 pro-
	   posed 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 dis-
	 covered  under	a different path (such is the case when	we have	multi-
	 ple 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:gaborber-
	 nat. (#1535)

   Improved Documentation - 20.0.0b2
        Create	  the	first	iteration   of	the  new  documentation	 -  by
	 @gaborbernat. (#1465)

        Project readme	is now of type MarkDown	instead	of reStructuredText  -
	 by @gaborbernat. (#1531)

   v20.0.0b1 (2020-01-28)
        First public release of the rewrite. Everything is brand new and just
	 added.

        --download defaults to	False

        No  longer  replaces  builtin	site  module with custom version baked
	 within	virtualenv code	itself.	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	itera-
	  tion.	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.

AUTHOR
       unknown

COPYRIGHT
       2007-2026, PyPA,	PyPA

21.2				 June 11, 2026			 VIRTUALENV(1)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=virtualenv&sektion=1&manpath=FreeBSD+Ports+15.1.quarterly>

home | help