Skip to content

Commit 93c171c

Browse files
committed
Do not re-resolve with a new Python version in uv tool if it is incompatible with --python
1 parent 9efd053 commit 93c171c

2 files changed

Lines changed: 31 additions & 11 deletions

File tree

crates/uv/src/commands/tool/common.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,6 @@ pub(crate) async fn refine_interpreter(
9898
return Ok(None);
9999
}
100100

101-
// If the user passed a `--python` request, and the refined interpreter is incompatible, we
102-
// can't use it.
103-
if let Some(python_request) = python_request {
104-
if !python_request.satisfied(interpreter, cache) {
105-
return Ok(None);
106-
}
107-
}
108-
109101
// We want an interpreter that's as close to the required version as possible. If we choose the
110102
// "latest" Python, we risk choosing a version that lacks wheels for the tool's requirements
111103
// (assuming those requirements don't publish source distributions).
@@ -135,15 +127,15 @@ pub(crate) async fn refine_interpreter(
135127
Bound::Unbounded => unreachable!("`requires-python` should never be unbounded"),
136128
};
137129

138-
let python_request = PythonRequest::Version(VersionRequest::Range(
130+
let requires_python_request = PythonRequest::Version(VersionRequest::Range(
139131
VersionSpecifiers::from_iter([lower_bound, upper_bound]),
140132
PythonVariant::default(),
141133
));
142134

143-
debug!("Refining interpreter with: {python_request}");
135+
debug!("Refining interpreter with: {requires_python_request}");
144136

145137
let interpreter = PythonInstallation::find_or_download(
146-
Some(&python_request),
138+
Some(&requires_python_request),
147139
EnvironmentPreference::OnlySystem,
148140
python_preference,
149141
python_downloads,
@@ -158,6 +150,14 @@ pub(crate) async fn refine_interpreter(
158150
.await?
159151
.into_interpreter();
160152

153+
// If the user passed a `--python` request, and the refined interpreter is incompatible, we
154+
// can't use it.
155+
if let Some(python_request) = python_request {
156+
if !python_request.satisfied(&interpreter, cache) {
157+
return Ok(None);
158+
}
159+
}
160+
161161
Ok(Some(interpreter))
162162
}
163163

crates/uv/tests/it/tool_run.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,7 @@ fn tool_run_reresolve_python() -> anyhow::Result<()> {
30263026
+ foo==1.0.0 (from file://[TEMP_DIR]/foo)
30273027
");
30283028

3029+
// When an incompatible Python version is explicitly requested, we should not re-resolve
30293030
uv_snapshot!(context.filters(), context.tool_run()
30303031
.arg("--from")
30313032
.arg("./foo")
@@ -3034,6 +3035,25 @@ fn tool_run_reresolve_python() -> anyhow::Result<()> {
30343035
.arg("foo")
30353036
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
30363037
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
3038+
success: false
3039+
exit_code: 1
3040+
----- stdout -----
3041+
3042+
----- stderr -----
3043+
× No solution found when resolving tool dependencies:
3044+
╰─▶ Because the current Python version (3.11.[X]) does not satisfy Python>=3.12 and foo==1.0.0 depends on Python>=3.12, we can conclude that foo==1.0.0 cannot be used.
3045+
And because only foo==1.0.0 is available and you require foo, we can conclude that your requirements are unsatisfiable.
3046+
");
3047+
3048+
// Unless the discovered interpreter is compatible with the request
3049+
uv_snapshot!(context.filters(), context.tool_run()
3050+
.arg("--from")
3051+
.arg("./foo")
3052+
.arg("--python")
3053+
.arg(">=3.11")
3054+
.arg("foo")
3055+
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
3056+
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
30373057
success: true
30383058
exit_code: 0
30393059
----- stdout -----

0 commit comments

Comments
 (0)