Skip to content

Commit 812b26f

Browse files
committed
Set 'home' to parent directory of system_executable
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>
1 parent 50b4b6b commit 812b26f

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

docs/changelog/2440.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use parent directory of python executable for pyvenv.cfg "home" value per PEP 405 - by :user:`vfazio`.

src/virtualenv/create/creator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def run(self):
157157

158158
def set_pyenv_cfg(self):
159159
self.pyenv_cfg.content = OrderedDict()
160-
self.pyenv_cfg["home"] = self.interpreter.system_exec_prefix
160+
self.pyenv_cfg["home"] = os.path.dirname(os.path.abspath(self.interpreter.system_executable))
161161
self.pyenv_cfg["implementation"] = self.interpreter.implementation
162162
self.pyenv_cfg["version_info"] = ".".join(str(i) for i in self.interpreter.version_info)
163163
self.pyenv_cfg["virtualenv"] = __version__

tests/unit/create/test_creator.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,28 @@ def test_prompt_set(tmp_path, creator, prompt):
318318
assert cfg["prompt"] == actual_prompt
319319

320320

321+
@pytest.mark.parametrize("creator", CURRENT_CREATORS)
322+
def test_home_path_is_exe_parent(tmp_path, creator):
323+
cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", creator]
324+
325+
result = cli_run(cmd)
326+
cfg = PyEnvCfg.from_file(result.creator.pyenv_cfg.path)
327+
328+
# Cannot assume "home" path is a specific value as path resolution may change
329+
# between versions (symlinks, framework paths, etc) but we can check that a
330+
# python executable is present from the configured path per PEP 405
331+
if sys.platform == "win32":
332+
exes = ("python.exe",)
333+
else:
334+
exes = (
335+
"python",
336+
f"python{sys.version_info.major}",
337+
f"python{sys.version_info.major}.{sys.version_info.minor}",
338+
)
339+
340+
assert any(os.path.exists(os.path.join(cfg["home"], exe)) for exe in exes)
341+
342+
321343
@pytest.mark.slow()
322344
@pytest.mark.usefixtures("current_fastest")
323345
def test_cross_major(cross_python, coverage_env, tmp_path, session_app_data):

0 commit comments

Comments
 (0)