summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_getpath.py32
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-12-16-15-04-58.bpo-46028.zfWacB.rst3
-rw-r--r--Modules/getpath.py13
3 files changed, 47 insertions, 1 deletions
diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py
index 1a336a4..eaf4a99 100644
--- a/Lib/test/test_getpath.py
+++ b/Lib/test/test_getpath.py
@@ -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
index 0000000..cc34c0f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-16-15-04-58.bpo-46028.zfWacB.rst
@@ -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.
diff --git a/Modules/getpath.py b/Modules/getpath.py
index 6f2e038..f84e6e8 100644
--- a/Modules/getpath.py
+++ b/Modules/getpath.py
@@ -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