Skip to content

Commit

Permalink
Warn when an unsupported Python version is encountered (#3250)
Browse files Browse the repository at this point in the history
I rebased #2757 then realized that
we want to implement this for more than `uv venv`.

Closes #2587
Closes #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>
  • Loading branch information
zanieb and stegayet authored Apr 24, 2024
1 parent 20e9589 commit c22e15f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/uv-interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
43 changes: 33 additions & 10 deletions crates/uv-interpreter/src/find_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) => {
Expand All @@ -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()),
}
Expand All @@ -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) {
Error::NoPythonInstalledWindows
} else if cfg!(unix) {
Error::NoPythonInstalledUnix
} else {
unreachable!("Only Unix and Windows are supported")
})
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`.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down

0 comments on commit c22e15f

Please sign in to comment.