mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-30 14:01:13 +00:00
Warn when an unsupported Python version is encountered (#3250)
I rebased https://github.com/astral-sh/uv/pull/2757 then realized that we want to implement this for more than `uv venv`. Closes https://github.com/astral-sh/uv/issues/2587 Closes https://github.com/astral-sh/uv/issues/2757 ``` ❯ cargo run -q -- pip install -p /Users/mz/bin/python3.7 anyio warning: uv is only compatible with Python 3.8+, found Python 3.7.17. Audited 1 package in 84ms ❯ cargo run -q -- venv -p /Users/mz/bin/python3.7 warning: uv is only compatible with Python 3.8+, found Python 3.7.17. Using Python 3.7.17 interpreter at: /Users/mz/bin/python3.7 Creating virtualenv at: .venv Activate with: source .venv/bin/activate ``` --------- Co-authored-by: Stevie Gayet <stegayet@users.noreply.github.com>
This commit is contained in:
parent
20e9589662
commit
c22e15f07d
4 changed files with 36 additions and 10 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4862,6 +4862,7 @@ dependencies = [
|
|||
"uv-cache",
|
||||
"uv-fs",
|
||||
"uv-toolchain",
|
||||
"uv-warnings",
|
||||
"which",
|
||||
"winapi",
|
||||
]
|
||||
|
|
|
@ -22,6 +22,7 @@ pypi-types = { workspace = true }
|
|||
uv-cache = { workspace = true }
|
||||
uv-fs = { workspace = true }
|
||||
uv-toolchain = { workspace = true }
|
||||
uv-warnings = { workspace = true }
|
||||
|
||||
configparser = { workspace = true }
|
||||
fs-err = { workspace = true, features = ["tokio"] }
|
||||
|
|
|
@ -7,6 +7,7 @@ use tracing::{debug, instrument};
|
|||
|
||||
use uv_cache::Cache;
|
||||
use uv_toolchain::PythonVersion;
|
||||
use uv_warnings::warn_user_once;
|
||||
|
||||
use crate::interpreter::InterpreterInfoError;
|
||||
use crate::python_environment::{detect_python_executable, detect_virtual_env};
|
||||
|
@ -42,7 +43,11 @@ pub fn find_requested_python(request: &str, cache: &Cache) -> Result<Option<Inte
|
|||
// SAFETY: Guaranteed by the Ok(versions) guard
|
||||
_ => unreachable!(),
|
||||
};
|
||||
find_python(selector, cache)
|
||||
let interpreter = find_python(selector, cache)?;
|
||||
interpreter
|
||||
.as_ref()
|
||||
.inspect(|inner| warn_on_unsupported_python(inner));
|
||||
Ok(interpreter)
|
||||
} else {
|
||||
match fs_err::metadata(request) {
|
||||
Ok(metadata) => {
|
||||
|
@ -61,14 +66,18 @@ pub fn find_requested_python(request: &str, cache: &Cache) -> Result<Option<Inte
|
|||
// `-p /home/ferris/.local/bin/python3.10`
|
||||
path
|
||||
};
|
||||
Interpreter::query(executable, cache).map(Some)
|
||||
Interpreter::query(executable, cache)
|
||||
.inspect(warn_on_unsupported_python)
|
||||
.map(Some)
|
||||
}
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||
// `-p python3.10`; Generally not used on windows because all Python are `python.exe`.
|
||||
let Some(executable) = find_executable(request)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
Interpreter::query(executable, cache).map(Some)
|
||||
Interpreter::query(executable, cache)
|
||||
.inspect(warn_on_unsupported_python)
|
||||
.map(Some)
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
|
@ -82,13 +91,15 @@ pub fn find_requested_python(request: &str, cache: &Cache) -> Result<Option<Inte
|
|||
#[instrument(skip_all)]
|
||||
pub fn find_default_python(cache: &Cache) -> Result<Interpreter, Error> {
|
||||
debug!("Starting interpreter discovery for default Python");
|
||||
try_find_default_python(cache)?.ok_or(if cfg!(windows) {
|
||||
try_find_default_python(cache)?
|
||||
.ok_or(if cfg!(windows) {
|
||||
Error::NoPythonInstalledWindows
|
||||
} else if cfg!(unix) {
|
||||
Error::NoPythonInstalledUnix
|
||||
} else {
|
||||
unreachable!("Only Unix and Windows are supported")
|
||||
})
|
||||
.inspect(warn_on_unsupported_python)
|
||||
}
|
||||
|
||||
/// Same as [`find_default_python`] but returns `None` if no python is found instead of returning an `Err`.
|
||||
|
@ -412,6 +423,16 @@ impl PythonVersionSelector {
|
|||
}
|
||||
}
|
||||
|
||||
fn warn_on_unsupported_python(interpreter: &Interpreter) {
|
||||
// Warn on usage with an unsupported Python version
|
||||
if interpreter.python_tuple() < (3, 8) {
|
||||
warn_user_once!(
|
||||
"uv is only compatible with Python 3.8+, found Python {}.",
|
||||
interpreter.python_version()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a matching Python or any fallback Python.
|
||||
///
|
||||
/// If no Python version is provided, we will use the first available interpreter.
|
||||
|
@ -439,6 +460,7 @@ pub fn find_best_python(
|
|||
|
||||
// First, check for an exact match (or the first available version if no Python version was provided)
|
||||
if let Some(interpreter) = find_version(python_version, system, cache)? {
|
||||
warn_on_unsupported_python(&interpreter);
|
||||
return Ok(interpreter);
|
||||
}
|
||||
|
||||
|
@ -449,6 +471,7 @@ pub fn find_best_python(
|
|||
if let Some(interpreter) =
|
||||
find_version(Some(&python_version.without_patch()), system, cache)?
|
||||
{
|
||||
warn_on_unsupported_python(&interpreter);
|
||||
return Ok(interpreter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -913,6 +913,7 @@ fn compile_python_37() -> Result<()> {
|
|||
"warning: The requested Python version 3.7 is not available; .* will be used to build dependencies instead.\n",
|
||||
"",
|
||||
),
|
||||
(r"warning: uv is only compatible with Python 3\.8\+, found Python 3\.7.*\n", "")
|
||||
]
|
||||
.into_iter()
|
||||
.chain(context.filters())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue