Skip to content

🐛 fix(env): strip PYTHONPATH from isolated builds#1024

Merged
gaborbernat merged 1 commit intopypa:mainfrom
gaborbernat:fix/pythonpath-isolation
Apr 10, 2026
Merged

🐛 fix(env): strip PYTHONPATH from isolated builds#1024
gaborbernat merged 1 commit intopypa:mainfrom
gaborbernat:fix/pythonpath-isolation

Conversation

@gaborbernat
Copy link
Copy Markdown
Collaborator

Closes #405

When PYTHONPATH is set in the host environment, it leaks into isolated build subprocesses. The build backend and package installers then discover packages from the host instead of the isolated venv, breaking the isolation contract. 🔒 This causes hard-to-diagnose build failures when the host has incompatible package versions — for example, an old pip that lacks --use-pep517.

The fix clears PYTHONPATH in make_extra_environ() so all backend hook calls via pyproject_hooks strip it from their subprocess environment. The uv backend's install path, which explicitly passes os.environ, also gets the same treatment. Internal pip calls already use -Im (isolated mode) which ignores PYTHONPATH, so they were unaffected.

Setting PYTHONPATH to an empty string (rather than removing it) ensures the key is present in the environment dict and overrides whatever value the host had, even when the runner merges it with os.environ.copy(). Non-isolated builds (--no-isolation) are unaffected since they don't go through DefaultIsolatedEnv.

@gaborbernat gaborbernat requested a review from FFY00 as a code owner April 10, 2026 17:17
@gaborbernat gaborbernat added the bug Something isn't working label Apr 10, 2026
@gaborbernat gaborbernat force-pushed the fix/pythonpath-isolation branch 2 times, most recently from 6301f3b to 10ceaa3 Compare April 10, 2026 18:47
When PYTHONPATH is set in the host environment it leaks into isolated
build subprocesses, causing the build backend and package installers to
discover packages from the host instead of the isolated venv. This
breaks the isolation contract and can cause build failures when the
host has incompatible package versions.

Strip PYTHONPATH from os.environ on DefaultIsolatedEnv entry and
restore it on exit. This covers all subprocess calls within the
isolated context: backend hook invocations via pyproject_hooks, pip
and uv install commands, and venv creation via ensurepip.
@gaborbernat gaborbernat force-pushed the fix/pythonpath-isolation branch from 10ceaa3 to c6249bf Compare April 10, 2026 19:04
@gaborbernat
Copy link
Copy Markdown
Collaborator Author

Updated the approach per your feedback. The fix now:

  1. make_extra_environ() returns PYTHONPATH: '' — this overrides the host value when pyproject_hooks' runner does os.environ.copy().update(extra_environ). An empty PYTHONPATH is treated as unset by CPython's path initialization (if pythonpath_env: is falsy for empty string), so no paths are added to sys.path.

  2. _UvBackend.install_dependencies() builds the env dict by filtering out PYTHONPATH entirely (it passes env= directly to subprocess, so true removal is possible here).

No os.environ mutation, fully thread-safe. The PYTHONPATH='' approach through extra_environ is the only way to override the value without bypassing the pyproject_hooks runner (which handles stdout/stderr display for verbosity control).

@henryiii
Copy link
Copy Markdown
Contributor

Okay, that's reasonable. Maybe could be a future thing to do in pyproject_hooks.

@gaborbernat gaborbernat merged commit 27b67b2 into pypa:main Apr 10, 2026
65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PYTHONPATH affects isolated builds

2 participants