Skip to content

Commit

Permalink
Use an enum to differentiate between resolved and requested python
Browse files Browse the repository at this point in the history
  • Loading branch information
blueraft committed Jul 16, 2024
1 parent cf551f2 commit a377c35
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 16 deletions.
56 changes: 42 additions & 14 deletions crates/uv/src/commands/python/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,18 @@ pub(crate) async fn pin(
// Error if the request is incompatible with the Python requirement
if let PythonRequest::Version(version) = &request {
if let Ok(python_version) = pep440_rs::Version::from_str(&version.to_string()) {
assert_python_compatibility(&python_version, virtual_project)?;
assert_python_compatibility(
&PythonVersionCompatibility::Requested(&python_version),
virtual_project,
)?;
}
} else {
if let Some(python) = &python {
// Warn if the resolved Python is incompatible with the Python requirement unless --resolved is used
if let Err(err) =
assert_python_compatibility(python.python_version(), virtual_project)
{
if let Err(err) = assert_python_compatibility(
&PythonVersionCompatibility::Resolved(python.python_version()),
virtual_project,
) {
if resolved {
return Err(err);
};
Expand Down Expand Up @@ -143,7 +147,10 @@ fn check_request_requires_python_compatibility(
if !matches!(request_version, uv_python::VersionRequest::Range(_)) {
// SAFETY: converting `VersionRequest` to `Version` is guaranteed to succeed
let version = pep440_rs::Version::from_str(&request_version.to_string()).unwrap();
if let Err(err) = assert_python_compatibility(&version, virtual_project) {
if let Err(err) = assert_python_compatibility(
&PythonVersionCompatibility::Requested(&version),
virtual_project,
) {
warn_user_once!("{}", err);
return;
}
Expand All @@ -163,7 +170,10 @@ fn check_request_requires_python_compatibility(
"The pinned Python version {} resolves to {}",
pin, python_version
);
if let Err(err) = assert_python_compatibility(python_version, virtual_project) {
if let Err(err) = assert_python_compatibility(
&PythonVersionCompatibility::Resolved(python_version),
virtual_project,
) {
warn_user_once!("{}", err);
}
}
Expand All @@ -177,9 +187,13 @@ fn check_request_requires_python_compatibility(
}
}

enum PythonVersionCompatibility<'a> {
Requested(&'a pep440_rs::Version),
Resolved(&'a pep440_rs::Version),
}
/// Checks if the pinned Python version is compatible with the workspace/project's `Requires-Python`.
fn assert_python_compatibility(
python_version: &pep440_rs::Version,
python_version: &PythonVersionCompatibility,
virtual_project: &VirtualProject,
) -> Result<()> {
let (requires_python, project_type) = match virtual_project {
Expand All @@ -203,13 +217,27 @@ fn assert_python_compatibility(
};

if let Some(requires_python) = requires_python {
if !requires_python.contains(python_version) {
anyhow::bail!(
"The pinned Python version {} is incompatible with the {}'s `Requires-Python` of {}.",
python_version,
project_type,
requires_python
);
match python_version {
PythonVersionCompatibility::Resolved(resolved_version) => {
if !requires_python.contains(resolved_version) {
anyhow::bail!(
"The pinned resolved Python version `{}` is incompatible with the {}'s `Requires-Python` of `{}`.",
resolved_version,
project_type,
requires_python
);
}
}
PythonVersionCompatibility::Requested(requested_version) => {
if !requires_python.contains(requested_version) {
anyhow::bail!(
"The pinned requested Python version `{}` is incompatible with the {}'s `Requires-Python` of `{}`.",
requested_version,
project_type,
requires_python
);
}
}
}
}
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions crates/uv/tests/python_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ fn python_pin_compatible_with_requires_python() -> anyhow::Result<()> {
----- stdout -----
----- stderr -----
error: The pinned Python version 3.10 is incompatible with the project's `Requires-Python` of >=3.11.
error: The pinned requested Python version `3.10` is incompatible with the project's `Requires-Python` of `>=3.11`.
"###);

uv_snapshot!(context.filters(), context.python_pin().arg("3.11"), @r###"
Expand Down Expand Up @@ -290,7 +290,7 @@ fn python_pin_compatible_with_requires_python() -> anyhow::Result<()> {
3.11
----- stderr -----
warning: The pinned Python version 3.11 is incompatible with the project's `Requires-Python` of >=3.12.
warning: The pinned requested Python version `3.11` is incompatible with the project's `Requires-Python` of `>=3.12`.
"###);

Ok(())
Expand Down

0 comments on commit a377c35

Please sign in to comment.