mirror of https://github.com/astral-sh/uv
Add environment variable to isolate Python version lookups
This commit is contained in:
parent
b95ae00f3c
commit
930dda1086
|
|
@ -2616,6 +2616,7 @@ dependencies = [
|
|||
"platform-tags",
|
||||
"puffin-cache",
|
||||
"puffin-fs",
|
||||
"puffin-warnings",
|
||||
"regex",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ platform-host = { path = "../platform-host" }
|
|||
platform-tags = { path = "../platform-tags" }
|
||||
puffin-cache = { path = "../puffin-cache" }
|
||||
puffin-fs = { path = "../puffin-fs" }
|
||||
puffin-warnings = { path = "../puffin-warnings" }
|
||||
|
||||
fs-err = { workspace = true, features = ["tokio"] }
|
||||
once_cell = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ use crate::python_platform::PythonPlatform;
|
|||
use crate::python_query::find_python_windows;
|
||||
use crate::virtual_env::detect_virtual_env;
|
||||
use crate::{Error, PythonVersion};
|
||||
use puffin_warnings::warn_user_once;
|
||||
|
||||
/// A Python executable and its associated platform markers.
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -132,6 +134,10 @@ impl Interpreter {
|
|||
/// - If a python version is given: `pythonx.y`
|
||||
/// - `python3` (unix) or `python.exe` (windows)
|
||||
///
|
||||
/// If `PUFFIN_PYTHON_PATH` is set, we will not check for Python versions in the
|
||||
/// global PATH, instead we will search using the provided path. Virtual environments
|
||||
/// will still be respected.
|
||||
///
|
||||
/// If a version is provided and an interpreter cannot be found with the given version,
|
||||
/// we will return [`None`].
|
||||
pub fn find_version(
|
||||
|
|
@ -166,7 +172,8 @@ impl Interpreter {
|
|||
python_version.major(),
|
||||
python_version.minor()
|
||||
);
|
||||
if let Ok(executable) = which::which(&requested) {
|
||||
|
||||
if let Ok(executable) = Interpreter::find_executable(&requested) {
|
||||
debug!("Resolved {requested} to {}", executable.display());
|
||||
let interpreter = Interpreter::query(&executable, &platform.0, cache)?;
|
||||
if version_matches(&interpreter) {
|
||||
|
|
@ -175,7 +182,7 @@ impl Interpreter {
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(executable) = which::which("python3") {
|
||||
if let Ok(executable) = Interpreter::find_executable("python3") {
|
||||
debug!("Resolved python3 to {}", executable.display());
|
||||
let interpreter = Interpreter::query(&executable, &platform.0, cache)?;
|
||||
if version_matches(&interpreter) {
|
||||
|
|
@ -194,7 +201,7 @@ impl Interpreter {
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(executable) = which::which("python.exe") {
|
||||
if let Ok(executable) = Interpreter::find_executable("python.exe") {
|
||||
let interpreter = Interpreter::query(&executable, &platform.0, cache)?;
|
||||
if version_matches(&interpreter) {
|
||||
return Ok(Some(interpreter));
|
||||
|
|
@ -207,6 +214,26 @@ impl Interpreter {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn find_executable<R: AsRef<OsStr> + Into<OsString> + Copy>(
|
||||
requested: R,
|
||||
) -> Result<PathBuf, Error> {
|
||||
if let Some(isolated) = std::env::var_os("PUFFIN_PYTHON_PATH") {
|
||||
warn_user_once!(
|
||||
"PUFFIN_PYTHON_PATH is set; ignoring system PATH when looking for binaries."
|
||||
);
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
which::which_in(&requested, Some(isolated), cwd)
|
||||
.map_err(|err| Error::Which(requested.into(), err))
|
||||
} else {
|
||||
which::which_in_global(requested, Some(isolated))
|
||||
.map_err(|err| Error::Which(requested.into(), err))
|
||||
.and_then(|mut paths| paths.next().ok_or(Error::PythonNotFound))
|
||||
}
|
||||
} else {
|
||||
which::which(&requested).map_err(|err| Error::Which(requested.into(), err))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the Python virtual environment.
|
||||
#[inline]
|
||||
pub fn platform(&self) -> &Platform {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTimeError;
|
||||
|
|
@ -59,6 +60,6 @@ pub enum Error {
|
|||
Encode(#[from] rmp_serde::encode::Error),
|
||||
#[error("Failed to parse pyvenv.cfg")]
|
||||
Cfg(#[from] cfg::Error),
|
||||
#[error("Couldn't find `{0}` in PATH")]
|
||||
Which(PathBuf, #[source] which::Error),
|
||||
#[error("Couldn't find {0:?} in PATH")]
|
||||
Which(OsString, #[source] which::Error),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use once_cell::sync::Lazy;
|
|||
use regex::Regex;
|
||||
use tracing::info_span;
|
||||
|
||||
use crate::Error;
|
||||
use crate::{Error, Interpreter};
|
||||
|
||||
/// ```text
|
||||
/// -V:3.12 C:\Users\Ferris\AppData\Local\Programs\Python\Python312\python.exe
|
||||
|
|
@ -34,7 +34,7 @@ pub fn find_requested_python(request: &str) -> Result<PathBuf, Error> {
|
|||
// `-p 3.10` or `-p 3.10.1`
|
||||
if cfg!(unix) {
|
||||
let formatted = PathBuf::from(format!("python{request}"));
|
||||
which::which_global(&formatted).map_err(|err| Error::Which(formatted, err))
|
||||
Interpreter::find_executable(&formatted)
|
||||
} else if cfg!(windows) {
|
||||
if let [major, minor] = versions.as_slice() {
|
||||
find_python_windows(*major, *minor)?.ok_or(Error::NoSuchPython {
|
||||
|
|
@ -49,8 +49,7 @@ pub fn find_requested_python(request: &str) -> Result<PathBuf, Error> {
|
|||
}
|
||||
} else if !request.contains(std::path::MAIN_SEPARATOR) {
|
||||
// `-p python3.10`; Generally not used on windows because all Python are `python.exe`.
|
||||
let request = PathBuf::from(request);
|
||||
which::which_global(&request).map_err(|err| Error::Which(request, err))
|
||||
Interpreter::find_executable(&request)
|
||||
} else {
|
||||
// `-p /home/ferris/.local/bin/python3.10`
|
||||
Ok(fs_err::canonicalize(request)?)
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ async fn venv_impl(
|
|||
find_requested_python(python_request).into_diagnostic()?
|
||||
} else {
|
||||
fs::canonicalize(
|
||||
which::which_global("python3")
|
||||
.or_else(|_| which::which_global("python"))
|
||||
Interpreter::find_executable("python3")
|
||||
.or_else(|_| Interpreter::find_executable("python"))
|
||||
.map_err(|_| VenvError::PythonNotFound)?,
|
||||
)
|
||||
.into_diagnostic()?
|
||||
|
|
|
|||
Loading…
Reference in New Issue