mirror of https://github.com/astral-sh/uv
Use comparable representation for `PackageId` (#1543)
## Summary By using the display representation of `Version` to form a `PackageId`, we run the risk (as seen in the linked issue) of thinking that versions like `2021.1` and `2021.1.0` are not equivalent. Closes https://github.com/astral-sh/uv/issues/1536
This commit is contained in:
parent
7c08e61b73
commit
b4ea48955b
|
|
@ -1,18 +1,35 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use url::Url;
|
||||
|
||||
use pep440_rs::Version;
|
||||
use uv_normalize::PackageName;
|
||||
|
||||
/// A unique identifier for a package (e.g., `black==23.10.0`).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct PackageId(String);
|
||||
pub enum PackageId {
|
||||
NameVersion(PackageName, Version),
|
||||
Url(String),
|
||||
}
|
||||
|
||||
impl PackageId {
|
||||
pub fn new(id: impl Into<String>) -> Self {
|
||||
Self(id.into())
|
||||
/// Create a new [`PackageId`] from a package name and version.
|
||||
pub fn from_registry(name: PackageName, version: Version) -> Self {
|
||||
Self::NameVersion(name, version)
|
||||
}
|
||||
|
||||
/// Create a new [`PackageId`] from a URL.
|
||||
pub fn from_url(url: &Url) -> Self {
|
||||
Self::Url(cache_key::digest(&cache_key::CanonicalUrl::new(url)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PackageId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
match self {
|
||||
PackageId::NameVersion(name, version) => write!(f, "{name}-{version}"),
|
||||
PackageId::Url(url) => write!(f, "{url}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,14 +31,12 @@ pub trait DistributionMetadata: Name {
|
|||
/// registry-based distributions (e.g., different wheels for the same package and version)
|
||||
/// will return the same package ID, but different distribution IDs.
|
||||
fn package_id(&self) -> PackageId {
|
||||
PackageId::new(match self.version_or_url() {
|
||||
match self.version_or_url() {
|
||||
VersionOrUrl::Version(version) => {
|
||||
// https://packaging.python.org/en/latest/specifications/recording-installed-packages/#the-dist-info-directory
|
||||
// `version` is normalized by its `ToString` impl
|
||||
format!("{}-{}", self.name(), version)
|
||||
PackageId::from_registry(self.name().clone(), version.clone())
|
||||
}
|
||||
VersionOrUrl::Url(url) => cache_key::digest(&cache_key::CanonicalUrl::new(url)),
|
||||
})
|
||||
VersionOrUrl::Url(url) => PackageId::from_url(url),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3376,3 +3376,31 @@ fn compile_none_extra() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve a package (`pytz`) with a preference that omits a trailing zero.
|
||||
///
|
||||
/// See: <https://github.com/astral-sh/uv/issues/1536>
|
||||
#[test]
|
||||
fn compile_types_pytz() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let requirements_in = context.temp_dir.child("requirements.in");
|
||||
requirements_in.write_str("types-pytz")?;
|
||||
|
||||
let requirements_txt = context.temp_dir.child("requirements.txt");
|
||||
requirements_txt.write_str("types-pytz==2021.1")?;
|
||||
|
||||
uv_snapshot!(context
|
||||
.compile()
|
||||
.arg("requirements.in")
|
||||
.arg("-o")
|
||||
.arg("requirements.txt"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue