diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index 7e5c4a3d14d..f86df9d0d03 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -832,6 +832,37 @@ def test_explicitly_set_stdlib_dir(self): actual = getpath(ns, expected) self.assertEqual(expected, actual) + def test_PYTHONHOME_in_venv(self): + "Make sure prefix/exec_prefix still point to the venv if PYTHONHOME was used." + ns = MockPosixNamespace( + argv0="/venv/bin/python", + PREFIX="/usr", + ENV_PYTHONHOME="/pythonhome", + ) + # Setup venv + ns.add_known_xfile("/venv/bin/python") + ns.add_known_file("/venv/pyvenv.cfg", [ + r"home = /usr/bin" + ]) + # Seutup PYTHONHOME + ns.add_known_file("/pythonhome/lib/python9.8/os.py") + ns.add_known_dir("/pythonhome/lib/python9.8/lib-dynload") + + expected = dict( + executable="/venv/bin/python", + prefix="/venv", + exec_prefix="/venv", + base_prefix="/pythonhome", + base_exec_prefix="/pythonhome", + module_search_paths_set=1, + module_search_paths=[ + "/pythonhome/lib/python98.zip", + "/pythonhome/lib/python9.8", + "/pythonhome/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) # ****************************************************************************** diff --git a/Modules/getpath.py b/Modules/getpath.py index b14f985a0d5..c34101e7208 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -344,9 +344,10 @@ def search_up(prefix, *landmarks, test=isfile): venv_prefix = None -# Calling Py_SetPythonHome(), Py_SetPath() or -# setting $PYTHONHOME will override venv detection. -if not home and not py_setpath: +# Calling Py_SetPath() will override venv detection. +# Calling Py_SetPythonHome() or setting $PYTHONHOME will override the 'home' key +# specified in pyvenv.cfg. +if not py_setpath: try: # prefix2 is just to avoid calculating dirname again later, # as the path in venv_prefix is the more common case. @@ -370,6 +371,9 @@ def search_up(prefix, *landmarks, test=isfile): for line in pyvenvcfg: key, had_equ, value = line.partition('=') if had_equ and key.strip().lower() == 'home': + # If PYTHONHOME was set, ignore 'home' from pyvenv.cfg. + if home: + break # Override executable_dir/real_executable_dir with the value from 'home'. # These values may be later used to calculate prefix/base_prefix, if a more # reliable source — like the runtime library (libpython) path — isn't available.