Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::sync::Arc;

use itertools::Itertools;
use owo_colors::OwoColorize;
use tracing::{debug, warn};
use tracing::{debug, trace, warn};

use uv_auth::UrlAuthPolicies;
use uv_cache::{Cache, CacheBucket};
Expand Down Expand Up @@ -766,6 +766,43 @@ impl ScriptInterpreter {
}
}

/// Whether an environment is usable for the project, i.e., if it matches the requirements.
fn environment_is_usable(
environment: &PythonEnvironment,
python_request: Option<&PythonRequest>,
requires_python: Option<&RequiresPython>,
cache: &Cache,
) -> bool {
if !environment.matches_interpreter(environment.interpreter()) {
debug!("The virtual environment's interpreter version does not match the version it was created from.");
return false;
}

if let Some(request) = python_request {
if request.satisfied(environment.interpreter(), cache) {
debug!("The virtual environment's Python version satisfies the request: `{request}`");
} else {
debug!("The virtual environment's Python version does not satisfy the request: `{request}`");
return false;
}
}

if let Some(requires_python) = requires_python.as_ref() {
if requires_python.contains(environment.interpreter().python_version()) {
trace!(
"The virtual environment's Python version meets the Python requirement: `{requires_python}`"
);
} else {
debug!(
"The virtual environment's Python version does not meet the Python requirement: `{requires_python}`"
);
return false;
}
}

true
}

/// An interpreter suitable for the project.
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -803,37 +840,13 @@ impl ProjectInterpreter {
let venv = workspace.venv(active);
match PythonEnvironment::from_root(&venv, cache) {
Ok(venv) => {
let venv_matches_interpreter = venv.matches_interpreter(venv.interpreter());
if !venv_matches_interpreter {
debug!("The virtual environment's interpreter version does not match the version it was created from.");
}
if venv_matches_interpreter
&& python_request.as_ref().is_none_or(|request| {
if request.satisfied(venv.interpreter(), cache) {
debug!(
"The virtual environment's Python version satisfies `{}`",
request.to_canonical_string()
);
true
} else {
debug!(
"The virtual environment's Python version does not satisfy `{}`",
request.to_canonical_string()
);
false
}
})
{
if let Some(requires_python) = requires_python.as_ref() {
if requires_python.contains(venv.interpreter().python_version()) {
return Ok(Self::Environment(venv));
}
debug!(
"The virtual environment's Python version does not meet the project's Python requirement: `{requires_python}`"
);
} else {
return Ok(Self::Environment(venv));
}
if environment_is_usable(
&venv,
python_request.as_ref(),
requires_python.as_ref(),
cache,
) {
return Ok(Self::Environment(venv));
}
}
Err(uv_python::Error::MissingEnvironment(_)) => {}
Expand Down
2 changes: 1 addition & 1 deletion crates/uv/tests/it/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15748,7 +15748,7 @@ fn lock_explicit_default_index() -> Result<()> {
DEBUG No Python version file found in workspace: [TEMP_DIR]/
DEBUG Using Python request `>=3.12` from `requires-python` metadata
DEBUG Checking for Python environment at `.venv`
DEBUG The virtual environment's Python version satisfies `>=3.12`
DEBUG The virtual environment's Python version satisfies the request: `Python >=3.12`
DEBUG Using request timeout of [TIME]
DEBUG Found static `pyproject.toml` for: project @ file://[TEMP_DIR]/
DEBUG No workspace root found, using project root
Expand Down
Loading