Re-query the interpreter for new venvs

Co-authored-by: Pradyun Gedam <pgedam@bloomberg.net>

When a venv is created, values such as `sys.path` and `site.getsitepackages()` are different from the base interpreter, which we query from the interpreter directly instead of trying to do the transformation ourselves.
This commit is contained in:
konstin 2025-03-05 17:55:11 +01:00
parent cd7a1dbe07
commit c23bc77e8a
16 changed files with 42 additions and 19 deletions

2
Cargo.lock generated
View file

@ -4690,6 +4690,7 @@ dependencies = [
"tokio",
"toml_edit",
"tracing",
"uv-cache",
"uv-configuration",
"uv-distribution",
"uv-distribution-types",
@ -5746,6 +5747,7 @@ dependencies = [
"self-replace",
"thiserror 2.0.11",
"tracing",
"uv-cache",
"uv-fs",
"uv-pypi-types",
"uv-python",

View file

@ -17,6 +17,7 @@ doctest = false
workspace = true
[dependencies]
uv-cache = { workspace = true }
uv-configuration = { workspace = true }
uv-distribution = { workspace = true }
uv-distribution-types = { workspace = true }

View file

@ -27,6 +27,7 @@ use tokio::process::Command;
use tokio::sync::{Mutex, Semaphore};
use tracing::{debug, info_span, instrument, Instrument};
use uv_cache::Cache;
use uv_configuration::{BuildKind, BuildOutput, ConfigSettings, SourceStrategy};
use uv_distribution::BuildRequires;
use uv_distribution_types::{IndexLocations, Resolution};
@ -276,6 +277,7 @@ impl SourceBuild {
mut environment_variables: FxHashMap<OsString, OsString>,
level: BuildOutput,
concurrent_builds: usize,
cache: &Cache,
) -> Result<Self, Error> {
let temp_dir = build_context.cache().venv_dir()?;
@ -316,8 +318,9 @@ impl SourceBuild {
} else {
uv_virtualenv::create_venv(
temp_dir.path(),
interpreter.clone(),
interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
false,

View file

@ -424,6 +424,7 @@ impl BuildContext for BuildDispatch<'_> {
self.build_extra_env_vars.clone(),
build_output,
self.concurrency.builds,
self.cache,
)
.boxed_local()
.await?;

View file

@ -576,7 +576,7 @@ impl Interpreter {
} else {
Either::Right(
self.site_packages_()
.into_iter()
.iter()
.map(|path| Cow::Borrowed(path.as_path())),
)
}

View file

@ -253,7 +253,8 @@ impl InstalledTools {
pub fn create_environment(
&self,
name: &PackageName,
interpreter: Interpreter,
interpreter: &Interpreter,
cache: &Cache,
) -> Result<PythonEnvironment, Error> {
let environment_path = self.tool_dir(name);
@ -279,6 +280,7 @@ impl InstalledTools {
&environment_path,
interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
false,

View file

@ -20,6 +20,7 @@ doctest = false
workspace = true
[dependencies]
uv-cache = { workspace = true }
uv-fs = { workspace = true }
uv-pypi-types = { workspace = true }
uv-python = { workspace = true }

View file

@ -1,5 +1,6 @@
use std::io;
use std::path::Path;
use uv_cache::Cache;
use thiserror::Error;
@ -11,6 +12,8 @@ mod virtualenv;
pub enum Error {
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
InterpreterQuery(#[from] uv_python::InterpreterError),
#[error("Could not find a suitable Python executable for the virtual environment based on the interpreter: {0}")]
NotFound(String),
}
@ -42,8 +45,9 @@ impl Prompt {
#[allow(clippy::fn_params_excessive_bools)]
pub fn create_venv(
location: &Path,
interpreter: Interpreter,
interpreter: &Interpreter,
prompt: Prompt,
cache: &Cache,
system_site_packages: bool,
allow_existing: bool,
relocatable: bool,
@ -52,7 +56,7 @@ pub fn create_venv(
// Create the virtualenv at the given location.
let virtualenv = virtualenv::create(
location,
&interpreter,
interpreter,
prompt,
system_site_packages,
allow_existing,
@ -61,6 +65,6 @@ pub fn create_venv(
)?;
// Create the corresponding `PythonEnvironment`.
let interpreter = interpreter.with_virtualenv(virtualenv);
let interpreter = Interpreter::query(virtualenv.executable, cache)?;
Ok(PythonEnvironment::from_interpreter(interpreter))
}

View file

@ -87,8 +87,9 @@ impl CachedEnvironment {
let temp_dir = cache.venv_dir()?;
let venv = uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
true,

View file

@ -1220,8 +1220,9 @@ impl ProjectEnvironment {
let temp_dir = cache.venv_dir()?;
let environment = uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
prompt,
cache,
false,
false,
false,
@ -1257,8 +1258,9 @@ impl ProjectEnvironment {
let environment = uv_virtualenv::create_venv(
&root,
interpreter,
&interpreter,
prompt,
cache,
false,
false,
false,
@ -1386,8 +1388,9 @@ impl ScriptEnvironment {
let temp_dir = cache.venv_dir()?;
let environment = uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
prompt,
cache,
false,
false,
false,
@ -1420,8 +1423,9 @@ impl ScriptEnvironment {
let environment = uv_virtualenv::create_venv(
&root,
interpreter,
&interpreter,
prompt,
cache,
false,
false,
false,

View file

@ -406,8 +406,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
temp_dir = cache.venv_dir()?;
let environment = uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
false,
@ -596,8 +597,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
temp_dir = cache.venv_dir()?;
uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
false,
@ -821,8 +823,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
temp_dir = cache.venv_dir()?;
let venv = uv_virtualenv::create_venv(
temp_dir.path(),
interpreter,
&interpreter,
uv_virtualenv::Prompt::None,
cache,
false,
false,
false,

View file

@ -176,7 +176,7 @@ pub(crate) fn install_executables(
let installed_packages = InstalledPackages::from_environment(environment)?;
let installed = installed_packages.get_packages(name);
let Some(installed_dist) = installed.first().copied() else {
bail!("Expected at least one requirement")
bail!("Expected at least one installed distribution for executables for {name}")
};
// Find a suitable path to install into

View file

@ -508,7 +508,7 @@ pub(crate) async fn install(
},
};
let environment = installed_tools.create_environment(&from.name, interpreter)?;
let environment = installed_tools.create_environment(&from.name, &interpreter, &cache)?;
// At this point, we removed any existing environment, so we should remove any of its
// executables.

View file

@ -337,7 +337,7 @@ fn get_entrypoints(
) -> anyhow::Result<Vec<(String, PathBuf)>> {
let installed = installed_packages.get_packages(from);
let Some(installed_dist) = installed.first().copied() else {
bail!("Expected at least one requirement")
bail!("Expected at least one installed distribution for entrypoints for {from}")
};
Ok(entrypoint_paths(

View file

@ -302,7 +302,7 @@ async fn upgrade_tool(
)
.await?;
let environment = installed_tools.create_environment(name, interpreter.clone())?;
let environment = installed_tools.create_environment(name, interpreter, cache)?;
let environment = sync_environment(
environment,

View file

@ -263,8 +263,9 @@ async fn venv_impl(
// Create the virtual environment.
let venv = uv_virtualenv::create_venv(
&path,
interpreter,
&interpreter,
prompt,
cache,
system_site_packages,
allow_existing,
relocatable,