mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-17 13:58:29 +00:00
Rename ResolutionGraph
to ResolverOutput
(#9103)
## Summary As discussed in Discord... This struct has evolved to include a lot of information apart from the `petgraph::Graph`. And I want to add a graph to the simplified `Resolution` type. So I think this name makes more sense.
This commit is contained in:
parent
02a7bb43d9
commit
b37170df94
12 changed files with 104 additions and 109 deletions
|
@ -101,7 +101,7 @@ mod resolver {
|
||||||
use uv_python::Interpreter;
|
use uv_python::Interpreter;
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, RequiresPython,
|
FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, RequiresPython,
|
||||||
ResolutionGraph, Resolver, ResolverEnvironment,
|
Resolver, ResolverEnvironment, ResolverOutput,
|
||||||
};
|
};
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ mod resolver {
|
||||||
client: &RegistryClient,
|
client: &RegistryClient,
|
||||||
interpreter: &Interpreter,
|
interpreter: &Interpreter,
|
||||||
universal: bool,
|
universal: bool,
|
||||||
) -> Result<ResolutionGraph> {
|
) -> Result<ResolverOutput> {
|
||||||
let build_isolation = BuildIsolation::default();
|
let build_isolation = BuildIsolation::default();
|
||||||
let build_options = BuildOptions::default();
|
let build_options = BuildOptions::default();
|
||||||
let concurrency = Concurrency::default();
|
let concurrency = Concurrency::default();
|
||||||
|
|
|
@ -197,7 +197,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
|
||||||
EmptyInstalledPackages,
|
EmptyInstalledPackages,
|
||||||
DistributionDatabase::new(self.client, self, self.concurrency.downloads),
|
DistributionDatabase::new(self.client, self, self.concurrency.downloads),
|
||||||
)?;
|
)?;
|
||||||
let graph = resolver.resolve().await.with_context(|| {
|
let resolution = Resolution::from(resolver.resolve().await.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"No solution found when resolving: {}",
|
"No solution found when resolving: {}",
|
||||||
requirements
|
requirements
|
||||||
|
@ -205,8 +205,8 @@ impl<'a> BuildContext for BuildDispatch<'a> {
|
||||||
.map(|requirement| format!("`{requirement}`"))
|
.map(|requirement| format!("`{requirement}`"))
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
})?;
|
})?);
|
||||||
Ok(Resolution::from(graph))
|
Ok(resolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(
|
#[instrument(
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub use prerelease::PrereleaseMode;
|
||||||
pub use python_requirement::PythonRequirement;
|
pub use python_requirement::PythonRequirement;
|
||||||
pub use requires_python::{RequiresPython, RequiresPythonRange};
|
pub use requires_python::{RequiresPython, RequiresPythonRange};
|
||||||
pub use resolution::{
|
pub use resolution::{
|
||||||
AnnotationStyle, ConflictingDistributionError, DisplayResolutionGraph, ResolutionGraph,
|
AnnotationStyle, ConflictingDistributionError, DisplayResolutionGraph, ResolverOutput,
|
||||||
};
|
};
|
||||||
pub use resolution_mode::ResolutionMode;
|
pub use resolution_mode::ResolutionMode;
|
||||||
pub use resolver::{
|
pub use resolver::{
|
||||||
|
|
|
@ -20,8 +20,8 @@ pub use crate::lock::tree::TreeDisplay;
|
||||||
use crate::requires_python::SimplifiedMarkerTree;
|
use crate::requires_python::SimplifiedMarkerTree;
|
||||||
use crate::resolution::{AnnotatedDist, ResolutionGraphNode};
|
use crate::resolution::{AnnotatedDist, ResolutionGraphNode};
|
||||||
use crate::{
|
use crate::{
|
||||||
ExcludeNewer, InMemoryIndex, MetadataResponse, PrereleaseMode, RequiresPython, ResolutionGraph,
|
ExcludeNewer, InMemoryIndex, MetadataResponse, PrereleaseMode, RequiresPython, ResolutionMode,
|
||||||
ResolutionMode,
|
ResolverOutput,
|
||||||
};
|
};
|
||||||
use uv_cache_key::RepositoryUrl;
|
use uv_cache_key::RepositoryUrl;
|
||||||
use uv_configuration::BuildOptions;
|
use uv_configuration::BuildOptions;
|
||||||
|
@ -108,16 +108,16 @@ pub struct Lock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lock {
|
impl Lock {
|
||||||
/// Initialize a [`Lock`] from a [`ResolutionGraph`].
|
/// Initialize a [`Lock`] from a [`ResolverOutput`].
|
||||||
pub fn from_resolution_graph(graph: &ResolutionGraph, root: &Path) -> Result<Self, LockError> {
|
pub fn from_resolution(resolution: &ResolverOutput, root: &Path) -> Result<Self, LockError> {
|
||||||
let mut packages = BTreeMap::new();
|
let mut packages = BTreeMap::new();
|
||||||
let requires_python = graph.requires_python.clone();
|
let requires_python = resolution.requires_python.clone();
|
||||||
|
|
||||||
// Determine the set of packages included at multiple versions.
|
// Determine the set of packages included at multiple versions.
|
||||||
let mut seen = FxHashSet::default();
|
let mut seen = FxHashSet::default();
|
||||||
let mut duplicates = FxHashSet::default();
|
let mut duplicates = FxHashSet::default();
|
||||||
for node_index in graph.petgraph.node_indices() {
|
for node_index in resolution.graph.node_indices() {
|
||||||
let ResolutionGraphNode::Dist(dist) = &graph.petgraph[node_index] else {
|
let ResolutionGraphNode::Dist(dist) = &resolution.graph[node_index] else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if !dist.is_base() {
|
if !dist.is_base() {
|
||||||
|
@ -129,8 +129,8 @@ impl Lock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock all base packages.
|
// Lock all base packages.
|
||||||
for node_index in graph.petgraph.node_indices() {
|
for node_index in resolution.graph.node_indices() {
|
||||||
let ResolutionGraphNode::Dist(dist) = &graph.petgraph[node_index] else {
|
let ResolutionGraphNode::Dist(dist) = &resolution.graph[node_index] else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if !dist.is_base() {
|
if !dist.is_base() {
|
||||||
|
@ -140,7 +140,7 @@ impl Lock {
|
||||||
// If there are multiple distributions for the same package, include the markers of all
|
// If there are multiple distributions for the same package, include the markers of all
|
||||||
// forks that included the current distribution.
|
// forks that included the current distribution.
|
||||||
let fork_markers = if duplicates.contains(dist.name()) {
|
let fork_markers = if duplicates.contains(dist.name()) {
|
||||||
graph
|
resolution
|
||||||
.fork_markers
|
.fork_markers
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|fork_markers| !fork_markers.is_disjoint(&dist.marker))
|
.filter(|fork_markers| !fork_markers.is_disjoint(&dist.marker))
|
||||||
|
@ -151,11 +151,11 @@ impl Lock {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut package = Package::from_annotated_dist(dist, fork_markers, root)?;
|
let mut package = Package::from_annotated_dist(dist, fork_markers, root)?;
|
||||||
Self::remove_unreachable_wheels(graph, &requires_python, node_index, &mut package);
|
Self::remove_unreachable_wheels(resolution, &requires_python, node_index, &mut package);
|
||||||
|
|
||||||
// Add all dependencies
|
// Add all dependencies
|
||||||
for edge in graph.petgraph.edges(node_index) {
|
for edge in resolution.graph.edges(node_index) {
|
||||||
let ResolutionGraphNode::Dist(dependency_dist) = &graph.petgraph[edge.target()]
|
let ResolutionGraphNode::Dist(dependency_dist) = &resolution.graph[edge.target()]
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -173,8 +173,8 @@ impl Lock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock all extras and development dependencies.
|
// Lock all extras and development dependencies.
|
||||||
for node_index in graph.petgraph.node_indices() {
|
for node_index in resolution.graph.node_indices() {
|
||||||
let ResolutionGraphNode::Dist(dist) = &graph.petgraph[node_index] else {
|
let ResolutionGraphNode::Dist(dist) = &resolution.graph[node_index] else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(extra) = dist.extra.as_ref() {
|
if let Some(extra) = dist.extra.as_ref() {
|
||||||
|
@ -186,8 +186,9 @@ impl Lock {
|
||||||
}
|
}
|
||||||
.into());
|
.into());
|
||||||
};
|
};
|
||||||
for edge in graph.petgraph.edges(node_index) {
|
for edge in resolution.graph.edges(node_index) {
|
||||||
let ResolutionGraphNode::Dist(dependency_dist) = &graph.petgraph[edge.target()]
|
let ResolutionGraphNode::Dist(dependency_dist) =
|
||||||
|
&resolution.graph[edge.target()]
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -210,8 +211,9 @@ impl Lock {
|
||||||
}
|
}
|
||||||
.into());
|
.into());
|
||||||
};
|
};
|
||||||
for edge in graph.petgraph.edges(node_index) {
|
for edge in resolution.graph.edges(node_index) {
|
||||||
let ResolutionGraphNode::Dist(dependency_dist) = &graph.petgraph[edge.target()]
|
let ResolutionGraphNode::Dist(dependency_dist) =
|
||||||
|
&resolution.graph[edge.target()]
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -229,9 +231,9 @@ impl Lock {
|
||||||
|
|
||||||
let packages = packages.into_values().collect();
|
let packages = packages.into_values().collect();
|
||||||
let options = ResolverOptions {
|
let options = ResolverOptions {
|
||||||
resolution_mode: graph.options.resolution_mode,
|
resolution_mode: resolution.options.resolution_mode,
|
||||||
prerelease_mode: graph.options.prerelease_mode,
|
prerelease_mode: resolution.options.prerelease_mode,
|
||||||
exclude_newer: graph.options.exclude_newer,
|
exclude_newer: resolution.options.exclude_newer,
|
||||||
};
|
};
|
||||||
let lock = Self::new(
|
let lock = Self::new(
|
||||||
VERSION,
|
VERSION,
|
||||||
|
@ -241,7 +243,7 @@ impl Lock {
|
||||||
ResolverManifest::default(),
|
ResolverManifest::default(),
|
||||||
Conflicts::empty(),
|
Conflicts::empty(),
|
||||||
vec![],
|
vec![],
|
||||||
graph.fork_markers.clone(),
|
resolution.fork_markers.clone(),
|
||||||
)?;
|
)?;
|
||||||
Ok(lock)
|
Ok(lock)
|
||||||
}
|
}
|
||||||
|
@ -251,7 +253,7 @@ impl Lock {
|
||||||
/// For example, a package included under `sys_platform == 'win32'` does not need Linux
|
/// For example, a package included under `sys_platform == 'win32'` does not need Linux
|
||||||
/// wheels.
|
/// wheels.
|
||||||
fn remove_unreachable_wheels(
|
fn remove_unreachable_wheels(
|
||||||
graph: &ResolutionGraph,
|
graph: &ResolverOutput,
|
||||||
requires_python: &RequiresPython,
|
requires_python: &RequiresPython,
|
||||||
node_index: NodeIndex,
|
node_index: NodeIndex,
|
||||||
locked_dist: &mut Package,
|
locked_dist: &mut Package,
|
||||||
|
@ -288,20 +290,16 @@ impl Lock {
|
||||||
tag.starts_with(linux_tag) || tag == "linux_armv6l" || tag == "linux_armv7l"
|
tag.starts_with(linux_tag) || tag == "linux_armv6l" || tag == "linux_armv7l"
|
||||||
})
|
})
|
||||||
}) {
|
}) {
|
||||||
!graph.petgraph[node_index]
|
!graph.graph[node_index].marker().is_disjoint(&LINUX_MARKERS)
|
||||||
.marker()
|
|
||||||
.is_disjoint(&LINUX_MARKERS)
|
|
||||||
} else if platform_tags
|
} else if platform_tags
|
||||||
.iter()
|
.iter()
|
||||||
.all(|tag| windows_tags.contains(&&**tag))
|
.all(|tag| windows_tags.contains(&&**tag))
|
||||||
{
|
{
|
||||||
!graph.petgraph[node_index]
|
!graph.graph[node_index]
|
||||||
.marker()
|
.marker()
|
||||||
.is_disjoint(&WINDOWS_MARKERS)
|
.is_disjoint(&WINDOWS_MARKERS)
|
||||||
} else if platform_tags.iter().all(|tag| tag.starts_with("macosx_")) {
|
} else if platform_tags.iter().all(|tag| tag.starts_with("macosx_")) {
|
||||||
!graph.petgraph[node_index]
|
!graph.graph[node_index].marker().is_disjoint(&MAC_MARKERS)
|
||||||
.marker()
|
|
||||||
.is_disjoint(&MAC_MARKERS)
|
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,14 @@ use uv_normalize::PackageName;
|
||||||
use uv_pep508::MarkerTree;
|
use uv_pep508::MarkerTree;
|
||||||
|
|
||||||
use crate::resolution::{RequirementsTxtDist, ResolutionGraphNode};
|
use crate::resolution::{RequirementsTxtDist, ResolutionGraphNode};
|
||||||
use crate::{ResolutionGraph, ResolverEnvironment};
|
use crate::{ResolverEnvironment, ResolverOutput};
|
||||||
|
|
||||||
/// A [`std::fmt::Display`] implementation for the resolution graph.
|
/// A [`std::fmt::Display`] implementation for the resolution graph.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct DisplayResolutionGraph<'a> {
|
pub struct DisplayResolutionGraph<'a> {
|
||||||
/// The underlying graph.
|
/// The underlying graph.
|
||||||
resolution: &'a ResolutionGraph,
|
resolution: &'a ResolverOutput,
|
||||||
/// The resolver marker environment, used to determine the markers that apply to each package.
|
/// The resolver marker environment, used to determine the markers that apply to each package.
|
||||||
env: &'a ResolverEnvironment,
|
env: &'a ResolverEnvironment,
|
||||||
/// The packages to exclude from the output.
|
/// The packages to exclude from the output.
|
||||||
|
@ -50,7 +50,7 @@ impl<'a> DisplayResolutionGraph<'a> {
|
||||||
/// Create a new [`DisplayResolutionGraph`] for the given graph.
|
/// Create a new [`DisplayResolutionGraph`] for the given graph.
|
||||||
#[allow(clippy::fn_params_excessive_bools)]
|
#[allow(clippy::fn_params_excessive_bools)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
underlying: &'a ResolutionGraph,
|
underlying: &'a ResolverOutput,
|
||||||
env: &'a ResolverEnvironment,
|
env: &'a ResolverEnvironment,
|
||||||
no_emit_packages: &'a [PackageName],
|
no_emit_packages: &'a [PackageName],
|
||||||
show_hashes: bool,
|
show_hashes: bool,
|
||||||
|
@ -136,7 +136,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
|
||||||
// We assign each package its propagated markers: In `requirements.txt`, we want a flat list
|
// We assign each package its propagated markers: In `requirements.txt`, we want a flat list
|
||||||
// that for each package tells us if it should be installed on the current platform, without
|
// that for each package tells us if it should be installed on the current platform, without
|
||||||
// looking at which packages depend on it.
|
// looking at which packages depend on it.
|
||||||
let petgraph = self.resolution.petgraph.map(
|
let graph = self.resolution.graph.map(
|
||||||
|_index, node| match node {
|
|_index, node| match node {
|
||||||
ResolutionGraphNode::Root => DisplayResolutionGraphNode::Root,
|
ResolutionGraphNode::Root => DisplayResolutionGraphNode::Root,
|
||||||
ResolutionGraphNode::Dist(dist) => {
|
ResolutionGraphNode::Dist(dist) => {
|
||||||
|
@ -150,17 +150,17 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reduce the graph, removing or combining extras for a given package.
|
// Reduce the graph, removing or combining extras for a given package.
|
||||||
let petgraph = if self.include_extras {
|
let graph = if self.include_extras {
|
||||||
combine_extras(&petgraph)
|
combine_extras(&graph)
|
||||||
} else {
|
} else {
|
||||||
strip_extras(&petgraph)
|
strip_extras(&graph)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collect all packages.
|
// Collect all packages.
|
||||||
let mut nodes = petgraph
|
let mut nodes = graph
|
||||||
.node_indices()
|
.node_indices()
|
||||||
.filter_map(|index| {
|
.filter_map(|index| {
|
||||||
let dist = &petgraph[index];
|
let dist = &graph[index];
|
||||||
let name = dist.name();
|
let name = dist.name();
|
||||||
if self.no_emit_packages.contains(name) {
|
if self.no_emit_packages.contains(name) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -199,9 +199,9 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
|
||||||
if self.include_annotations {
|
if self.include_annotations {
|
||||||
// Display all dependents (i.e., all packages that depend on the current package).
|
// Display all dependents (i.e., all packages that depend on the current package).
|
||||||
let dependents = {
|
let dependents = {
|
||||||
let mut dependents = petgraph
|
let mut dependents = graph
|
||||||
.edges_directed(index, Direction::Incoming)
|
.edges_directed(index, Direction::Incoming)
|
||||||
.map(|edge| &petgraph[edge.source()])
|
.map(|edge| &graph[edge.source()])
|
||||||
.map(uv_distribution_types::Name::name)
|
.map(uv_distribution_types::Name::name)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
dependents.sort_unstable();
|
dependents.sort_unstable();
|
||||||
|
|
|
@ -11,12 +11,12 @@ use uv_pep508::MarkerTree;
|
||||||
use uv_pypi_types::HashDigest;
|
use uv_pypi_types::HashDigest;
|
||||||
|
|
||||||
pub use crate::resolution::display::{AnnotationStyle, DisplayResolutionGraph};
|
pub use crate::resolution::display::{AnnotationStyle, DisplayResolutionGraph};
|
||||||
pub(crate) use crate::resolution::graph::ResolutionGraphNode;
|
pub(crate) use crate::resolution::output::ResolutionGraphNode;
|
||||||
pub use crate::resolution::graph::{ConflictingDistributionError, ResolutionGraph};
|
pub use crate::resolution::output::{ConflictingDistributionError, ResolverOutput};
|
||||||
pub(crate) use crate::resolution::requirements_txt::RequirementsTxtDist;
|
pub(crate) use crate::resolution::requirements_txt::RequirementsTxtDist;
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
mod graph;
|
mod output;
|
||||||
mod requirements_txt;
|
mod requirements_txt;
|
||||||
|
|
||||||
/// A pinned package with its resolved distribution and metadata. The [`ResolvedDist`] refers to a
|
/// A pinned package with its resolved distribution and metadata. The [`ResolvedDist`] refers to a
|
||||||
|
|
|
@ -35,12 +35,14 @@ use crate::{
|
||||||
|
|
||||||
pub(crate) type MarkersForDistribution = Vec<MarkerTree>;
|
pub(crate) type MarkersForDistribution = Vec<MarkerTree>;
|
||||||
|
|
||||||
/// A complete resolution graph in which every node represents a pinned package and every edge
|
/// The output of a successful resolution.
|
||||||
/// represents a dependency between two pinned packages.
|
///
|
||||||
|
/// Includes a complete resolution graph in which every node represents a pinned package and every
|
||||||
|
/// edge represents a dependency between two pinned packages.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ResolutionGraph {
|
pub struct ResolverOutput {
|
||||||
/// The underlying graph.
|
/// The underlying graph.
|
||||||
pub(crate) petgraph: Graph<ResolutionGraphNode, MarkerTree, Directed>,
|
pub(crate) graph: Graph<ResolutionGraphNode, MarkerTree, Directed>,
|
||||||
/// The range of supported Python versions.
|
/// The range of supported Python versions.
|
||||||
pub(crate) requires_python: RequiresPython,
|
pub(crate) requires_python: RequiresPython,
|
||||||
/// If the resolution had non-identical forks, store the forks in the lockfile so we can
|
/// If the resolution had non-identical forks, store the forks in the lockfile so we can
|
||||||
|
@ -92,8 +94,8 @@ struct PackageRef<'a> {
|
||||||
group: Option<&'a GroupName>,
|
group: Option<&'a GroupName>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolutionGraph {
|
impl ResolverOutput {
|
||||||
/// Create a new graph from the resolved PubGrub state.
|
/// Create a new [`ResolverOutput`] from the resolved PubGrub state.
|
||||||
pub(crate) fn from_state(
|
pub(crate) fn from_state(
|
||||||
resolutions: &[Resolution],
|
resolutions: &[Resolution],
|
||||||
requirements: &[Requirement],
|
requirements: &[Requirement],
|
||||||
|
@ -108,14 +110,14 @@ impl ResolutionGraph {
|
||||||
options: Options,
|
options: Options,
|
||||||
) -> Result<Self, ResolveError> {
|
) -> Result<Self, ResolveError> {
|
||||||
let size_guess = resolutions[0].nodes.len();
|
let size_guess = resolutions[0].nodes.len();
|
||||||
let mut petgraph: Graph<ResolutionGraphNode, MarkerTree, Directed> =
|
let mut graph: Graph<ResolutionGraphNode, MarkerTree, Directed> =
|
||||||
Graph::with_capacity(size_guess, size_guess);
|
Graph::with_capacity(size_guess, size_guess);
|
||||||
let mut inverse: FxHashMap<PackageRef, NodeIndex<u32>> =
|
let mut inverse: FxHashMap<PackageRef, NodeIndex<u32>> =
|
||||||
FxHashMap::with_capacity_and_hasher(size_guess, FxBuildHasher);
|
FxHashMap::with_capacity_and_hasher(size_guess, FxBuildHasher);
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
// Add the root node.
|
// Add the root node.
|
||||||
let root_index = petgraph.add_node(ResolutionGraphNode::Root);
|
let root_index = graph.add_node(ResolutionGraphNode::Root);
|
||||||
|
|
||||||
let mut package_markers: FxHashMap<PackageName, MarkersForDistribution> =
|
let mut package_markers: FxHashMap<PackageName, MarkersForDistribution> =
|
||||||
FxHashMap::default();
|
FxHashMap::default();
|
||||||
|
@ -140,7 +142,7 @@ impl ResolutionGraph {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Self::add_version(
|
Self::add_version(
|
||||||
&mut petgraph,
|
&mut graph,
|
||||||
&mut inverse,
|
&mut inverse,
|
||||||
&mut diagnostics,
|
&mut diagnostics,
|
||||||
preferences,
|
preferences,
|
||||||
|
@ -165,13 +167,7 @@ impl ResolutionGraph {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::add_edge(
|
Self::add_edge(&mut graph, &mut inverse, root_index, edge, marker.clone());
|
||||||
&mut petgraph,
|
|
||||||
&mut inverse,
|
|
||||||
root_index,
|
|
||||||
edge,
|
|
||||||
marker.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,24 +209,24 @@ impl ResolutionGraph {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute and apply the marker reachability.
|
// Compute and apply the marker reachability.
|
||||||
let mut reachability = marker_reachability(&petgraph, &fork_markers);
|
let mut reachability = marker_reachability(&graph, &fork_markers);
|
||||||
|
|
||||||
// Apply the reachability to the graph.
|
// Apply the reachability to the graph.
|
||||||
for index in petgraph.node_indices() {
|
for index in graph.node_indices() {
|
||||||
if let ResolutionGraphNode::Dist(dist) = &mut petgraph[index] {
|
if let ResolutionGraphNode::Dist(dist) = &mut graph[index] {
|
||||||
dist.marker = reachability.remove(&index).unwrap_or_default();
|
dist.marker = reachability.remove(&index).unwrap_or_default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard any unreachable nodes.
|
// Discard any unreachable nodes.
|
||||||
petgraph.retain_nodes(|graph, node| !graph[node].marker().is_false());
|
graph.retain_nodes(|graph, node| !graph[node].marker().is_false());
|
||||||
|
|
||||||
if matches!(resolution_strategy, ResolutionStrategy::Lowest) {
|
if matches!(resolution_strategy, ResolutionStrategy::Lowest) {
|
||||||
report_missing_lower_bounds(&petgraph, &mut diagnostics);
|
report_missing_lower_bounds(&graph, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
let graph = Self {
|
let output = Self {
|
||||||
petgraph,
|
graph,
|
||||||
requires_python,
|
requires_python,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
requirements: requirements.to_vec(),
|
requirements: requirements.to_vec(),
|
||||||
|
@ -253,7 +249,7 @@ impl ResolutionGraph {
|
||||||
// versions of the same package into the same virtualenv. ---AG
|
// versions of the same package into the same virtualenv. ---AG
|
||||||
if conflicts.is_empty() {
|
if conflicts.is_empty() {
|
||||||
#[allow(unused_mut, reason = "Used in debug_assertions below")]
|
#[allow(unused_mut, reason = "Used in debug_assertions below")]
|
||||||
let mut conflicting = graph.find_conflicting_distributions();
|
let mut conflicting = output.find_conflicting_distributions();
|
||||||
if !conflicting.is_empty() {
|
if !conflicting.is_empty() {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"found {} conflicting distributions in resolution, \
|
"found {} conflicting distributions in resolution, \
|
||||||
|
@ -275,7 +271,7 @@ impl ResolutionGraph {
|
||||||
return Err(ResolveError::ConflictingDistribution(err));
|
return Err(ResolveError::ConflictingDistribution(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(graph)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_edge(
|
fn add_edge(
|
||||||
|
@ -566,9 +562,9 @@ impl ResolutionGraph {
|
||||||
|
|
||||||
/// Returns an iterator over the distinct packages in the graph.
|
/// Returns an iterator over the distinct packages in the graph.
|
||||||
fn dists(&self) -> impl Iterator<Item = &AnnotatedDist> {
|
fn dists(&self) -> impl Iterator<Item = &AnnotatedDist> {
|
||||||
self.petgraph
|
self.graph
|
||||||
.node_indices()
|
.node_indices()
|
||||||
.filter_map(move |index| match &self.petgraph[index] {
|
.filter_map(move |index| match &self.graph[index] {
|
||||||
ResolutionGraphNode::Root => None,
|
ResolutionGraphNode::Root => None,
|
||||||
ResolutionGraphNode::Dist(dist) => Some(dist),
|
ResolutionGraphNode::Dist(dist) => Some(dist),
|
||||||
})
|
})
|
||||||
|
@ -677,8 +673,8 @@ impl ResolutionGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut seen_marker_values = IndexSet::default();
|
let mut seen_marker_values = IndexSet::default();
|
||||||
for i in self.petgraph.node_indices() {
|
for i in self.graph.node_indices() {
|
||||||
let ResolutionGraphNode::Dist(dist) = &self.petgraph[i] else {
|
let ResolutionGraphNode::Dist(dist) = &self.graph[i] else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let version_id = match dist.version_or_url() {
|
let version_id = match dist.version_or_url() {
|
||||||
|
@ -750,7 +746,7 @@ impl ResolutionGraph {
|
||||||
fn find_conflicting_distributions(&self) -> Vec<ConflictingDistributionError> {
|
fn find_conflicting_distributions(&self) -> Vec<ConflictingDistributionError> {
|
||||||
let mut name_to_markers: BTreeMap<&PackageName, Vec<(&Version, &MarkerTree)>> =
|
let mut name_to_markers: BTreeMap<&PackageName, Vec<(&Version, &MarkerTree)>> =
|
||||||
BTreeMap::new();
|
BTreeMap::new();
|
||||||
for node in self.petgraph.node_weights() {
|
for node in self.graph.node_weights() {
|
||||||
let annotated_dist = match node {
|
let annotated_dist = match node {
|
||||||
ResolutionGraphNode::Root => continue,
|
ResolutionGraphNode::Root => continue,
|
||||||
ResolutionGraphNode::Dist(ref annotated_dist) => annotated_dist,
|
ResolutionGraphNode::Dist(ref annotated_dist) => annotated_dist,
|
||||||
|
@ -818,8 +814,8 @@ impl Display for ConflictingDistributionError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ResolutionGraph> for uv_distribution_types::Resolution {
|
impl From<ResolverOutput> for uv_distribution_types::Resolution {
|
||||||
fn from(graph: ResolutionGraph) -> Self {
|
fn from(graph: ResolverOutput) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
graph
|
graph
|
||||||
.dists()
|
.dists()
|
|
@ -56,7 +56,7 @@ use crate::pubgrub::{
|
||||||
PubGrubPython,
|
PubGrubPython,
|
||||||
};
|
};
|
||||||
use crate::python_requirement::PythonRequirement;
|
use crate::python_requirement::PythonRequirement;
|
||||||
use crate::resolution::ResolutionGraph;
|
use crate::resolution::ResolverOutput;
|
||||||
use crate::resolution_mode::ResolutionStrategy;
|
use crate::resolution_mode::ResolutionStrategy;
|
||||||
pub(crate) use crate::resolver::availability::{
|
pub(crate) use crate::resolver::availability::{
|
||||||
IncompletePackage, ResolverVersion, UnavailablePackage, UnavailableReason, UnavailableVersion,
|
IncompletePackage, ResolverVersion, UnavailablePackage, UnavailableReason, UnavailableVersion,
|
||||||
|
@ -251,7 +251,7 @@ impl<Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvider>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve a set of requirements into a set of pinned versions.
|
/// Resolve a set of requirements into a set of pinned versions.
|
||||||
pub async fn resolve(self) -> Result<ResolutionGraph, ResolveError> {
|
pub async fn resolve(self) -> Result<ResolverOutput, ResolveError> {
|
||||||
let state = Arc::new(self.state);
|
let state = Arc::new(self.state);
|
||||||
let provider = Arc::new(self.provider);
|
let provider = Arc::new(self.provider);
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
fn solve(
|
fn solve(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
request_sink: Sender<Request>,
|
request_sink: Sender<Request>,
|
||||||
) -> Result<ResolutionGraph, ResolveError> {
|
) -> Result<ResolverOutput, ResolveError> {
|
||||||
debug!(
|
debug!(
|
||||||
"Solving with installed Python version: {}",
|
"Solving with installed Python version: {}",
|
||||||
self.python_requirement.exact()
|
self.python_requirement.exact()
|
||||||
|
@ -598,7 +598,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
for resolution in &resolutions {
|
for resolution in &resolutions {
|
||||||
Self::trace_resolution(resolution);
|
Self::trace_resolution(resolution);
|
||||||
}
|
}
|
||||||
ResolutionGraph::from_state(
|
ResolverOutput::from_state(
|
||||||
&resolutions,
|
&resolutions,
|
||||||
&self.requirements,
|
&self.requirements,
|
||||||
&self.constraints,
|
&self.constraints,
|
||||||
|
|
|
@ -37,7 +37,7 @@ use uv_requirements::{
|
||||||
};
|
};
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
DependencyMode, Exclusions, FlatIndex, InMemoryIndex, Manifest, Options, Preference,
|
DependencyMode, Exclusions, FlatIndex, InMemoryIndex, Manifest, Options, Preference,
|
||||||
Preferences, PythonRequirement, ResolutionGraph, Resolver, ResolverEnvironment,
|
Preferences, PythonRequirement, Resolver, ResolverEnvironment, ResolverOutput,
|
||||||
};
|
};
|
||||||
use uv_types::{HashStrategy, InFlight, InstalledPackagesProvider};
|
use uv_types::{HashStrategy, InFlight, InstalledPackagesProvider};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
@ -113,7 +113,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
|
||||||
options: Options,
|
options: Options,
|
||||||
logger: Box<dyn ResolveLogger>,
|
logger: Box<dyn ResolveLogger>,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ResolutionGraph, Error> {
|
) -> Result<ResolverOutput, Error> {
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
// Resolve the requirements from the provided sources.
|
// Resolve the requirements from the provided sources.
|
||||||
|
|
|
@ -58,7 +58,8 @@ impl CachedEnvironment {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve the requirements with the interpreter.
|
// Resolve the requirements with the interpreter.
|
||||||
let graph = resolve_environment(
|
let resolution = Resolution::from(
|
||||||
|
resolve_environment(
|
||||||
spec,
|
spec,
|
||||||
&interpreter,
|
&interpreter,
|
||||||
settings.as_ref().into(),
|
settings.as_ref().into(),
|
||||||
|
@ -71,8 +72,8 @@ impl CachedEnvironment {
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?,
|
||||||
let resolution = Resolution::from(graph);
|
);
|
||||||
|
|
||||||
// Hash the resolution by hashing the generated lockfile.
|
// Hash the resolution by hashing the generated lockfile.
|
||||||
// TODO(charlie): If the resolution contains any mutable metadata (like a path or URL
|
// TODO(charlie): If the resolution contains any mutable metadata (like a path or URL
|
||||||
|
|
|
@ -659,7 +659,7 @@ async fn do_lock(
|
||||||
.relative_to(workspace)?;
|
.relative_to(workspace)?;
|
||||||
|
|
||||||
let previous = existing_lock.map(ValidatedLock::into_lock);
|
let previous = existing_lock.map(ValidatedLock::into_lock);
|
||||||
let lock = Lock::from_resolution_graph(&resolution, workspace.install_path())?
|
let lock = Lock::from_resolution(&resolution, workspace.install_path())?
|
||||||
.with_manifest(manifest)
|
.with_manifest(manifest)
|
||||||
.with_conflicts(workspace.conflicts())
|
.with_conflicts(workspace.conflicts())
|
||||||
.with_supported_environments(
|
.with_supported_environments(
|
||||||
|
|
|
@ -31,8 +31,8 @@ use uv_python::{
|
||||||
use uv_requirements::upgrade::{read_lock_requirements, LockedRequirements};
|
use uv_requirements::upgrade::{read_lock_requirements, LockedRequirements};
|
||||||
use uv_requirements::{NamedRequirementsResolver, RequirementsSpecification};
|
use uv_requirements::{NamedRequirementsResolver, RequirementsSpecification};
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython, ResolutionGraph,
|
FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython, ResolverEnvironment,
|
||||||
ResolverEnvironment,
|
ResolverOutput,
|
||||||
};
|
};
|
||||||
use uv_scripts::Pep723Item;
|
use uv_scripts::Pep723Item;
|
||||||
use uv_settings::PythonInstallMirrors;
|
use uv_settings::PythonInstallMirrors;
|
||||||
|
@ -955,7 +955,7 @@ impl<'lock> EnvironmentSpecification<'lock> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run dependency resolution for an interpreter, returning the [`ResolutionGraph`].
|
/// Run dependency resolution for an interpreter, returning the [`ResolverOutput`].
|
||||||
pub(crate) async fn resolve_environment<'a>(
|
pub(crate) async fn resolve_environment<'a>(
|
||||||
spec: EnvironmentSpecification<'_>,
|
spec: EnvironmentSpecification<'_>,
|
||||||
interpreter: &Interpreter,
|
interpreter: &Interpreter,
|
||||||
|
@ -968,7 +968,7 @@ pub(crate) async fn resolve_environment<'a>(
|
||||||
allow_insecure_host: &[TrustedHost],
|
allow_insecure_host: &[TrustedHost],
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ResolutionGraph, ProjectError> {
|
) -> Result<ResolverOutput, ProjectError> {
|
||||||
warn_on_requirements_txt_setting(&spec.requirements, settings);
|
warn_on_requirements_txt_setting(&spec.requirements, settings);
|
||||||
|
|
||||||
let ResolverSettingsRef {
|
let ResolverSettingsRef {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue