Respect static metadata for already-installed distributions (#10242)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

## Summary

Closes
https://github.com/astral-sh/uv/issues/10239#issuecomment-2565663046
This commit is contained in:
Charlie Marsh 2024-12-30 12:47:06 -05:00 committed by GitHub
parent dec6f5aa02
commit dcd96a83aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 347 additions and 47 deletions

View file

@ -10,8 +10,7 @@ use rustc_hash::FxHashMap;
use tracing::trace;
use uv_distribution_types::{
DerivationChain, Dist, DistErrorKind, IndexCapabilities, IndexLocations, IndexUrl,
InstalledDist, InstalledDistError,
DerivationChain, DistErrorKind, IndexCapabilities, IndexLocations, IndexUrl, RequestedDist,
};
use uv_normalize::{ExtraName, PackageName};
use uv_pep440::{LocalVersionSlice, Version};
@ -98,14 +97,11 @@ pub enum ResolveError {
#[error("{0} `{1}`")]
Dist(
DistErrorKind,
Box<Dist>,
Box<RequestedDist>,
DerivationChain,
#[source] Arc<uv_distribution::Error>,
),
#[error("Failed to read metadata from installed package `{0}`")]
ReadInstalled(Box<InstalledDist>, #[source] InstalledDistError),
#[error(transparent)]
NoSolution(#[from] NoSolutionError),

View file

@ -21,7 +21,7 @@ use tokio_stream::wrappers::ReceiverStream;
use tracing::{debug, info, instrument, trace, warn, Level};
use uv_configuration::{Constraints, Overrides};
use uv_distribution::{ArchiveMetadata, DistributionDatabase};
use uv_distribution::DistributionDatabase;
use uv_distribution_types::{
BuiltDist, CompatibleDist, DerivationChain, Dist, DistErrorKind, DistributionMetadata,
IncompatibleDist, IncompatibleSource, IncompatibleWheel, IndexCapabilities, IndexLocations,
@ -33,9 +33,7 @@ use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::{release_specifiers_to_ranges, Version, VersionSpecifiers, MIN_VERSION};
use uv_pep508::MarkerTree;
use uv_platform_tags::Tags;
use uv_pypi_types::{
ConflictItem, ConflictItemRef, Conflicts, Requirement, ResolutionMetadata, VerbatimParsedUrl,
};
use uv_pypi_types::{ConflictItem, ConflictItemRef, Conflicts, Requirement, VerbatimParsedUrl};
use uv_types::{BuildContext, HashStrategy, InstalledPackagesProvider};
use uv_warnings::warn_user_once;
@ -1097,11 +1095,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
.insert(name.clone(), reason.into());
return Ok(None);
}
// TODO(charlie): Add derivation chain for URL dependencies. In practice, this isn't
// critical since we fetch URL dependencies _prior_ to invoking the resolver.
MetadataResponse::Error(dist, err) => {
// TODO(charlie): Add derivation chain for URL dependencies. In practice, this isn't
// critical since we fetch URL dependencies _prior_ to invoking the resolver.
return Err(ResolveError::Dist(
DistErrorKind::from_dist_and_err(dist, &**err),
DistErrorKind::from_requested_dist(dist, &**err),
dist.clone(),
DerivationChain::default(),
err.clone(),
@ -1642,7 +1640,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
let chain = DerivationChainBuilder::from_state(id, version, pubgrub)
.unwrap_or_default();
return Err(ResolveError::Dist(
DistErrorKind::from_dist_and_err(dist, &**err),
DistErrorKind::from_requested_dist(dist, &**err),
dist.clone(),
chain,
err.clone(),
@ -2068,12 +2066,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
}
Some(Response::Installed { dist, metadata }) => {
trace!("Received installed distribution metadata for: {dist}");
self.index.distributions().done(
dist.version_id(),
Arc::new(MetadataResponse::Found(ArchiveMetadata::from_metadata23(
metadata,
))),
);
self.index
.distributions()
.done(dist.version_id(), Arc::new(metadata));
}
Some(Response::Dist { dist, metadata }) => {
let dist_kind = match dist {
@ -2134,10 +2129,8 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
}
Request::Installed(dist) => {
// TODO(charlie): This should be return a `MetadataResponse`.
let metadata = dist
.metadata()
.map_err(|err| ResolveError::ReadInstalled(Box::new(dist.clone()), err))?;
let metadata = provider.get_installed_metadata(&dist).boxed_local().await?;
Ok(Some(Response::Installed { dist, metadata }))
}
@ -2251,9 +2244,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
Response::Dist { dist, metadata }
}
ResolvedDist::Installed { dist } => {
let metadata = dist.metadata().map_err(|err| {
ResolveError::ReadInstalled(Box::new(dist.clone()), err)
})?;
let metadata =
provider.get_installed_metadata(&dist).boxed_local().await?;
Response::Installed { dist, metadata }
}
};
@ -3079,7 +3072,7 @@ enum Response {
/// The returned metadata for an already-installed distribution.
Installed {
dist: InstalledDist,
metadata: ResolutionMetadata,
metadata: MetadataResponse,
},
}

View file

@ -3,7 +3,7 @@ use std::sync::Arc;
use uv_configuration::BuildOptions;
use uv_distribution::{ArchiveMetadata, DistributionDatabase};
use uv_distribution_types::{Dist, IndexCapabilities, IndexUrl};
use uv_distribution_types::{Dist, IndexCapabilities, IndexUrl, InstalledDist, RequestedDist};
use uv_normalize::PackageName;
use uv_pep440::{Version, VersionSpecifiers};
use uv_platform_tags::Tags;
@ -37,7 +37,7 @@ pub enum MetadataResponse {
/// A non-fatal error.
Unavailable(MetadataUnavailable),
/// The distribution could not be built or downloaded, a fatal error.
Error(Box<Dist>, Arc<uv_distribution::Error>),
Error(Box<RequestedDist>, Arc<uv_distribution::Error>),
}
/// Non-fatal metadata fetching error.
@ -83,7 +83,7 @@ pub trait ResolverProvider {
/// Get the metadata for a distribution.
///
/// For a wheel, this is done by querying it's (remote) metadata, for a source dist we
/// For a wheel, this is done by querying it (remote) metadata. For a source distribution, we
/// (fetch and) build the source distribution and return the metadata from the built
/// distribution.
fn get_or_build_wheel_metadata<'io>(
@ -91,6 +91,12 @@ pub trait ResolverProvider {
dist: &'io Dist,
) -> impl Future<Output = WheelMetadataResult> + 'io;
/// Get the metadata for an installed distribution.
fn get_installed_metadata<'io>(
&'io self,
dist: &'io InstalledDist,
) -> impl Future<Output = WheelMetadataResult> + 'io;
/// Set the [`uv_distribution::Reporter`] to use for this installer.
#[must_use]
fn with_reporter(self, reporter: impl uv_distribution::Reporter + 'static) -> Self;
@ -246,13 +252,27 @@ impl<'a, Context: BuildContext> ResolverProvider for DefaultResolverProvider<'a,
))
}
err => Ok(MetadataResponse::Error(
Box::new(dist.clone()),
Box::new(RequestedDist::Installable(dist.clone())),
Arc::new(err),
)),
},
}
}
/// Return the metadata for an installed distribution.
async fn get_installed_metadata<'io>(
&'io self,
dist: &'io InstalledDist,
) -> WheelMetadataResult {
match self.fetcher.get_installed_metadata(dist).await {
Ok(metadata) => Ok(MetadataResponse::Found(metadata)),
Err(err) => Ok(MetadataResponse::Error(
Box::new(RequestedDist::Installed(dist.clone())),
Arc::new(err),
)),
}
}
/// Set the [`uv_distribution::Reporter`] to use for this installer.
#[must_use]
fn with_reporter(self, reporter: impl uv_distribution::Reporter + 'static) -> Self {