Skip to content
Closed
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
61 changes: 41 additions & 20 deletions crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,11 @@ pub(crate) async fn pip_compile(
install_mirrors.python_downloads_json_url.as_deref(),
)
.await?;
let interpreter = if let Some(python) = python.as_ref() {

let (installation, python_missing_download) = if let Some(python) = python.as_ref() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why python_missing_download is an Option instead of a bool is to avoid needing to check a bool and let Some(python) = python.as_ref() a second time.

The reason why this exists at all is to detect the case when the attempt to download failed in the first place, I couldn't find some way of testing if an interpreter satisfied a specific version. If there is a way to do that, let me know, then this code can simplified.

let request = PythonRequest::parse(python);
let reporter = PythonDownloadReporter::single(printer);
PythonInstallation::find_or_download(
match PythonInstallation::find_or_download(
Some(&request),
environment_preference,
python_preference,
Expand All @@ -320,32 +321,52 @@ pub(crate) async fn pip_compile(
preview,
)
.await
{
Ok(interpreter) => (Some(Ok(interpreter)), None),
Err(uv_python::Error::MissingPython(..)) => (None, Some(python)),
Err(uv_python::Error::Discovery(err)) if !err.is_critical() => (None, Some(python)),
Comment on lines +326 to +327
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are taken from find_or_download. Maybe this is an argument for some kind of predicate function for uv_python::Error so this case can be tested in one place?

err => (Some(err), None),
}
} else {
// TODO(zanieb): The split here hints at a problem with the request abstraction; we should
// be able to use `PythonInstallation::find(...)` here.
let request = if let Some(version) = python_version.as_ref() {
// TODO(zanieb): We should consolidate `VersionRequest` and `PythonVersion`
PythonRequest::Version(VersionRequest::from(version))
} else {
PythonRequest::default()
};
PythonInstallation::find_best(
&request,
environment_preference,
python_preference,
&download_list,
&cache,
preview,
)
}?
.into_interpreter();
(None, None)
};
let interpreter = installation
.unwrap_or_else(|| {
// TODO(zanieb): The split here hints at a problem with the request abstraction; we should
// be able to use `PythonInstallation::find(...)` here.
let request = if let Some(version) = python.as_ref() {
PythonRequest::parse(version)
} else if let Some(version) = python_version.as_ref() {
// TODO(zanieb): We should consolidate `VersionRequest` and `PythonVersion`
PythonRequest::Version(VersionRequest::from(version))
} else {
PythonRequest::default()
};
PythonInstallation::find_best(
&request,
environment_preference,
python_preference,
&download_list,
&cache,
preview,
)
})?
.into_interpreter();

debug!(
"Using Python {} interpreter at {} for builds",
interpreter.python_version(),
interpreter.sys_executable().user_display().cyan()
);

if let Some(python_missing_download) = python_missing_download {
warn_user!(
"The requested Python version {} was not found and could not be downloaded; {} will be used to build dependencies instead.",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be is not available and could not be downloaded or it could just be is not available like the other message?

python_missing_download,
interpreter.python_version(),
);
}

Comment on lines +362 to +369
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an argument to be made here that this should print the original error too... Let me know.

if let Some(python_version) = python_version.as_ref() {
// If the requested version does not match the version we're using warn the user
// _unless_ they have not specified a patch version and that is the only difference
Expand Down
100 changes: 80 additions & 20 deletions crates/uv/tests/it/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1557,14 +1557,31 @@ fn compile_fallback_interpreter() -> Result<()> {
.arg("requirements.in")
.arg("-p")
.arg("pypy"), @r"
success: false
exit_code: 2
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in -p pypy
black==23.10.[X]
# via -r requirements.in
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black
tomli==2.0.1
# via black
typing-extensions==4.10.0
# via black

----- stderr -----
error: No interpreter found for PyPy in [PYTHON SOURCES]

hint: A managed Python download is available for PyPy, but Python downloads are set to 'never'
warning: The requested Python version pypy was not found and could not be downloaded; 3.10.[X] will be used to build dependencies instead.
Resolved 8 packages in [TIME]
"
);

Expand All @@ -1573,14 +1590,31 @@ fn compile_fallback_interpreter() -> Result<()> {
.arg("requirements.in")
.arg("-p")
.arg(">=3.12"), @r"
success: false
exit_code: 2
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in -p >=3.12
black==23.10.[X]
# via -r requirements.in
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black
tomli==2.0.1
# via black
typing-extensions==4.10.0
# via black

----- stderr -----
error: No interpreter found for Python >=3.12 in [PYTHON SOURCES]

hint: A managed Python download is available for Python >=3.12, but Python downloads are set to 'never'
warning: The requested Python version >=3.12 was not found and could not be downloaded; 3.10.[X] will be used to build dependencies instead.
Resolved 8 packages in [TIME]
"
);

Expand Down Expand Up @@ -1779,14 +1813,27 @@ fn compile_python_build_version_different_than_target() -> Result<()> {
.arg("-p")
.arg("pypy@3.11")
.env_remove(EnvVars::VIRTUAL_ENV), @r"
success: false
exit_code: 2
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --python-version 3.12 -p pypy@3.11
black==23.10.[X]
# via -r requirements.in
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black

----- stderr -----
error: No interpreter found for PyPy 3.11 in [PYTHON SOURCES]

hint: A managed Python download is available for PyPy 3.11, but Python downloads are set to 'never'
warning: The requested Python version pypy@3.11 was not found and could not be downloaded; 3.12.[X] will be used to build dependencies instead.
Resolved 6 packages in [TIME]
"
);

Expand All @@ -1797,14 +1844,27 @@ fn compile_python_build_version_different_than_target() -> Result<()> {
.arg("-p")
.arg("3.13")
.env_remove(EnvVars::VIRTUAL_ENV), @r"
success: false
exit_code: 2
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --python-version 3.12 -p 3.13
black==23.10.[X]
# via -r requirements.in
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black

----- stderr -----
error: No interpreter found for Python 3.13 in [PYTHON SOURCES]

hint: A managed Python download is available for Python 3.13, but Python downloads are set to 'never'
warning: The requested Python version 3.13 was not found and could not be downloaded; 3.12.[X] will be used to build dependencies instead.
Resolved 6 packages in [TIME]
"
);

Expand Down
Loading