Skip to content

Commit d12ab93

Browse files
committed
gh-154160: Make sys.executable absolute when resolved from a relative PATH entry
When the interpreter is started by a bare program name and found through a relative directory in PATH, getpath left sys.executable as that relative path, contrary to its documented behaviour of being an absolute path. This is a regression from the getpath.c rewrite in 3.11. Absolutize the executable resolved from PATH, matching the sibling branch that already calls abspath() when the program name itself contains a separator.
1 parent 249d5e0 commit d12ab93

3 files changed

Lines changed: 32 additions & 1 deletion

File tree

Lib/test/test_getpath.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,32 @@ def test_normal_posix(self):
290290
actual = getpath(ns, expected)
291291
self.assertEqual(expected, actual)
292292

293+
def test_relative_path_env_posix(self):
294+
"Resolving the executable from a relative PATH entry yields an absolute path (gh-154160)"
295+
ns = MockPosixNamespace(
296+
PREFIX="/usr",
297+
argv0="python",
298+
ENV_PATH="usr/bin",
299+
)
300+
ns.add_known_xfile("usr/bin/python")
301+
ns.add_known_xfile("/Absolute/usr/bin/python")
302+
ns.add_known_file("/usr/lib/python9.8/os.py")
303+
ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
304+
expected = dict(
305+
executable="/Absolute/usr/bin/python",
306+
base_executable="/Absolute/usr/bin/python",
307+
prefix="/usr",
308+
exec_prefix="/usr",
309+
module_search_paths_set=1,
310+
module_search_paths=[
311+
"/usr/lib/python98.zip",
312+
"/usr/lib/python9.8",
313+
"/usr/lib/python9.8/lib-dynload",
314+
],
315+
)
316+
actual = getpath(ns, expected)
317+
self.assertEqual(expected, actual)
318+
293319
def test_buildpath_posix(self):
294320
"""Test an in-build-tree layout on POSIX.
295321
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed :data:`sys.executable` being a relative path when the interpreter was
2+
found through a relative entry in :envvar:`PATH`. It is now made absolute, as
3+
documented.

Modules/getpath.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ def search_up(prefix, *landmarks, test=isfile):
285285
for p in ENV_PATH.split(DELIM):
286286
p = joinpath(p, program_name)
287287
if isxfile(p):
288-
executable = p
288+
# A relative PATH entry would otherwise leave executable
289+
# relative, contrary to the documented behaviour (gh-154160).
290+
executable = abspath(p)
289291
break
290292

291293
if not executable:

0 commit comments

Comments
 (0)