Skip to content

gh-106045: Keep searching from venv home when the resolved base executable has no stdlib - #160123

Merged
itamaro merged 5 commits into
python:mainfrom
itamaro:gh-106045-venv-home-fallback
Oct 22, 2026
Merged

itamaro merged 5 commits into
python:mainfrom
itamaro:gh-106045-venv-home-fallback

Conversation

@itamaro

@itamaro itamaro commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

GH-156483 made getpath locate a venv's base installation relative to the resolved base executable instead of the home key in pyvenv.cfg. When the resolved executable lives outside the installation tree (e.g. a launcher binary symlinked into it), nothing is found there and discovery falls back to the compiled-in PREFIX. The venv then either fails to start or silently runs with another installation's standard library.

This PR:

  • Keeps gh-106045: Fix venv path discovery for symlinked executables #156483's behavior when the resolved executable's directory locates a standard library (pybuilddir.txt, the stdlib zip, or os.py). Otherwise it keeps searching from home, as before gh-106045: Fix venv path discovery for symlinked executables #156483.
  • In that fallback case, still searches the resolved executable's directory for lib-dynload when determining exec_prefix: after prefix, before home and the compiled-in EXEC_PREFIX. Layouts with a separate exec prefix (e.g. ./configure --exec-prefix) then keep loading extension modules from the right place, and a stale lib-dynload near the home symlink can't take precedence over the one beside the resolved executable.

The tests added by GH-156483 pass unchanged. Three new test_getpath cases cover the launcher-outside-the-installation and separate-exec-prefix layouts, and a misleading lib-dynload near home; each fails without this change.

Reproducer

On main (0a86a34), with a plain ./configure --prefix=$HOME/py-under-test && make && make install:

#!/bin/sh
# Usage: venv-home-repro.sh <installed-prefix> <X.Y>
set -eu
PREFIX=$1; VER=$2
W=$(mktemp -d)
mkdir -p "$W/runtime/bin" "$W/runtime/lib" "$W/launcher"
cp -R "$PREFIX/lib/python$VER" "$W/runtime/lib/"
cp "$PREFIX/bin/python$VER" "$W/launcher/python3"
ln -s "$W/launcher/python3" "$W/runtime/bin/python3"
PYTHONHOME="$W/runtime" "$W/runtime/bin/python3" -m venv --without-pip "$W/venv"
grep '^home' "$W/venv/pyvenv.cfg"
echo "expected base_prefix: $W/runtime"
"$W/venv/bin/python" -c 'import os, sys; print("actual base_prefix:", sys.base_prefix); print("os.py loaded from:", os.__file__)'

Before:

home = /tmp/tmp.NFug9wEr4h/runtime/bin
expected base_prefix: /tmp/tmp.NFug9wEr4h/runtime
actual base_prefix: /home/user/py-under-test
os.py loaded from: /home/user/py-under-test/lib/python3.16/os.py

(With $HOME/py-under-test/lib/python3.16 removed, the venv instead fails with ModuleNotFoundError: No module named 'encodings'.)

After:

home = /tmp/tmp.8Zne2otFrw/runtime/bin
expected base_prefix: /tmp/tmp.8Zne2otFrw/runtime
actual base_prefix: /tmp/tmp.8Zne2otFrw/runtime
os.py loaded from: /tmp/tmp.8Zne2otFrw/runtime/lib/python3.16/os.py

Written with assistance from Claude Code Fable 5.1

Comment thread Modules/getpath.py
@bedevere-app

bedevere-app Bot commented Oct 21, 2026

Copy link
Copy Markdown

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

@ambv

ambv commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

If you rebase, the Hypo failure is fixed.

itamaro and others added 2 commits October 21, 2026 17:28
… executable has no stdlib

pythonGH-156483 searches for a venv's base installation relative to the
resolved base executable. When that executable lives outside the
installation tree that 'home' in pyvenv.cfg points into (e.g. a launcher
binary symlinked into it), nothing is found there and discovery falls
back to the compiled-in PREFIX.

Only prefer the resolved executable's directory when a standard library
landmark is found from there; otherwise keep searching from 'home'.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A93JzpSGH27i6PNX8re4YV
Even when stdlib discovery falls back to 'home', the resolved base
executable may live under a separate exec_prefix (e.g. ./configure
--exec-prefix), so search there for platform dependent libraries before
falling back to the compiled-in EXEC_PREFIX.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A93JzpSGH27i6PNX8re4YV
@itamaro
itamaro force-pushed the gh-106045-venv-home-fallback branch from 620ac1e to 72b32a4 Compare October 22, 2026 00:33
@itamaro

itamaro commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

I have made the requested changes; please review again.

@bedevere-app

bedevere-app Bot commented Oct 22, 2026

Copy link
Copy Markdown

Thanks for making the requested changes!

@ambv: please review the changes made to this pull request.

@bedevere-app
bedevere-app Bot requested a review from ambv October 22, 2026 00:42
Comment thread Modules/getpath.py Outdated
Comment thread Lib/test/test_getpath.py
itamaro and others added 2 commits October 22, 2026 11:08
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
@ambv ambv removed the skip news label Oct 22, 2026
@ambv

ambv commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

We can no longer "skip news" for this if it shipped to 3.14.9 and 3.15.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A93JzpSGH27i6PNX8re4YV
@ambv

ambv commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

@itamaro nitpick: update the description before landing to match the code.

It says the resolved executable's directory is searched for lib-dynload "after prefix and home". Since your reorder, it's searched after prefix but before home (Modules/getpath.py:636-642). And there's three cases.

@itamaro

itamaro commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@itamaro nitpick: update the description before landing to match the code.

It says the resolved executable's directory is searched for lib-dynload "after prefix and home". Since your reorder, it's searched after prefix but before home (Modules/getpath.py:636-642). And there's three cases.

thanks, updated the description!

@itamaro
itamaro enabled auto-merge (squash) October 22, 2026 20:26
@itamaro
itamaro merged commit 5b55b50 into python:main Oct 22, 2026
62 of 63 checks passed
@miss-islington-app

Copy link
Copy Markdown

Thanks @itamaro for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14, 3.15.
🐍🍒⛏🤖

@bedevere-app

bedevere-app Bot commented Oct 22, 2026

Copy link
Copy Markdown

GH-160354 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 bugs and security fixes label Oct 22, 2026
@bedevere-app

bedevere-app Bot commented Oct 22, 2026

Copy link
Copy Markdown

GH-160355 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.14 bugs and security fixes 3.15 bugs and security fixes release-blocker

Projects

Development

Successfully merging this pull request may close these issues.

2 participants