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",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sys-info",
|
"sys-info",
|
||||||
"tempfile",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tl",
|
"tl",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -38,7 +38,6 @@ rmp-serde = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
sys-info = { workspace = true }
|
sys-info = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tl = { workspace = true }
|
tl = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
|
|
@ -162,10 +162,6 @@ pub enum ErrorKind {
|
||||||
#[error("Metadata file `{0}` was not found in {1}")]
|
#[error("Metadata file `{0}` was not found in {1}")]
|
||||||
MetadataNotFound(WheelFilename, String),
|
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
|
/// A generic request error happened while making a request. Refer to the
|
||||||
/// error message for more details.
|
/// error message for more details.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
@ -185,9 +181,6 @@ pub enum ErrorKind {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
AsyncHttpRangeReader(#[from] AsyncHttpRangeReaderError),
|
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")]
|
#[error("{0} is not a valid wheel filename")]
|
||||||
WheelFilename(#[source] WheelFilenameError),
|
WheelFilename(#[source] WheelFilenameError),
|
||||||
|
|
||||||
|
@ -212,10 +205,6 @@ pub enum ErrorKind {
|
||||||
#[error("Cache serialization failed")]
|
#[error("Cache serialization failed")]
|
||||||
Encode(#[source] rmp_serde::encode::Error),
|
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}")]
|
#[error("Missing `Content-Type` header for {0}")]
|
||||||
MissingContentType(Url),
|
MissingContentType(Url),
|
||||||
|
|
||||||
|
|
|
@ -476,6 +476,11 @@ impl PubGrubReportFormatter<'_> {
|
||||||
Some(UnavailablePackage::Offline) => {
|
Some(UnavailablePackage::Offline) => {
|
||||||
hints.insert(PubGrubHint::Offline);
|
hints.insert(PubGrubHint::Offline);
|
||||||
}
|
}
|
||||||
|
Some(UnavailablePackage::MissingMetadata) => {
|
||||||
|
hints.insert(PubGrubHint::MissingPackageMetadata {
|
||||||
|
package: package.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
Some(UnavailablePackage::InvalidMetadata(reason)) => {
|
Some(UnavailablePackage::InvalidMetadata(reason)) => {
|
||||||
hints.insert(PubGrubHint::InvalidPackageMetadata {
|
hints.insert(PubGrubHint::InvalidPackageMetadata {
|
||||||
package: package.clone(),
|
package: package.clone(),
|
||||||
|
@ -500,6 +505,12 @@ impl PubGrubReportFormatter<'_> {
|
||||||
IncompletePackage::Offline => {
|
IncompletePackage::Offline => {
|
||||||
hints.insert(PubGrubHint::Offline);
|
hints.insert(PubGrubHint::Offline);
|
||||||
}
|
}
|
||||||
|
IncompletePackage::MissingMetadata => {
|
||||||
|
hints.insert(PubGrubHint::MissingVersionMetadata {
|
||||||
|
package: package.clone(),
|
||||||
|
version: version.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
IncompletePackage::InvalidMetadata(reason) => {
|
IncompletePackage::InvalidMetadata(reason) => {
|
||||||
hints.insert(PubGrubHint::InvalidVersionMetadata {
|
hints.insert(PubGrubHint::InvalidVersionMetadata {
|
||||||
package: package.clone(),
|
package: package.clone(),
|
||||||
|
@ -601,6 +612,8 @@ pub(crate) enum PubGrubHint {
|
||||||
NoIndex,
|
NoIndex,
|
||||||
/// A package was not found in the registry, but network access was disabled.
|
/// A package was not found in the registry, but network access was disabled.
|
||||||
Offline,
|
Offline,
|
||||||
|
/// Metadata for a package could not be found.
|
||||||
|
MissingPackageMetadata { package: PubGrubPackage },
|
||||||
/// Metadata for a package could not be parsed.
|
/// Metadata for a package could not be parsed.
|
||||||
InvalidPackageMetadata {
|
InvalidPackageMetadata {
|
||||||
package: PubGrubPackage,
|
package: PubGrubPackage,
|
||||||
|
@ -613,6 +626,12 @@ pub(crate) enum PubGrubHint {
|
||||||
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
||||||
reason: String,
|
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.
|
/// Metadata for a package version could not be parsed.
|
||||||
InvalidVersionMetadata {
|
InvalidVersionMetadata {
|
||||||
package: PubGrubPackage,
|
package: PubGrubPackage,
|
||||||
|
@ -689,6 +708,15 @@ impl std::fmt::Display for PubGrubHint {
|
||||||
":".bold(),
|
":".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 } => {
|
Self::InvalidPackageMetadata { package, reason } => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -709,6 +737,16 @@ impl std::fmt::Display for PubGrubHint {
|
||||||
textwrap::indent(reason, " ")
|
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 {
|
Self::InvalidVersionMetadata {
|
||||||
package,
|
package,
|
||||||
version,
|
version,
|
||||||
|
|
|
@ -30,6 +30,8 @@ impl Display for UnavailableReason {
|
||||||
pub(crate) enum UnavailableVersion {
|
pub(crate) enum UnavailableVersion {
|
||||||
/// Version is incompatible because it has no usable distributions
|
/// Version is incompatible because it has no usable distributions
|
||||||
IncompatibleDist(IncompatibleDist),
|
IncompatibleDist(IncompatibleDist),
|
||||||
|
/// The wheel metadata was not found.
|
||||||
|
MissingMetadata,
|
||||||
/// The wheel metadata was found, but could not be parsed.
|
/// The wheel metadata was found, but could not be parsed.
|
||||||
InvalidMetadata,
|
InvalidMetadata,
|
||||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
/// 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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
UnavailableVersion::IncompatibleDist(invalid_dist) => Display::fmt(invalid_dist, f),
|
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::InvalidMetadata => f.write_str("has invalid metadata"),
|
||||||
UnavailableVersion::InconsistentMetadata => f.write_str("has inconsistent metadata"),
|
UnavailableVersion::InconsistentMetadata => f.write_str("has inconsistent metadata"),
|
||||||
UnavailableVersion::InvalidStructure => f.write_str("has an invalid package format"),
|
UnavailableVersion::InvalidStructure => f.write_str("has an invalid package format"),
|
||||||
|
@ -66,6 +71,8 @@ pub(crate) enum UnavailablePackage {
|
||||||
Offline,
|
Offline,
|
||||||
/// The package was not found in the registry.
|
/// The package was not found in the registry.
|
||||||
NotFound,
|
NotFound,
|
||||||
|
/// The package metadata was not found.
|
||||||
|
MissingMetadata,
|
||||||
/// The package metadata was found, but could not be parsed.
|
/// The package metadata was found, but could not be parsed.
|
||||||
InvalidMetadata(String),
|
InvalidMetadata(String),
|
||||||
/// The package has an invalid structure.
|
/// The package has an invalid structure.
|
||||||
|
@ -78,6 +85,7 @@ impl UnavailablePackage {
|
||||||
UnavailablePackage::NoIndex => "was not found in the provided package locations",
|
UnavailablePackage::NoIndex => "was not found in the provided package locations",
|
||||||
UnavailablePackage::Offline => "was not found in the cache",
|
UnavailablePackage::Offline => "was not found in the cache",
|
||||||
UnavailablePackage::NotFound => "was not found in the package registry",
|
UnavailablePackage::NotFound => "was not found in the package registry",
|
||||||
|
UnavailablePackage::MissingMetadata => "does not include a `METADATA` file",
|
||||||
UnavailablePackage::InvalidMetadata(_) => "has invalid metadata",
|
UnavailablePackage::InvalidMetadata(_) => "has invalid metadata",
|
||||||
UnavailablePackage::InvalidStructure(_) => "has an invalid package format",
|
UnavailablePackage::InvalidStructure(_) => "has an invalid package format",
|
||||||
}
|
}
|
||||||
|
@ -95,6 +103,8 @@ impl Display for UnavailablePackage {
|
||||||
pub(crate) enum IncompletePackage {
|
pub(crate) enum IncompletePackage {
|
||||||
/// Network requests were disabled (i.e., `--offline`), and the wheel metadata was not found in the cache.
|
/// Network requests were disabled (i.e., `--offline`), and the wheel metadata was not found in the cache.
|
||||||
Offline,
|
Offline,
|
||||||
|
/// The wheel metadata was not found.
|
||||||
|
MissingMetadata,
|
||||||
/// The wheel metadata was found, but could not be parsed.
|
/// The wheel metadata was found, but could not be parsed.
|
||||||
InvalidMetadata(String),
|
InvalidMetadata(String),
|
||||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
/// The wheel metadata was found, but the metadata was inconsistent.
|
||||||
|
|
|
@ -749,6 +749,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
.insert(name.clone(), UnavailablePackage::Offline);
|
.insert(name.clone(), UnavailablePackage::Offline);
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
MetadataResponse::MissingMetadata => {
|
||||||
|
self.unavailable_packages
|
||||||
|
.insert(name.clone(), UnavailablePackage::MissingMetadata);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
MetadataResponse::InvalidMetadata(err) => {
|
MetadataResponse::InvalidMetadata(err) => {
|
||||||
self.unavailable_packages.insert(
|
self.unavailable_packages.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
@ -1042,6 +1047,15 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
.insert(version.clone(), IncompletePackage::Offline);
|
.insert(version.clone(), IncompletePackage::Offline);
|
||||||
return Ok(Dependencies::Unavailable(UnavailableVersion::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) => {
|
MetadataResponse::InvalidMetadata(err) => {
|
||||||
warn!("Unable to extract metadata for {name}: {err}");
|
warn!("Unable to extract metadata for {name}: {err}");
|
||||||
self.incomplete_packages
|
self.incomplete_packages
|
||||||
|
|
|
@ -33,6 +33,8 @@ pub enum VersionsResponse {
|
||||||
pub enum MetadataResponse {
|
pub enum MetadataResponse {
|
||||||
/// The wheel metadata was found and parsed successfully.
|
/// The wheel metadata was found and parsed successfully.
|
||||||
Found(ArchiveMetadata),
|
Found(ArchiveMetadata),
|
||||||
|
/// The wheel metadata was not found.
|
||||||
|
MissingMetadata,
|
||||||
/// The wheel metadata was found, but could not be parsed.
|
/// The wheel metadata was found, but could not be parsed.
|
||||||
InvalidMetadata(Box<pypi_types::MetadataError>),
|
InvalidMetadata(Box<pypi_types::MetadataError>),
|
||||||
/// The wheel metadata was found, but the metadata was inconsistent.
|
/// 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 {
|
Err(err) => match err {
|
||||||
uv_distribution::Error::Client(client) => match client.into_kind() {
|
uv_distribution::Error::Client(client) => match client.into_kind() {
|
||||||
uv_client::ErrorKind::Offline(_) => Ok(MetadataResponse::Offline),
|
uv_client::ErrorKind::Offline(_) => Ok(MetadataResponse::Offline),
|
||||||
|
uv_client::ErrorKind::MetadataNotFound(_, _) => {
|
||||||
|
Ok(MetadataResponse::MissingMetadata)
|
||||||
|
}
|
||||||
uv_client::ErrorKind::MetadataParseError(_, _, err) => {
|
uv_client::ErrorKind::MetadataParseError(_, _, err) => {
|
||||||
Ok(MetadataResponse::InvalidMetadata(err))
|
Ok(MetadataResponse::InvalidMetadata(err))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue