-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PEP 796: relative virtual environments, initial draft #4476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rickeylev
wants to merge
29
commits into
python:main
Choose a base branch
from
rickeylev:relative.venvs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
ceeaa3b
initial file
rickeylev d0a9289
add some core content
rickeylev 41d2ea8
rename to motivation
rickeylev 65a415c
note it enables more advanced optimizations
rickeylev 4175b20
add foot notes, relocatable term section, links
rickeylev bbc85b7
update discussion, sponsor headers to pending
rickeylev a0c2529
rst fixups
rickeylev 8e6e21e
fixup italics
rickeylev 37202ca
rename to relative-venv
rickeylev b81c50f
clarify advanced deployment options, reflow some text
rickeylev 55a5e28
add specification, rationale section; doc why env vars arent an option
rickeylev e09b00d
also mention curdir syntax handling
rickeylev c7a6a9b
update some todo text
rickeylev bc1ffbd
update codeowners
rickeylev 2301d2a
add initial discussion footnote link
rickeylev e14b01f
add fr footnote
rickeylev 175f378
revert codeowners change
rickeylev 31cb756
remove packaging-related specs
rickeylev cd46f4d
fix lint errors with headers
rickeylev b532f5c
set sponsor
rickeylev 99434fc
set sponsor as codeowner
rickeylev 862142a
clarify title to focus on core pyvenv.cfg home behavior
rickeylev 1c8fb2d
fix typo; remove host-relocatable mention; remove non-germane copying…
rickeylev c542890
fix typos, grammar
rickeylev 3240227
Apply suggestions from code review
rickeylev 557cb71
fix up markdown and text width
rickeylev 0579623
fix title underlines
rickeylev c9388b3
link to relative venv reference implementation
rickeylev b959f24
Apply suggestions from code review
rickeylev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
add specification, rationale section; doc why env vars arent an option
- Loading branch information
commit 55a5e2857487d435a82772717f6a6d5083f94cd8
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -50,13 +50,14 @@ requirement should be relaxed and relative path behavior allowed and defined. | |||||
Second, virtual environments are the standard way for running Python | ||||||
applications. This means ... | ||||||
|
||||||
* The closer the dev environment is to the non-dev environment, the more reliable | ||||||
software one can get. | ||||||
* The closer the dev and non-dev envs are, the easier it is to reproduce issues. | ||||||
* The closer the dev environment is to the non-dev environment, the more | ||||||
reliable software one can get. | ||||||
* The closer the dev and non-dev envs are, the easier it is to reproduce | ||||||
issues. | ||||||
* The simpler the process is to re-create the environment, the more reliable | ||||||
software one can get. | ||||||
* The simpler the process is to re-create the environment, the faster the process | ||||||
can be. | ||||||
* The simpler the process is to re-create the environment, the faster the | ||||||
process can be. | ||||||
|
||||||
By making it trivial to copy a virtual environment from one host to another, it | ||||||
avoids these categories of problems. Additionally, the development tools to | ||||||
|
@@ -70,6 +71,36 @@ caching of artifacts. | |||||
Rationale | ||||||
========= | ||||||
|
||||||
The reason support for relative virtual environments needs to be | ||||||
in the interpreter itself is because locating ``PYTHONHOME`` happens | ||||||
very early in the interpreter startup process, which limits the options for | ||||||
customizing how it's computed. Without the ability to specify where the | ||||||
supporting Python runtime files are, the interpreter can't finish startup, | ||||||
so other hook points (e.g. ``site`` initialization) never trigger. | ||||||
|
||||||
Specification | ||||||
============= | ||||||
|
||||||
The ``home`` value in ``pyvenv.cfg`` is permitted to use a relative path value. | ||||||
These may contain up-references outside of the virtual environnment root | ||||||
directory. Examples: | ||||||
|
||||||
* ``subdir/whatever/bin`` (a directory within the virtual environment). | ||||||
* ``../../../../../elsewhere/runtime/bin`` (a directory outside the virtual | ||||||
environment). | ||||||
|
||||||
Relative paths are relative to the directory containing ``pyvenv.cfg``. During | ||||||
interpreter startup (i.e. ``getpath.py``), the relative path is joined to the | ||||||
directory to form an absolute path. Up-references are resolved syntactically | ||||||
(i.e. not resolving symlinks). Symlinks are *not* resolved prior to | ||||||
construction of the absolute path to ensure semantics between a relative path | ||||||
and absolute path remain the same. | ||||||
|
||||||
For example, given | ||||||
``/home/user/venv/bin/pyvenv.cfg`` with | ||||||
``home = ../../runtime/bin``, the result is ``home = /home/user/runtime/bin``, | ||||||
i.e. it's equivalent to using that value verbatim in ``pyvenv.cfg``. | ||||||
|
||||||
|
||||||
Python Runtime Changes | ||||||
rickeylev marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
====================== | ||||||
|
@@ -82,18 +113,18 @@ Today, relative paths resolve relative to the process's current working | |||||
directory. Because CWD isn't knowable in advance, it makes relative paths today | ||||||
effective impossible. | ||||||
|
||||||
Instead, the paths should be relative to the location of the ``pyvenv.cfg`` file. | ||||||
This file is chosen as the anchor point because the tool that creates the file | ||||||
also has to know where the Python runtime is, so can easily calculate the | ||||||
Instead, the paths should be relative to the location of the ``pyvenv.cfg`` | ||||||
file. This file is chosen as the anchor point because the tool that creates the | ||||||
file also has to know where the Python runtime is, so can easily calculate the | ||||||
correct relative path. For tools that read the ``pyvenv.cfg``, it is also easy | ||||||
to simple join the directory name of where ``pyvenv.cfg`` was found with the | ||||||
path in the config file. When a person reads the config file, they can do | ||||||
similar, which is a lower cognitive burden and helps avoids the question of | ||||||
"relative to what?" | ||||||
|
||||||
This change is only a couple of lines in the start up code. Specifically, when | ||||||
parsing the ``pyvenv.cfg`` file and finding the ``home`` value, it just needs to | ||||||
be checked if it's already absolute. If not, then join to the directory name | ||||||
parsing the ``pyvenv.cfg`` file and finding the ``home`` value, it just needs | ||||||
to be checked if it's already absolute. If not, then join to the directory name | ||||||
of the ``pyvenv.cfg`` file. The code alredy knows the directory and has helpers | ||||||
already present for checking if a path is absolute and joining two paths. | ||||||
|
||||||
|
@@ -103,12 +134,12 @@ A proof-of-concept of this is implemented in | |||||
Virtual Environment Tool Changes | ||||||
================================ | ||||||
|
||||||
Virtual environment management tools should support a mechanism to generate | ||||||
a ``pyvenv.cfg`` file with a ``home`` key that is a relative path to the relevant | ||||||
Virtual environment management tools should support a mechanism to generate a | ||||||
``pyvenv.cfg`` file with a ``home`` key that is a relative path to the relevant | ||||||
Python installation. | ||||||
|
||||||
For the standard library's ``venv`` module, the flag ``--relative`` will be added | ||||||
to trigger this behavior. | ||||||
For the standard library's ``venv`` module, the flag ``--relative`` will be | ||||||
added to trigger this behavior. | ||||||
|
||||||
Package Installer Changes | ||||||
========================= | ||||||
|
@@ -120,20 +151,29 @@ absolute paths occur today are: | |||||
1. ``bin/`` scripts, where shebangs are rewritten. | ||||||
2. ``site-packages`` symlinks. | ||||||
|
||||||
Instead, they should create relative symlinks pointing to the actual | ||||||
For symlinks, they should create relative symlinks pointing to the actual | ||||||
installation directory for packages. | ||||||
|
||||||
For ``bin/`` scripts, installers should generate executables that are able to | ||||||
locate the venv's interpreter at runtime. How to do this is implementation | ||||||
defined. Typically it means having shell code use ``$0`` to locate the | ||||||
appropriate ``bin/python3`` executable, but installers are free to use whatever | ||||||
mechanism they want (e.g. a native polyglot executable). | ||||||
|
||||||
todo: copy/paste example shell? | ||||||
|
||||||
Copying a Venv to Another Host | ||||||
================================= | ||||||
|
||||||
Copying the venv to another host is simple: copy the venv directory itself, the | ||||||
relative location ``home`` points to, and preserve the relative directory | ||||||
structures. | ||||||
Copying the venv to another host is simple: copy the venv directory itself, and | ||||||
any directories outside the venv it needs, while preserving the relative | ||||||
directory structures. | ||||||
|
||||||
How to do this, exactly, is implementation-defined. | ||||||
|
||||||
In practice, this typically means copying a parent directory of the virtual | ||||||
environment, which contains the runtime, installations of dependencies, and | ||||||
the group of virtual environments to relocate. | ||||||
environment, which contains the runtime, one or more venvs, installations | ||||||
of dependencies, and any other supporting files. | ||||||
|
||||||
Backwards Compatibility | ||||||
======================= | ||||||
|
@@ -157,8 +197,7 @@ Reference Implementation | |||||
A reference implementation is available by using the combination of: | ||||||
|
||||||
* Python runtime from `rickeylev/feat.relative.pyvenv.home <https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home>`__ | ||||||
* rules_python with (todo: alterations to use cpython build as in-build | ||||||
runtime) | ||||||
* rules_python with (todo: link to branch that uses above) | ||||||
|
||||||
Open Issues | ||||||
=========== | ||||||
|
@@ -178,7 +217,7 @@ Footnotes | |||||
implements same-host relocatable virtual environments. | ||||||
* `python-build-standalone <https://github.com/astral-sh/python-build-standalone>`__: | ||||||
rickeylev marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put something after the colon? Or delete the colon?
Suggested change
|
||||||
A relocatable Python runtime. | ||||||
|
||||||
* `PoC for relative home in Python startup <https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home>`__ | ||||||
|
||||||
Rejected Ideas | ||||||
===================== | ||||||
|
@@ -223,10 +262,22 @@ Second, when using relative paths that point outside the venv, the venv is only | |||||
relocatable insofar as those external artifacts are also relocated. This is an | ||||||
additional nuance that requires qualification of the term. | ||||||
|
||||||
To better avoid this confusiong, "relative" is chosen, which more naturally | ||||||
To better avoid this confusion, "relative" is chosen, which more naturally | ||||||
invites the question *"Relative to what?"*. | ||||||
|
||||||
|
||||||
Using PYTHONHOME at runtime to specify home | ||||||
------------------------------------------- | ||||||
|
||||||
Using the ``PYTHONHOME`` environment variable (or any environment variable) is | ||||||
problematic because it's difficult to know and control when an environment | ||||||
variable should or shouldn't be inherited by subprocesses. In some cases, it's | ||||||
not feasible because of how layers of programs calling programs interact. | ||||||
|
||||||
Code generally assumes that any virtual environment will be | ||||||
automatically detected and activated by the presence of ``pyvenv.cfg``, so | ||||||
things work better when alterations to the environemtn aren't a concern. | ||||||
|
||||||
Copyright | ||||||
========= | ||||||
|
||||||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.