Mailing List Archive

gh-117786: Fix venv created from Windows Store install by restoring __PYVENV_LAUNCHER__ smuggling (GH-117814)
https://github.com/python/cpython/commit/4b10e209c76f9f36f8ae2e4d713b3a01591c1856
commit: 4b10e209c76f9f36f8ae2e4d713b3a01591c1856
branch: main
author: Steve Dower <steve.dower@python.org>
committer: zooba <steve.dower@microsoft.com>
date: 2024-04-24T23:00:55+01:00
summary:

gh-117786: Fix venv created from Windows Store install by restoring __PYVENV_LAUNCHER__ smuggling (GH-117814)

files:
A Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst
M Lib/test/test_embed.py
M Modules/getpath.py
M PC/venvlauncher.c

diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index ec928f935655f9..d94c63a13b8ea4 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -747,6 +747,9 @@ def check_config(self, configs, expected):
if value is self.IGNORE_CONFIG:
config.pop(key, None)
del expected[key]
+ # Resolve bool/int mismatches to reduce noise in diffs
+ if isinstance(value, (bool, int)) and isinstance(config.get(key), (bool, int)):
+ expected[key] = type(config[key])(expected[key])
self.assertEqual(config, expected)

def check_global_config(self, configs):
diff --git a/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst b/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst
new file mode 100644
index 00000000000000..a4cd9a9adb3e59
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst
@@ -0,0 +1,2 @@
+Fixes virtual environments not correctly launching when created from a Store
+install.
diff --git a/Modules/getpath.py b/Modules/getpath.py
index 1410ffdbed8c70..bc7053224aaf16 100644
--- a/Modules/getpath.py
+++ b/Modules/getpath.py
@@ -310,7 +310,10 @@ def search_up(prefix, *landmarks, test=isfile):
# and should not affect base_executable.
base_executable = f"{dirname(library)}/bin/python{VERSION_MAJOR}.{VERSION_MINOR}"
else:
- base_executable = executable
+ # Use the real executable as our base, or argv[0] otherwise
+ # (on Windows, argv[0] is likely to be ENV___PYVENV_LAUNCHER__; on
+ # other platforms, real_executable is likely to be empty)
+ base_executable = real_executable or executable

if not real_executable:
real_executable = base_executable
@@ -408,13 +411,14 @@ def search_up(prefix, *landmarks, test=isfile):
if not real_executable:
real_executable = base_executable

-try:
- real_executable = realpath(real_executable)
-except OSError as ex:
- # Only warn if the file actually exists and was unresolvable
- # Otherwise users who specify a fake executable may get spurious warnings.
- if isfile(real_executable):
- warn(f'Failed to find real location of {base_executable}')
+if real_executable:
+ try:
+ real_executable = realpath(real_executable)
+ except OSError as ex:
+ # Only warn if the file actually exists and was unresolvable
+ # Otherwise users who specify a fake executable may get spurious warnings.
+ if isfile(real_executable):
+ warn(f'Failed to find real location of {base_executable}')

if not executable_dir and os_name == 'darwin' and library:
# QUIRK: macOS checks adjacent to its library early
@@ -427,12 +431,12 @@ def search_up(prefix, *landmarks, test=isfile):

# If we do not have the executable's directory, we can calculate it.
# This is the directory used to find prefix/exec_prefix if necessary.
-if not executable_dir:
+if not executable_dir and real_executable:
executable_dir = real_executable_dir = dirname(real_executable)

# If we do not have the real executable's directory, we calculate it.
# This is the directory used to detect build layouts.
-if not real_executable_dir:
+if not real_executable_dir and real_executable:
real_executable_dir = dirname(real_executable)

# ******************************************************************************
diff --git a/PC/venvlauncher.c b/PC/venvlauncher.c
index fe97d32e93b5f6..b1c8d0763d8c76 100644
--- a/PC/venvlauncher.c
+++ b/PC/venvlauncher.c
@@ -484,8 +484,8 @@ process(int argc, wchar_t ** argv)

// We do not update argv[0] to point at the target runtime, and so we do not
// pass through our original argv[0] in an environment variable.
- //exitCode = smuggle_path();
- //if (exitCode) return exitCode;
+ exitCode = smuggle_path();
+ if (exitCode) return exitCode;

exitCode = launch(home_path, GetCommandLineW());
return exitCode;

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-leave@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: list-python-checkins@lists.gossamer-threads.com