mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-01 12:24:15 +00:00
Avoid Windows Store shims in --python python3-like invocations (#2212)
## Summary We have logic in `python_query.rs` to filter out Windows Store shims when you use invocations like `-p 3.10`, but not `--python python3`, which is uncommon but allowed on Windows. Closes #2211.
This commit is contained in:
parent
cf94df7cb9
commit
01ebaef4e7
2 changed files with 37 additions and 21 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
use std::ffi::{OsStr, OsString};
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
@ -200,25 +199,6 @@ impl Interpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the Python interpreter in `PATH`, respecting `UV_PYTHON_PATH`.
|
|
||||||
///
|
|
||||||
/// Returns `Ok(None)` if not found.
|
|
||||||
pub(crate) fn find_executable<R: AsRef<OsStr> + Into<OsString> + Copy>(
|
|
||||||
requested: R,
|
|
||||||
) -> Result<Option<PathBuf>, Error> {
|
|
||||||
let result = if let Some(isolated) = std::env::var_os("UV_TEST_PYTHON_PATH") {
|
|
||||||
which::which_in(requested, Some(isolated), std::env::current_dir()?)
|
|
||||||
} else {
|
|
||||||
which::which(requested)
|
|
||||||
};
|
|
||||||
|
|
||||||
match result {
|
|
||||||
Err(which::Error::CannotFindBinaryPath) => Ok(None),
|
|
||||||
Err(err) => Err(Error::WhichError(requested.into(), err)),
|
|
||||||
Ok(path) => Ok(Some(path)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the path to the Python virtual environment.
|
/// Returns the path to the Python virtual environment.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn platform(&self) -> &Platform {
|
pub fn platform(&self) -> &Platform {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
@ -58,7 +59,7 @@ pub fn find_requested_python(
|
||||||
}
|
}
|
||||||
} else if !request.contains(std::path::MAIN_SEPARATOR) {
|
} else if !request.contains(std::path::MAIN_SEPARATOR) {
|
||||||
// `-p python3.10`; Generally not used on windows because all Python are `python.exe`.
|
// `-p python3.10`; Generally not used on windows because all Python are `python.exe`.
|
||||||
let Some(executable) = Interpreter::find_executable(request)? else {
|
let Some(executable) = find_executable(request)? else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
Interpreter::query(&executable, platform.clone(), cache).map(Some)
|
Interpreter::query(&executable, platform.clone(), cache).map(Some)
|
||||||
|
|
@ -198,6 +199,41 @@ fn find_python(
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the Python interpreter in `PATH` matching the given name (e.g., `python3`, respecting
|
||||||
|
/// `UV_PYTHON_PATH`.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(None)` if not found.
|
||||||
|
fn find_executable<R: AsRef<OsStr> + Into<OsString> + Copy>(
|
||||||
|
requested: R,
|
||||||
|
) -> Result<Option<PathBuf>, Error> {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let UV_TEST_PYTHON_PATH = env::var_os("UV_TEST_PYTHON_PATH");
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let PATH = UV_TEST_PYTHON_PATH
|
||||||
|
.or(env::var_os("PATH"))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// We use `which` here instead of joining the paths ourselves because `which` checks for us if the python
|
||||||
|
// binary is executable and exists. It also has some extra logic that handles inconsistent casing on Windows
|
||||||
|
// and expands `~`.
|
||||||
|
for path in env::split_paths(&PATH) {
|
||||||
|
let paths = match which::which_in_global(requested, Some(&path)) {
|
||||||
|
Ok(paths) => paths,
|
||||||
|
Err(which::Error::CannotFindBinaryPath) => continue,
|
||||||
|
Err(err) => return Err(Error::WhichError(requested.into(), err)),
|
||||||
|
};
|
||||||
|
for path in paths {
|
||||||
|
if cfg!(windows) && windows::is_windows_store_shim(&path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Ok(Some(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum PythonInstallation {
|
enum PythonInstallation {
|
||||||
PyListPath {
|
PyListPath {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue