diff --git a/crates/uv-static/src/env_vars.rs b/crates/uv-static/src/env_vars.rs index fc073cf92..b74b058ec 100644 --- a/crates/uv-static/src/env_vars.rs +++ b/crates/uv-static/src/env_vars.rs @@ -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"; } diff --git a/crates/uv-variant-frontend/src/lib.rs b/crates/uv-variant-frontend/src/lib.rs index c06746114..5d121839f 100644 --- a/crates/uv-variant-frontend/src/lib.rs +++ b/crates/uv-variant-frontend/src/lib.rs @@ -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 { 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 { - 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, 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::>(); 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 { + 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#"