]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46028: Calculate base_executable by resolving symlinks in a venv (GH-30144)
authorSteve Dower <steve.dower@python.org>
Tue, 18 Jan 2022 15:46:26 +0000 (15:46 +0000)
committerGitHub <noreply@github.com>
Tue, 18 Jan 2022 15:46:26 +0000 (15:46 +0000)
Lib/test/test_getpath.py
Misc/NEWS.d/next/Core and Builtins/2021-12-16-15-04-58.bpo-46028.zfWacB.rst [new file with mode: 0644]
Modules/getpath.py

index 1a336a4abcafdb18e6e62596821e34b4329fef1c..eaf4a99279663e04fa405df97be37b0d58a5d410 100644 (file)
@@ -328,6 +328,38 @@ class MockGetPathTests(unittest.TestCase):
         actual = getpath(ns, expected)
         self.assertEqual(expected, actual)
 
+    def test_venv_changed_name_posix(self):
+        "Test a venv layout on *nix."
+        ns = MockPosixNamespace(
+            argv0="python",
+            PREFIX="/usr",
+            ENV_PATH="/venv/bin:/usr/bin",
+        )
+        ns.add_known_xfile("/usr/bin/python3")
+        ns.add_known_xfile("/venv/bin/python")
+        ns.add_known_link("/venv/bin/python", "/usr/bin/python3")
+        ns.add_known_file("/usr/lib/python9.8/os.py")
+        ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
+        ns.add_known_file("/venv/pyvenv.cfg", [
+            r"home = /usr/bin"
+        ])
+        expected = dict(
+            executable="/venv/bin/python",
+            prefix="/usr",
+            exec_prefix="/usr",
+            base_executable="/usr/bin/python3",
+            base_prefix="/usr",
+            base_exec_prefix="/usr",
+            module_search_paths_set=1,
+            module_search_paths=[
+                "/usr/lib/python98.zip",
+                "/usr/lib/python9.8",
+                "/usr/lib/python9.8/lib-dynload",
+            ],
+        )
+        actual = getpath(ns, expected)
+        self.assertEqual(expected, actual)
+
     def test_symlink_normal_posix(self):
         "Test a 'standard' install layout via symlink on *nix"
         ns = MockPosixNamespace(
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-16-15-04-58.bpo-46028.zfWacB.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-16-15-04-58.bpo-46028.zfWacB.rst
new file mode 100644 (file)
index 0000000..cc34c0f
--- /dev/null
@@ -0,0 +1,3 @@
+Fixes calculation of :data:`sys._base_executable` when inside a virtual
+environment that uses symlinks with different binary names than the base
+environment provides.
index 6f2e0385577221b83edde9d94cb6fb6c83e7fb1d..f84e6e8afaf62ced7ba2b8ee48c112d3a1a642ba 100644 (file)
@@ -351,7 +351,18 @@ if not home and not py_setpath:
         key, had_equ, value = line.partition('=')
         if had_equ and key.strip().lower() == 'home':
             executable_dir = real_executable_dir = value.strip()
-            base_executable = joinpath(executable_dir, basename(executable))
+            if not base_executable:
+                # First try to resolve symlinked executables, since that may be
+                # more accurate than assuming the executable in 'home'.
+                try:
+                    base_executable = realpath(executable)
+                    if base_executable == executable:
+                        # No change, so probably not a link. Clear it and fall back
+                        base_executable = ''
+                except OSError:
+                    pass
+                if not base_executable:
+                    base_executable = joinpath(executable_dir, basename(executable))
             break
     else:
         venv_prefix = None