Skip to content

Commit

Permalink
Fix uv python pin 3.13t failure when parsing version for project re…
Browse files Browse the repository at this point in the history
…quires check (astral-sh#8056)

Closes astral-sh#7964

We can probably do some restructuring to avoid unwrapping here in the
future, but this just fixes the bug quick.
  • Loading branch information
zanieb authored Oct 10, 2024
1 parent 46a0ed7 commit 8270894
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
23 changes: 23 additions & 0 deletions crates/uv-python/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,29 @@ impl VersionRequest {
| Self::Range(_, variant) => variant == &PythonVariant::Freethreaded,
}
}

/// Return a new [`VersionRequest`] with the [`PythonVariant`] if it has one.
///
/// This is useful for converting the string representation to pep440.
#[must_use]
pub fn without_python_variant(self) -> Self {
// TODO(zanieb): Replace this entire function with a utility that casts this to a version
// without using `VersionRequest::to_string`.
match self {
Self::Any | Self::Default => self,
Self::Major(major, _) => Self::Major(major, PythonVariant::Default),
Self::MajorMinor(major, minor, _) => {
Self::MajorMinor(major, minor, PythonVariant::Default)
}
Self::MajorMinorPatch(major, minor, patch, _) => {
Self::MajorMinorPatch(major, minor, patch, PythonVariant::Default)
}
Self::MajorMinorPrerelease(major, minor, prerelease, _) => {
Self::MajorMinorPrerelease(major, minor, prerelease, PythonVariant::Default)
}
Self::Range(specifiers, _) => Self::Range(specifiers, PythonVariant::Default),
}
}
}

impl FromStr for VersionRequest {
Expand Down
8 changes: 6 additions & 2 deletions crates/uv/src/commands/python/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,12 @@ fn pep440_version_from_request(request: &PythonRequest) -> Option<uv_pep440::Ver
return None;
}

// SAFETY: converting `VersionRequest` to `Version` is guaranteed to succeed if not a `Range`.
Some(uv_pep440::Version::from_str(&version_request.to_string()).unwrap())
// SAFETY: converting `VersionRequest` to `Version` is guaranteed to succeed if not a `Range`
// and does not have a Python variant (e.g., freethreaded) attached.
Some(
uv_pep440::Version::from_str(&version_request.clone().without_python_variant().to_string())
.unwrap(),
)
}

/// Check if pinned request is compatible with the workspace/project's `Requires-Python`.
Expand Down
16 changes: 14 additions & 2 deletions crates/uv/tests/python_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ fn python_pin_no_python() {

#[test]
fn python_pin_compatible_with_requires_python() -> anyhow::Result<()> {
let context: TestContext = TestContext::new_with_versions(&["3.10", "3.11"]);
let context: TestContext =
TestContext::new_with_versions(&["3.10", "3.11"]).with_filtered_python_sources();
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
Expand Down Expand Up @@ -294,12 +295,23 @@ fn python_pin_compatible_with_requires_python() -> anyhow::Result<()> {
----- stderr -----
"###);

// Request a version that is compatible and uses a Python variant
uv_snapshot!(context.filters(), context.python_pin().arg("3.13t"), @r###"
success: true
exit_code: 0
----- stdout -----
Updated `.python-version` from `3.11` -> `3.13t`
----- stderr -----
warning: No interpreter found for Python 3.13t in [PYTHON SOURCES]
"###);

// Request a implementation version that is compatible
uv_snapshot!(context.filters(), context.python_pin().arg("cpython@3.11"), @r###"
success: true
exit_code: 0
----- stdout -----
Updated `.python-version` from `3.11` -> `cpython@3.11`
Updated `.python-version` from `3.13t` -> `cpython@3.11`
----- stderr -----
"###);
Expand Down

0 comments on commit 8270894

Please sign in to comment.