mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 10:58:28 +00:00
Make missing METADATA
file a recoverable error (#4247)
## Summary I don't have a great way to test it, but this makes the error described in https://github.com/astral-sh/uv/issues/4246 an incompatibility rather than a fatal error. Closes https://github.com/astral-sh/uv/issues/4246.
This commit is contained in:
parent
8cfe202e4e
commit
6dae1920af
7 changed files with 67 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4544,7 +4544,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sys-info",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tl",
|
||||
"tokio",
|
||||
|
|
|
@ -38,7 +38,6 @@ rmp-serde = { workspace = true }
|
|||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sys-info = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tl = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
|
|
|
@ -162,10 +162,6 @@ pub enum ErrorKind {
|
|||
#[error("Metadata file `{0}` was not found in {1}")]
|
||||
MetadataNotFound(WheelFilename, String),
|
||||
|
||||
/// The metadata file was not found in the registry.
|
||||
#[error("File `{0}` was not found in the registry at {1}.")]
|
||||
FileNotFound(String, #[source] BetterReqwestError),
|
||||
|
||||
/// A generic request error happened while making a request. Refer to the
|
||||
/// error message for more details.
|
||||
#[error(transparent)]
|
||||
|
@ -185,9 +181,6 @@ pub enum ErrorKind {
|
|||
#[error(transparent)]
|
||||
AsyncHttpRangeReader(#[from] AsyncHttpRangeReaderError),
|
||||
|
||||
#[error("Expected a single .dist-info directory in {0}, found {1}")]
|
||||
InvalidDistInfo(WheelFilename, String),
|
||||
|
||||
#[error("{0} is not a valid wheel filename")]
|
||||
WheelFilename(#[source] WheelFilenameError),
|
||||
|
||||
|
@ -212,10 +205,6 @@ pub enum ErrorKind {
|
|||
#[error("Cache serialization failed")]
|
||||
Encode(#[source] rmp_serde::encode::Error),
|
||||
|
||||
/// An [`io::Error`] with a filename attached
|
||||
#[error(transparent)]
|
||||
Persist(#[from] tempfile::PersistError),
|
||||
|
||||
#[error("Missing `Content-Type` header for {0}")]
|
||||
MissingContentType(Url),
|
||||
|
||||
|
|
|
@ -476,6 +476,11 @@ impl PubGrubReportFormatter<'_> {
|
|||
Some(UnavailablePackage::Offline) => {
|
||||
hints.insert(PubGrubHint::Offline);
|
||||
}
|
||||
Some(UnavailablePackage::MissingMetadata) => {
|
||||
hints.insert(PubGrubHint::MissingPackageMetadata {
|
||||
package: package.clone(),
|
||||
});
|
||||
}
|
||||
Some(UnavailablePackage::InvalidMetadata(reason)) => {
|
||||
hints.insert(PubGrubHint::InvalidPackageMetadata {
|
||||
package: package.clone(),
|
||||
|
@ -500,6 +505,12 @@ impl PubGrubReportFormatter<'_> {
|
|||
IncompletePackage::Offline => {
|
||||
hints.insert(PubGrubHint::Offline);
|
||||
}
|
||||
IncompletePackage::MissingMetadata => {
|
||||
hints.insert(PubGrubHint::MissingVersionMetadata {
|
||||
package: package.clone(),
|
||||
version: version.clone(),
|
||||
});
|
||||
}
|
||||
IncompletePackage::InvalidMetadata(reason) => {
|
||||
hints.insert(PubGrubHint::InvalidVersionMetadata {
|
||||
package: package.clone(),
|
||||
|
@ -601,6 +612,8 @@ pub(crate) enum PubGrubHint {
|
|||
NoIndex,
|
||||
/// A package was not found in the registry, but network access was disabled.
|
||||
Offline,
|
||||
/// Metadata for a package could not be found.
|
||||
MissingPackageMetadata { package: PubGrubPackage },
|
||||
/// Metadata for a package could not be parsed.
|
||||
InvalidPackageMetadata {
|
||||
package: PubGrubPackage,
|
||||
|
@ -613,6 +626,12 @@ pub(crate) enum PubGrubHint {
|
|||
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
||||
reason: String,
|
||||
},
|
||||
/// Metadata for a package version could not be found.
|
||||
MissingVersionMetadata {
|
||||
package: PubGrubPackage,
|
||||
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
||||
version: Version,
|
||||
},
|
||||
/// Metadata for a package version could not be parsed.
|
||||
InvalidVersionMetadata {
|
||||
package: PubGrubPackage,
|
||||
|
@ -689,6 +708,15 @@ impl std::fmt::Display for PubGrubHint {
|
|||
":".bold(),
|
||||
)
|
||||
}
|
||||
Self::MissingPackageMetadata { package } => {
|
||||
write!(
|
||||
f,
|
||||
"{}{} Metadata for {} could not be found, as the wheel is missing a `METADATA` file",
|
||||
"hint".bold().cyan(),
|
||||
":".bold(),
|
||||
package.bold()
|
||||
)
|
||||
}
|
||||
Self::InvalidPackageMetadata { package, reason } => {
|
||||
write!(
|
||||
f,
|
||||
|
@ -709,6 +737,16 @@ impl std::fmt::Display for PubGrubHint {
|
|||
textwrap::indent(reason, " ")
|
||||
)
|
||||
}
|
||||
Self::MissingVersionMetadata { package, version } => {
|
||||
write!(
|
||||
f,
|
||||
"{}{} Metadata for {}=={} could not be found, as the wheel is missing a `METADATA` file",
|
||||
"hint".bold().cyan(),
|
||||
":".bold(),
|
||||
package.bold(),
|
||||
version.bold(),
|
||||
)
|
||||
}
|
||||
Self::InvalidVersionMetadata {
|
||||
package,
|
||||
version,
|
||||
|
|
|
@ -30,6 +30,8 @@ impl Display for UnavailableReason {
|
|||
pub(crate) enum UnavailableVersion {
|
||||
/// Version is incompatible because it has no usable distributions
|
||||
IncompatibleDist(IncompatibleDist),
|
||||
/// The wheel metadata was not found.
|
||||
MissingMetadata,
|
||||
/// The wheel metadata was found, but could not be parsed.
|
||||
InvalidMetadata,
|
||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
||||
|
@ -46,6 +48,9 @@ impl Display for UnavailableVersion {
|
|||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
UnavailableVersion::IncompatibleDist(invalid_dist) => Display::fmt(invalid_dist, f),
|
||||
UnavailableVersion::MissingMetadata => {
|
||||
f.write_str("does not include a `METADATA` file")
|
||||
}
|
||||
UnavailableVersion::InvalidMetadata => f.write_str("has invalid metadata"),
|
||||
UnavailableVersion::InconsistentMetadata => f.write_str("has inconsistent metadata"),
|
||||
UnavailableVersion::InvalidStructure => f.write_str("has an invalid package format"),
|
||||
|
@ -66,6 +71,8 @@ pub(crate) enum UnavailablePackage {
|
|||
Offline,
|
||||
/// The package was not found in the registry.
|
||||
NotFound,
|
||||
/// The package metadata was not found.
|
||||
MissingMetadata,
|
||||
/// The package metadata was found, but could not be parsed.
|
||||
InvalidMetadata(String),
|
||||
/// The package has an invalid structure.
|
||||
|
@ -78,6 +85,7 @@ impl UnavailablePackage {
|
|||
UnavailablePackage::NoIndex => "was not found in the provided package locations",
|
||||
UnavailablePackage::Offline => "was not found in the cache",
|
||||
UnavailablePackage::NotFound => "was not found in the package registry",
|
||||
UnavailablePackage::MissingMetadata => "does not include a `METADATA` file",
|
||||
UnavailablePackage::InvalidMetadata(_) => "has invalid metadata",
|
||||
UnavailablePackage::InvalidStructure(_) => "has an invalid package format",
|
||||
}
|
||||
|
@ -95,6 +103,8 @@ impl Display for UnavailablePackage {
|
|||
pub(crate) enum IncompletePackage {
|
||||
/// Network requests were disabled (i.e., `--offline`), and the wheel metadata was not found in the cache.
|
||||
Offline,
|
||||
/// The wheel metadata was not found.
|
||||
MissingMetadata,
|
||||
/// The wheel metadata was found, but could not be parsed.
|
||||
InvalidMetadata(String),
|
||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
||||
|
|
|
@ -749,6 +749,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
.insert(name.clone(), UnavailablePackage::Offline);
|
||||
return Ok(None);
|
||||
}
|
||||
MetadataResponse::MissingMetadata => {
|
||||
self.unavailable_packages
|
||||
.insert(name.clone(), UnavailablePackage::MissingMetadata);
|
||||
return Ok(None);
|
||||
}
|
||||
MetadataResponse::InvalidMetadata(err) => {
|
||||
self.unavailable_packages.insert(
|
||||
name.clone(),
|
||||
|
@ -1042,6 +1047,15 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
.insert(version.clone(), IncompletePackage::Offline);
|
||||
return Ok(Dependencies::Unavailable(UnavailableVersion::Offline));
|
||||
}
|
||||
MetadataResponse::MissingMetadata => {
|
||||
self.incomplete_packages
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.insert(version.clone(), IncompletePackage::MissingMetadata);
|
||||
return Ok(Dependencies::Unavailable(
|
||||
UnavailableVersion::MissingMetadata,
|
||||
));
|
||||
}
|
||||
MetadataResponse::InvalidMetadata(err) => {
|
||||
warn!("Unable to extract metadata for {name}: {err}");
|
||||
self.incomplete_packages
|
||||
|
|
|
@ -33,6 +33,8 @@ pub enum VersionsResponse {
|
|||
pub enum MetadataResponse {
|
||||
/// The wheel metadata was found and parsed successfully.
|
||||
Found(ArchiveMetadata),
|
||||
/// The wheel metadata was not found.
|
||||
MissingMetadata,
|
||||
/// The wheel metadata was found, but could not be parsed.
|
||||
InvalidMetadata(Box<pypi_types::MetadataError>),
|
||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
||||
|
@ -184,6 +186,9 @@ impl<'a, Context: BuildContext> ResolverProvider for DefaultResolverProvider<'a,
|
|||
Err(err) => match err {
|
||||
uv_distribution::Error::Client(client) => match client.into_kind() {
|
||||
uv_client::ErrorKind::Offline(_) => Ok(MetadataResponse::Offline),
|
||||
uv_client::ErrorKind::MetadataNotFound(_, _) => {
|
||||
Ok(MetadataResponse::MissingMetadata)
|
||||
}
|
||||
uv_client::ErrorKind::MetadataParseError(_, _, err) => {
|
||||
Ok(MetadataResponse::InvalidMetadata(err))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue