Include all site packages directories in ephemeral environment overlays (#15121)

Related to https://github.com/astral-sh/uv/issues/15113

The case in the linked issue is that we perhaps should not be allowing
`uv run --with` with system interpreters at all. I think we can consider
that, but the issue highlighted that `uv run --with` for a system
interpreter is broken if the base interpreter has custom site packages.
This generalizes beyond system interpreters so we should probably fix
our overlays.
This commit is contained in:
Zanie Blue 2025-08-08 13:49:21 -05:00 committed by GitHub
parent f6a9b55eb7
commit bdb4b061db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 54 additions and 13 deletions

View file

@ -4,6 +4,7 @@ Queries information about the current Python interpreter and prints it as JSON.
The script will exit with status 0 on known error that are turned into rust errors.
"""
import site
import sys
import json
@ -637,6 +638,7 @@ def main() -> None:
# temporary path to `sys.path` so we can import it, which we have to strip later
# to avoid having this now-deleted path around.
"sys_path": sys.path[1:],
"site_packages": site.getsitepackages(),
"stdlib": sysconfig.get_path("stdlib"),
# Prior to the introduction of `sysconfig` patching, python-build-standalone installations would always use
# "/install" as the prefix. With `sysconfig` patching, we rewrite the prefix to match the actual installation

View file

@ -51,6 +51,7 @@ pub struct Interpreter {
sys_base_executable: Option<PathBuf>,
sys_executable: PathBuf,
sys_path: Vec<PathBuf>,
site_packages: Vec<PathBuf>,
stdlib: PathBuf,
standalone: bool,
tags: OnceLock<Tags>,
@ -86,6 +87,7 @@ impl Interpreter {
sys_base_executable: info.sys_base_executable,
sys_executable: info.sys_executable,
sys_path: info.sys_path,
site_packages: info.site_packages,
stdlib: info.stdlib,
standalone: info.standalone,
tags: OnceLock::new(),
@ -439,10 +441,21 @@ impl Interpreter {
}
/// Return the `sys.path` for this Python interpreter.
pub fn sys_path(&self) -> &Vec<PathBuf> {
pub fn sys_path(&self) -> &[PathBuf] {
&self.sys_path
}
/// Return the `site.getsitepackages` for this Python interpreter.
///
/// These are the paths Python will search for packages in at runtime. We use this for
/// environment layering, but not for checking for installed packages. We could use these paths
/// to check for installed packages, but it introduces a lot of complexity, so instead we use a
/// simplified version that does not respect customized site-packages. See
/// [`Interpreter::site_packages`].
pub fn runtime_site_packages(&self) -> &[PathBuf] {
&self.site_packages
}
/// Return the `stdlib` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn stdlib(&self) -> &Path {
&self.stdlib
@ -567,6 +580,9 @@ impl Interpreter {
///
/// Some distributions also create symbolic links from `purelib` to `platlib`; in such cases, we
/// still deduplicate the entries, returning a single path.
///
/// Note this does not include all runtime site-packages directories if the interpreter has been
/// customized. See [`Interpreter::runtime_site_packages`].
pub fn site_packages(&self) -> impl Iterator<Item = Cow<'_, Path>> {
let target = self.target().map(Target::site_packages);
@ -870,6 +886,7 @@ struct InterpreterInfo {
sys_base_executable: Option<PathBuf>,
sys_executable: PathBuf,
sys_path: Vec<PathBuf>,
site_packages: Vec<PathBuf>,
stdlib: PathBuf,
standalone: bool,
pointer_size: PointerSize,
@ -1247,6 +1264,9 @@ mod tests {
"/home/ferris/.pyenv/versions/3.12.0/lib/python3.12/lib/python3.12",
"/home/ferris/.pyenv/versions/3.12.0/lib/python3.12/site-packages"
],
"site_packages": [
"/home/ferris/.pyenv/versions/3.12.0/lib/python3.12/site-packages"
],
"stdlib": "/home/ferris/.pyenv/versions/3.12.0/lib/python3.12",
"scheme": {
"data": "/home/ferris/.pyenv/versions/3.12.0",

View file

@ -272,6 +272,9 @@ mod tests {
"/home/ferris/.pyenv/versions/{FULL_VERSION}/lib/python{VERSION}/lib/python{VERSION}",
"/home/ferris/.pyenv/versions/{FULL_VERSION}/lib/python{VERSION}/site-packages"
],
"site_packages": [
"/home/ferris/.pyenv/versions/{FULL_VERSION}/lib/python{VERSION}/site-packages"
],
"stdlib": "/home/ferris/.pyenv/versions/{FULL_VERSION}/lib/python{VERSION}",
"scheme": {
"data": "/home/ferris/.pyenv/versions/{FULL_VERSION}",