Skip to content

Commit

Permalink
Set 'home' to parent directory of system_executable
Browse files Browse the repository at this point in the history
PEP 405 says of the "home" key:

"If a home key is found, this signifies that the Python binary belongs
to a virtual environment, and the value of the home key is the directory
containing the Python executable used to create this virtual
environment."

And:

"In this case, prefix-finding continues as normal using the value of the
home key as the effective Python binary location, which finds the prefix
of the base installation."

Previously, "home" was being set to `interpreter.system_exec_prefix`
which does not abide by the PEP specification.

In Python 3.11, the "home" directory is used to determine the value of
`sys._base_executable`, so if the path specified is incorrect, the
path + interpreter returned will be invalid. This can cause headaches
later when trying to probe info via the discovery module.

Now, set this to the parent directory of `interpreter.system_executable`.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
  • Loading branch information
vfazio committed Nov 11, 2022
1 parent 50b4b6b commit 812b26f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/changelog/2440.bugfix.rst
@@ -0,0 +1 @@
Use parent directory of python executable for pyvenv.cfg "home" value per PEP 405 - by :user:`vfazio`.
2 changes: 1 addition & 1 deletion src/virtualenv/create/creator.py
Expand Up @@ -157,7 +157,7 @@ def run(self):

def set_pyenv_cfg(self):
self.pyenv_cfg.content = OrderedDict()
self.pyenv_cfg["home"] = self.interpreter.system_exec_prefix
self.pyenv_cfg["home"] = os.path.dirname(os.path.abspath(self.interpreter.system_executable))
self.pyenv_cfg["implementation"] = self.interpreter.implementation
self.pyenv_cfg["version_info"] = ".".join(str(i) for i in self.interpreter.version_info)
self.pyenv_cfg["virtualenv"] = __version__
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/create/test_creator.py
Expand Up @@ -318,6 +318,28 @@ def test_prompt_set(tmp_path, creator, prompt):
assert cfg["prompt"] == actual_prompt


@pytest.mark.parametrize("creator", CURRENT_CREATORS)
def test_home_path_is_exe_parent(tmp_path, creator):
cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", creator]

result = cli_run(cmd)
cfg = PyEnvCfg.from_file(result.creator.pyenv_cfg.path)

# Cannot assume "home" path is a specific value as path resolution may change
# between versions (symlinks, framework paths, etc) but we can check that a
# python executable is present from the configured path per PEP 405
if sys.platform == "win32":
exes = ("python.exe",)
else:
exes = (
"python",
f"python{sys.version_info.major}",
f"python{sys.version_info.major}.{sys.version_info.minor}",
)

assert any(os.path.exists(os.path.join(cfg["home"], exe)) for exe in exes)


@pytest.mark.slow()
@pytest.mark.usefixtures("current_fastest")
def test_cross_major(cross_python, coverage_env, tmp_path, session_app_data):
Expand Down

0 comments on commit 812b26f

Please sign in to comment.