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-cache",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-toolchain",
|
"uv-toolchain",
|
||||||
|
"uv-warnings",
|
||||||
"which",
|
"which",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,6 +22,7 @@ pypi-types = { workspace = true }
|
||||||
uv-cache = { workspace = true }
|
uv-cache = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-toolchain = { workspace = true }
|
||||||
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
configparser = { workspace = true }
|
configparser = { workspace = true }
|
||||||
fs-err = { workspace = true, features = ["tokio"] }
|
fs-err = { workspace = true, features = ["tokio"] }
|
||||||
|
|
|
@ -7,6 +7,7 @@ use tracing::{debug, instrument};
|
||||||
|
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_toolchain::PythonVersion;
|
use uv_toolchain::PythonVersion;
|
||||||
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::interpreter::InterpreterInfoError;
|
use crate::interpreter::InterpreterInfoError;
|
||||||
use crate::python_environment::{detect_python_executable, detect_virtual_env};
|
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
|
// SAFETY: Guaranteed by the Ok(versions) guard
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
find_python(selector, cache)
|
let interpreter = find_python(selector, cache)?;
|
||||||
|
interpreter
|
||||||
|
.as_ref()
|
||||||
|
.inspect(|inner| warn_on_unsupported_python(inner));
|
||||||
|
Ok(interpreter)
|
||||||
} else {
|
} else {
|
||||||
match fs_err::metadata(request) {
|
match fs_err::metadata(request) {
|
||||||
Ok(metadata) => {
|
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`
|
// `-p /home/ferris/.local/bin/python3.10`
|
||||||
path
|
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 => {
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
// `-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) = find_executable(request)? else {
|
let Some(executable) = find_executable(request)? else {
|
||||||
return Ok(None);
|
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()),
|
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)]
|
#[instrument(skip_all)]
|
||||||
pub fn find_default_python(cache: &Cache) -> Result<Interpreter, Error> {
|
pub fn find_default_python(cache: &Cache) -> Result<Interpreter, Error> {
|
||||||
debug!("Starting interpreter discovery for default Python");
|
debug!("Starting interpreter discovery for default Python");
|
||||||
try_find_default_python(cache)?.ok_or(if cfg!(windows) {
|
try_find_default_python(cache)?
|
||||||
Error::NoPythonInstalledWindows
|
.ok_or(if cfg!(windows) {
|
||||||
} else if cfg!(unix) {
|
Error::NoPythonInstalledWindows
|
||||||
Error::NoPythonInstalledUnix
|
} else if cfg!(unix) {
|
||||||
} else {
|
Error::NoPythonInstalledUnix
|
||||||
unreachable!("Only Unix and Windows are supported")
|
} 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`.
|
/// 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.
|
/// Find a matching Python or any fallback Python.
|
||||||
///
|
///
|
||||||
/// If no Python version is provided, we will use the first available interpreter.
|
/// 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)
|
// 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)? {
|
if let Some(interpreter) = find_version(python_version, system, cache)? {
|
||||||
|
warn_on_unsupported_python(&interpreter);
|
||||||
return Ok(interpreter);
|
return Ok(interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +471,7 @@ pub fn find_best_python(
|
||||||
if let Some(interpreter) =
|
if let Some(interpreter) =
|
||||||
find_version(Some(&python_version.without_patch()), system, cache)?
|
find_version(Some(&python_version.without_patch()), system, cache)?
|
||||||
{
|
{
|
||||||
|
warn_on_unsupported_python(&interpreter);
|
||||||
return Ok(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",
|
"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()
|
.into_iter()
|
||||||
.chain(context.filters())
|
.chain(context.filters())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue