Skip to content

Commit

Permalink
Treat as settings
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 16, 2024
1 parent a60f3ab commit da3d55b
Show file tree
Hide file tree
Showing 28 changed files with 478 additions and 67 deletions.
10 changes: 5 additions & 5 deletions crates/bench/benches/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,18 @@ mod resolver {
.timestamp()
.into(),
);
let build_constraints = Constraints::default();
let capabilities = IndexCapabilities::default();
let flat_index = FlatIndex::default();
let git = GitResolver::default();
let capabilities = IndexCapabilities::default();
let static_metadata = StaticMetadata::default();
let hashes = HashStrategy::default();
let in_flight = InFlight::default();
let index = InMemoryIndex::default();
let index_locations = IndexLocations::default();
let installed_packages = EmptyInstalledPackages;
let sources = SourceStrategy::default();
let options = OptionsBuilder::new().exclude_newer(exclude_newer).build();
let build_constraints = Constraints::default();
let sources = SourceStrategy::default();
let static_metadata = StaticMetadata::default();

let python_requirement = if universal {
PythonRequirement::from_requires_python(
Expand All @@ -179,10 +179,10 @@ mod resolver {
interpreter,
&index_locations,
&flat_index,
&static_metadata,
&index,
&git,
&capabilities,
&static_metadata,
&in_flight,
IndexStrategy::default(),
&config_settings,
Expand Down
12 changes: 8 additions & 4 deletions crates/distribution-types/src/static_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use pypi_types::Metadata23;
use rustc_hash::FxHashMap;
use uv_normalize::PackageName;

/// Pre-defined [`Metadata23`] entries, indexed by [`PackageName`] and [`Version`].
#[derive(Debug, Clone, Default)]
pub struct StaticMetadata(FxHashMap<PackageName, FxHashMap<Version, Metadata23>>);

impl StaticMetadata {
/// Index a set of [`Metadata23`] entries by [`PackageName`] and [`Version`].
pub fn from_entries(entries: impl IntoIterator<Item = Metadata23>) -> Self {
let mut map = Self::default();
for entry in entries {
Expand All @@ -18,11 +20,13 @@ impl StaticMetadata {
map
}

pub fn insert(&mut self, package: PackageName, version: Version, metadata: Metadata23) {
self.0.entry(package).or_default().insert(version, metadata);
}

/// Retrieve a [`Metadata23`] entry by [`PackageName`] and [`Version`].
pub fn get(&self, package: &PackageName, version: &Version) -> Option<&Metadata23> {
self.0.get(package).and_then(|map| map.get(version))
}

/// Retrieve all [`Metadata23`] entries.
pub fn values(&self) -> impl Iterator<Item = &Metadata23> {
self.0.values().flat_map(|map| map.values())
}
}
8 changes: 5 additions & 3 deletions crates/pep508-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ create_exception!(
);

/// A PEP 508 dependency specifier.
#[derive(Hash, Debug, Clone, Eq, PartialEq)]
#[derive(Hash, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Requirement<T: Pep508Url = VerbatimUrl> {
/// The distribution name such as `requests` in
/// `requests [security,tests] >= 2.8.1, == 2.8.* ; python_version > "3.8"`.
Expand Down Expand Up @@ -480,7 +480,9 @@ impl<T: Pep508Url> schemars::JsonSchema for Requirement<T> {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("A PEP 508 dependency specifier".to_string()),
description: Some(
"A PEP 508 dependency specifier, e.g., `ruff >= 0.6.0`".to_string(),
),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
Expand Down Expand Up @@ -535,7 +537,7 @@ impl Extras {
}

/// The actual version specifier or URL to install.
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum VersionOrUrl<T: Pep508Url = VerbatimUrl> {
/// A PEP 440 version specifier set
VersionSpecifier(VersionSpecifiers),
Expand Down
4 changes: 3 additions & 1 deletion crates/pypi-types/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{LenientVersionSpecifiers, VerbatimParsedUrl};
/// fields that are relevant to dependency resolution.
///
/// At present, we support up to version 2.3 of the metadata specification.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub struct Metadata23 {
Expand All @@ -41,6 +41,7 @@ pub struct Metadata23 {
)]
pub version: Version,
// Optional fields
#[serde(default)]
pub requires_dist: Vec<Requirement<VerbatimParsedUrl>>,
#[cfg_attr(
feature = "schemars",
Expand All @@ -50,6 +51,7 @@ pub struct Metadata23 {
)
)]
pub requires_python: Option<VersionSpecifiers>,
#[serde(default)]
pub provides_extras: Vec<ExtraName>,
}

Expand Down
22 changes: 22 additions & 0 deletions crates/uv-distribution/src/distribution_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,15 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
dist: &BuiltDist,
hashes: HashPolicy<'_>,
) -> Result<ArchiveMetadata, Error> {
// If the metadata was provided by the user directly, prefer it.
if let Some(metadata) = self
.build_context
.static_metadata()
.get(dist.name(), dist.version())
{
return Ok(ArchiveMetadata::from_metadata23(metadata.clone()));
}

// If hash generation is enabled, and the distribution isn't hosted on an index, get the
// entire wheel to ensure that the hashes are included in the response. If the distribution
// is hosted on an index, the hashes will be included in the simple metadata response.
Expand Down Expand Up @@ -415,6 +424,19 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
source: &BuildableSource<'_>,
hashes: HashPolicy<'_>,
) -> Result<ArchiveMetadata, Error> {
// If the metadata was provided by the user directly, prefer it.
if let Some(dist) = source.as_dist() {
if let Some(version) = dist.version() {
if let Some(metadata) = self
.build_context
.static_metadata()
.get(dist.name(), version)
{
return Ok(ArchiveMetadata::from_metadata23(metadata.clone()));
}
}
}

// Optimization: Skip source dist download when we must not build them anyway.
if self
.build_context
Expand Down
56 changes: 53 additions & 3 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ use distribution_types::{
BuiltDist, DirectUrlBuiltDist, DirectUrlSourceDist, DirectorySourceDist, Dist,
DistributionMetadata, FileLocation, FlatIndexLocation, GitSourceDist, HashPolicy,
IndexLocations, IndexUrl, Name, PathBuiltDist, PathSourceDist, RegistryBuiltDist,
RegistryBuiltWheel, RegistrySourceDist, RemoteSource, Resolution, ResolvedDist, ToUrlError,
UrlString,
RegistryBuiltWheel, RegistrySourceDist, RemoteSource, Resolution, ResolvedDist, StaticMetadata,
ToUrlError, UrlString,
};
use pep440_rs::Version;
use pep508_rs::{split_scheme, MarkerEnvironment, MarkerTree, VerbatimUrl, VerbatimUrlError};
use platform_tags::{TagCompatibility, TagPriority, Tags};
use pypi_types::{
redact_git_credentials, HashDigest, ParsedArchiveUrl, ParsedGitUrl, Requirement,
redact_git_credentials, HashDigest, Metadata23, ParsedArchiveUrl, ParsedGitUrl, Requirement,
RequirementSource, ResolverMarkerEnvironment,
};
use uv_configuration::{BuildOptions, ExtrasSpecification, InstallOptions};
Expand Down Expand Up @@ -793,6 +793,38 @@ impl Lock {
manifest_table.insert("overrides", value(overrides));
}

if !self.manifest.static_metadata.is_empty() {
let mut tables = ArrayOfTables::new();
for metadata in &self.manifest.static_metadata {
let mut table = Table::new();
table.insert("name", value(metadata.name.to_string()));
table.insert("version", value(metadata.version.to_string()));
if !metadata.requires_dist.is_empty() {
table.insert(
"requires-dist",
value(serde::Serialize::serialize(
&metadata.requires_dist,
toml_edit::ser::ValueSerializer::new(),
)?),
);
}
if let Some(requires_python) = metadata.requires_python.as_ref() {
table.insert("requires-python", value(requires_python.to_string()));
}
if !metadata.provides_extras.is_empty() {
table.insert(
"provides-extras",
value(serde::Serialize::serialize(
&metadata.provides_extras,
toml_edit::ser::ValueSerializer::new(),
)?),
);
}
tables.push(table);
}
manifest_table.insert("static-metadata", Item::ArrayOfTables(tables));
}

if !manifest_table.is_empty() {
doc.insert("manifest", Item::Table(manifest_table));
}
Expand Down Expand Up @@ -879,6 +911,7 @@ impl Lock {
requirements: &[Requirement],
constraints: &[Requirement],
overrides: &[Requirement],
static_metadata: &StaticMetadata,
indexes: Option<&IndexLocations>,
build_options: &BuildOptions,
tags: &Tags,
Expand Down Expand Up @@ -993,6 +1026,15 @@ impl Lock {
}
}

// Validate that the lockfile was generated with the same static metadata.
{
let expected = static_metadata.values().cloned().collect::<BTreeSet<_>>();
let actual = &self.manifest.static_metadata;
if expected != *actual {
return Ok(SatisfiesResult::MismatchedStaticMetadata(expected, actual));
}
}

// Collect the set of available indexes (both `--index-url` and `--find-links` entries).
let remotes = indexes.map(|locations| {
locations
Expand Down Expand Up @@ -1247,6 +1289,8 @@ pub enum SatisfiesResult<'lock> {
MismatchedConstraints(BTreeSet<Requirement>, BTreeSet<Requirement>),
/// The lockfile uses a different set of overrides.
MismatchedOverrides(BTreeSet<Requirement>, BTreeSet<Requirement>),
/// The lockfile uses different static metadata.
MismatchedStaticMetadata(BTreeSet<Metadata23>, &'lock BTreeSet<Metadata23>),
/// The lockfile is missing a workspace member.
MissingRoot(PackageName),
/// The lockfile referenced a remote index that was not provided
Expand Down Expand Up @@ -1300,6 +1344,9 @@ pub struct ResolverManifest {
/// The overrides provided to the resolver.
#[serde(default)]
overrides: BTreeSet<Requirement>,
/// The static metadata provided to the resolver.
#[serde(default)]
static_metadata: BTreeSet<Metadata23>,
}

impl ResolverManifest {
Expand All @@ -1310,12 +1357,14 @@ impl ResolverManifest {
requirements: impl IntoIterator<Item = Requirement>,
constraints: impl IntoIterator<Item = Requirement>,
overrides: impl IntoIterator<Item = Requirement>,
static_metadata: impl IntoIterator<Item = Metadata23>,
) -> Self {
Self {
members: members.into_iter().collect(),
requirements: requirements.into_iter().collect(),
constraints: constraints.into_iter().collect(),
overrides: overrides.into_iter().collect(),
static_metadata: static_metadata.into_iter().collect(),
}
}

Expand All @@ -1338,6 +1387,7 @@ impl ResolverManifest {
.into_iter()
.map(|requirement| requirement.relative_to(workspace.install_path()))
.collect::<Result<BTreeSet<_>, _>>()?,
static_metadata: self.static_metadata,
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Ok(
requirements: {},
constraints: {},
overrides: {},
static_metadata: {},
},
},
)
2 changes: 1 addition & 1 deletion crates/uv-settings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ workspace = true
distribution-types = { workspace = true, features = ["schemars"] }
install-wheel-rs = { workspace = true, features = ["schemars", "clap"] }
pep508_rs = { workspace = true }
pypi-types = { workspace = true }
pypi-types = { workspace = true, features = ["schemars"] }
uv-cache-info = { workspace = true, features = ["schemars"] }
uv-configuration = { workspace = true, features = ["schemars", "clap"] }
uv-fs = { workspace = true }
Expand Down
Loading

0 comments on commit da3d55b

Please sign in to comment.