mirror of https://github.com/astral-sh/uv
Add support for disabling provider isolation with `UV_NO_PROVIDER_ISOLATION`
This commit is contained in:
parent
7e69f62093
commit
80db77d7c2
|
|
@ -1175,4 +1175,15 @@ impl EnvVars {
|
|||
/// around invalid artifacts in rare cases.
|
||||
#[attr_added_in("0.8.23")]
|
||||
pub const UV_SKIP_WHEEL_FILENAME_CHECK: &'static str = "UV_SKIP_WHEEL_FILENAME_CHECK";
|
||||
|
||||
/// A comma separated list of variant provider backends that use the current environment instead
|
||||
/// of an isolated environment.
|
||||
///
|
||||
/// The requirements need to be installed in the current environment, no provider `requires`
|
||||
/// will be installed. This option is intended for development and as an escape hatch where
|
||||
/// isolation fails.
|
||||
///
|
||||
/// Example: `UV_NO_PROVIDER_ISOLATION=gpu.provider:api,cpu,blas.backend`
|
||||
#[attr_added_in("0.9.2")]
|
||||
pub const UV_NO_PROVIDER_ISOLATION: &'static str = "UV_NO_PROVIDER_ISOLATION";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
mod error;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::Write;
|
||||
use std::io;
|
||||
|
|
@ -68,6 +69,36 @@ impl VariantBuild {
|
|||
) -> Result<Self, Error> {
|
||||
let temp_dir = build_context.cache().venv_dir()?;
|
||||
|
||||
// TODO(konsti): This is not the right location to parse the env var.
|
||||
let plugin_api = Self::plugin_api(&backend_name, backend, interpreter)?;
|
||||
let no_isolation =
|
||||
env::var(EnvVars::UV_NO_PROVIDER_ISOLATION).is_ok_and(|no_provider_isolation| {
|
||||
no_provider_isolation
|
||||
.split(",")
|
||||
.any(|api| (api) == plugin_api)
|
||||
});
|
||||
|
||||
// TODO(konsti): Integrate this properly with the configuration system.
|
||||
if no_isolation {
|
||||
debug!("Querying provider plugin without isolation: {backend_name}");
|
||||
|
||||
let runner = PythonRunner::new(concurrent_builds, level);
|
||||
let env = PythonEnvironment::from_interpreter(interpreter.clone());
|
||||
// The unmodified path
|
||||
let modified_path = OsString::from(env.scripts());
|
||||
|
||||
return Ok(Self {
|
||||
temp_dir,
|
||||
backend_name,
|
||||
backend: backend.clone(),
|
||||
venv: env,
|
||||
level,
|
||||
modified_path,
|
||||
environment_variables,
|
||||
runner,
|
||||
});
|
||||
}
|
||||
|
||||
// Create a virtual environment.
|
||||
let venv = uv_virtualenv::create_venv(
|
||||
temp_dir.path(),
|
||||
|
|
@ -149,36 +180,42 @@ impl VariantBuild {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn import(&self) -> Result<String, Error> {
|
||||
let import = if let Some(plugin_api) = &self.backend.plugin_api {
|
||||
if let Some((path, object)) = plugin_api.split_once(':') {
|
||||
format!("from {path} import {object} as backend")
|
||||
} else {
|
||||
format!("import {plugin_api} as backend")
|
||||
}
|
||||
// Not a method to be callable in the constructor.
|
||||
pub fn plugin_api<'a>(
|
||||
backend_name: &str,
|
||||
backend: &'a Provider,
|
||||
interpreter: &Interpreter,
|
||||
) -> Result<Cow<'a, str>, Error> {
|
||||
if let Some(plugin_api) = &backend.plugin_api {
|
||||
Ok(Cow::Borrowed(plugin_api))
|
||||
} else {
|
||||
let requires = self
|
||||
.backend
|
||||
let requires = backend
|
||||
.requires
|
||||
.as_ref()
|
||||
.ok_or_else(|| Error::MissingRequires(self.backend_name.clone()))?
|
||||
.ok_or_else(|| Error::MissingRequires(backend_name.to_string()))?
|
||||
.iter()
|
||||
.filter(|requirement| {
|
||||
requirement.evaluate_markers(
|
||||
self.venv.interpreter().markers(),
|
||||
&Vec::new().as_slice(),
|
||||
&[],
|
||||
)
|
||||
requirement.evaluate_markers(interpreter.markers(), &Vec::new().as_slice(), &[])
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if let [requires] = requires.as_slice() {
|
||||
format!("import {} as backend", requires.name.as_dist_info_name())
|
||||
Ok(requires.name.as_dist_info_name())
|
||||
} else {
|
||||
return Err(Error::InvalidRequires {
|
||||
backend_name: self.backend_name.clone(),
|
||||
Err(Error::InvalidRequires {
|
||||
backend_name: backend_name.to_string(),
|
||||
matching: requires.len(),
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn import(&self) -> Result<String, Error> {
|
||||
let plugin_api =
|
||||
Self::plugin_api(&self.backend_name, &self.backend, self.venv.interpreter())?;
|
||||
let import = if let Some((path, object)) = plugin_api.split_once(':') {
|
||||
format!("from {path} import {object} as backend")
|
||||
} else {
|
||||
format!("import {plugin_api} as backend")
|
||||
};
|
||||
|
||||
Ok(formatdoc! {r#"
|
||||
|
|
|
|||
Loading…
Reference in New Issue