mirror of
				https://github.com/astral-sh/uv.git
				synced 2025-10-31 12:06:13 +00:00 
			
		
		
		
	Arc-wrap PubGrubPackage for cheap cloning in pubgrub (#3688)
				
					
				
			Pubgrub stores incompatibilities as (package name, version range) tuples, meaning it needs to clone the package name for each incompatibility, and each non-borrowed operation on incompatibilities. https://github.com/astral-sh/uv/pull/3673 made me realize that `PubGrubPackage` has gotten large (expensive to copy), so like `Version` and other structs, i've added an `Arc` wrapper around it. It's a pity clippy forbids `.deref()`, it's less opaque than `&**` and has IDE support (clicking on `.deref()` jumps to the right impl). ## Benchmarks It looks like this matters most for complex resolutions which, i assume because they carry larger `PubGrubPackageInner::Package` and `PubGrubPackageInner::Extra` types. ```bash hyperfine --warmup 5 "./uv-main pip compile -q ./scripts/requirements/jupyter.in" "./uv-branch pip compile -q ./scripts/requirements/jupyter.in" hyperfine --warmup 5 "./uv-main pip compile -q ./scripts/requirements/airflow.in" "./uv-branch pip compile -q ./scripts/requirements/airflow.in" hyperfine --warmup 5 "./uv-main pip compile -q ./scripts/requirements/boto3.in" "./uv-branch pip compile -q ./scripts/requirements/boto3.in" ``` ``` Benchmark 1: ./uv-main pip compile -q ./scripts/requirements/jupyter.in Time (mean ± σ): 18.2 ms ± 1.6 ms [User: 14.4 ms, System: 26.0 ms] Range (min … max): 15.8 ms … 22.5 ms 181 runs Benchmark 2: ./uv-branch pip compile -q ./scripts/requirements/jupyter.in Time (mean ± σ): 17.8 ms ± 1.4 ms [User: 14.4 ms, System: 25.3 ms] Range (min … max): 15.4 ms … 23.1 ms 159 runs Summary ./uv-branch pip compile -q ./scripts/requirements/jupyter.in ran 1.02 ± 0.12 times faster than ./uv-main pip compile -q ./scripts/requirements/jupyter.in ``` ``` Benchmark 1: ./uv-main pip compile -q ./scripts/requirements/airflow.in Time (mean ± σ): 153.7 ms ± 3.5 ms [User: 165.2 ms, System: 157.6 ms] Range (min … max): 150.4 ms … 163.0 ms 19 runs Benchmark 2: ./uv-branch pip compile -q ./scripts/requirements/airflow.in Time (mean ± σ): 123.9 ms ± 4.6 ms [User: 152.4 ms, System: 133.8 ms] Range (min … max): 118.4 ms … 138.1 ms 24 runs Summary ./uv-branch pip compile -q ./scripts/requirements/airflow.in ran 1.24 ± 0.05 times faster than ./uv-main pip compile -q ./scripts/requirements/airflow.in ``` ``` Benchmark 1: ./uv-main pip compile -q ./scripts/requirements/boto3.in Time (mean ± σ): 327.0 ms ± 3.8 ms [User: 344.5 ms, System: 71.6 ms] Range (min … max): 322.7 ms … 334.6 ms 10 runs Benchmark 2: ./uv-branch pip compile -q ./scripts/requirements/boto3.in Time (mean ± σ): 311.2 ms ± 3.1 ms [User: 339.3 ms, System: 63.1 ms] Range (min … max): 307.8 ms … 317.0 ms 10 runs Summary ./uv-branch pip compile -q ./scripts/requirements/boto3.in ran 1.05 ± 0.02 times faster than ./uv-main pip compile -q ./scripts/requirements/boto3.in ``` <!-- Thank you for contributing to uv! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? -->
This commit is contained in:
		
							parent
							
								
									fbae55019e
								
							
						
					
					
						commit
						76418f5bdf
					
				
					 10 changed files with 159 additions and 122 deletions
				
			
		|  | @ -16,7 +16,7 @@ use uv_normalize::PackageName; | |||
| 
 | ||||
| use crate::candidate_selector::CandidateSelector; | ||||
| use crate::dependency_provider::UvDependencyProvider; | ||||
| use crate::pubgrub::{PubGrubPackage, PubGrubPython, PubGrubReportFormatter}; | ||||
| use crate::pubgrub::{PubGrubPackage, PubGrubPackageInner, PubGrubPython, PubGrubReportFormatter}; | ||||
| use crate::python_requirement::PythonRequirement; | ||||
| use crate::resolver::{ | ||||
|     FxOnceMap, IncompletePackage, UnavailablePackage, UnavailableReason, VersionsResponse, | ||||
|  | @ -114,7 +114,7 @@ impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ResolveError { | |||
| } | ||||
| 
 | ||||
| /// Given a [`DerivationTree`], collapse any [`External::FromDependencyOf`] incompatibilities
 | ||||
| /// wrap an [`PubGrubPackage::Extra`] package.
 | ||||
| /// wrap an [`PubGrubPackageInner::Extra`] package.
 | ||||
| fn collapse_extra_proxies( | ||||
|     derivation_tree: &mut DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>, | ||||
| ) { | ||||
|  | @ -126,22 +126,16 @@ fn collapse_extra_proxies( | |||
|                 Arc::make_mut(&mut derived.cause2), | ||||
|             ) { | ||||
|                 ( | ||||
|                     DerivationTree::External(External::FromDependencyOf( | ||||
|                         PubGrubPackage::Extra { .. }, | ||||
|                         .., | ||||
|                     )), | ||||
|                     DerivationTree::External(External::FromDependencyOf(package, ..)), | ||||
|                     ref mut cause, | ||||
|                 ) => { | ||||
|                 ) if matches!(&**package, PubGrubPackageInner::Extra { .. }) => { | ||||
|                     collapse_extra_proxies(cause); | ||||
|                     *derivation_tree = cause.clone(); | ||||
|                 } | ||||
|                 ( | ||||
|                     ref mut cause, | ||||
|                     DerivationTree::External(External::FromDependencyOf( | ||||
|                         PubGrubPackage::Extra { .. }, | ||||
|                         .., | ||||
|                     )), | ||||
|                 ) => { | ||||
|                     DerivationTree::External(External::FromDependencyOf(package, ..)), | ||||
|                 ) if matches!(&**package, PubGrubPackageInner::Extra { .. }) => { | ||||
|                     collapse_extra_proxies(cause); | ||||
|                     *derivation_tree = cause.clone(); | ||||
|                 } | ||||
|  | @ -241,22 +235,22 @@ impl NoSolutionError { | |||
|     ) -> Self { | ||||
|         let mut available_versions = IndexMap::default(); | ||||
|         for package in self.derivation_tree.packages() { | ||||
|             match package { | ||||
|                 PubGrubPackage::Root(_) => {} | ||||
|                 PubGrubPackage::Python(PubGrubPython::Installed) => { | ||||
|             match &**package { | ||||
|                 PubGrubPackageInner::Root(_) => {} | ||||
|                 PubGrubPackageInner::Python(PubGrubPython::Installed) => { | ||||
|                     available_versions.insert( | ||||
|                         package.clone(), | ||||
|                         BTreeSet::from([python_requirement.installed().deref().clone()]), | ||||
|                     ); | ||||
|                 } | ||||
|                 PubGrubPackage::Python(PubGrubPython::Target) => { | ||||
|                 PubGrubPackageInner::Python(PubGrubPython::Target) => { | ||||
|                     available_versions.insert( | ||||
|                         package.clone(), | ||||
|                         BTreeSet::from([python_requirement.target().deref().clone()]), | ||||
|                     ); | ||||
|                 } | ||||
|                 PubGrubPackage::Extra { .. } => {} | ||||
|                 PubGrubPackage::Package { name, .. } => { | ||||
|                 PubGrubPackageInner::Extra { .. } => {} | ||||
|                 PubGrubPackageInner::Package { name, .. } => { | ||||
|                     // Avoid including available versions for packages that exist in the derivation
 | ||||
|                     // tree, but were never visited during resolution. We _may_ have metadata for
 | ||||
|                     // these packages, but it's non-deterministic, and omitting them ensures that
 | ||||
|  | @ -304,7 +298,7 @@ impl NoSolutionError { | |||
|     ) -> Self { | ||||
|         let mut new = FxHashMap::default(); | ||||
|         for package in self.derivation_tree.packages() { | ||||
|             if let PubGrubPackage::Package { name, .. } = package { | ||||
|             if let PubGrubPackageInner::Package { name, .. } = &**package { | ||||
|                 if let Some(reason) = unavailable_packages.get(name) { | ||||
|                     new.insert(name.clone(), reason.clone()); | ||||
|                 } | ||||
|  | @ -322,7 +316,7 @@ impl NoSolutionError { | |||
|     ) -> Self { | ||||
|         let mut new = FxHashMap::default(); | ||||
|         for package in self.derivation_tree.packages() { | ||||
|             if let PubGrubPackage::Package { name, .. } = package { | ||||
|             if let PubGrubPackageInner::Package { name, .. } = &**package { | ||||
|                 if let Some(versions) = incomplete_packages.get(name) { | ||||
|                     for entry in versions.iter() { | ||||
|                         let (version, reason) = entry.pair(); | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ use uv_configuration::{Constraints, Overrides}; | |||
| use uv_normalize::{ExtraName, PackageName}; | ||||
| 
 | ||||
| use crate::pubgrub::specifier::PubGrubSpecifier; | ||||
| use crate::pubgrub::PubGrubPackage; | ||||
| use crate::pubgrub::{PubGrubPackage, PubGrubPackageInner}; | ||||
| use crate::resolver::{Locals, Urls}; | ||||
| use crate::ResolveError; | ||||
| 
 | ||||
|  | @ -102,8 +102,8 @@ fn add_requirements( | |||
|         })) { | ||||
|             let PubGrubRequirement { package, version } = result?; | ||||
| 
 | ||||
|             match &package { | ||||
|                 PubGrubPackage::Package { name, .. } => { | ||||
|             match &*package { | ||||
|                 PubGrubPackageInner::Package { name, .. } => { | ||||
|                     // Detect self-dependencies.
 | ||||
|                     if source_name.is_some_and(|source_name| source_name == name) { | ||||
|                         warn!("{name} has a dependency on itself"); | ||||
|  | @ -112,7 +112,7 @@ fn add_requirements( | |||
| 
 | ||||
|                     dependencies.push((package.clone(), version.clone())); | ||||
|                 } | ||||
|                 PubGrubPackage::Extra { name, extra, .. } => { | ||||
|                 PubGrubPackageInner::Extra { name, extra, .. } => { | ||||
|                     // Recursively add the dependencies of the current package (e.g., `black` depending on
 | ||||
|                     // `black[colorama]`).
 | ||||
|                     if source_name.is_some_and(|source_name| source_name == name) { | ||||
|  | @ -158,7 +158,7 @@ fn add_requirements( | |||
|                     PubGrubRequirement::from_constraint(constraint, urls, locals)?; | ||||
| 
 | ||||
|                 // Ignore self-dependencies.
 | ||||
|                 if let PubGrubPackage::Package { name, .. } = &package { | ||||
|                 if let PubGrubPackageInner::Package { name, .. } = &*package { | ||||
|                     // Detect self-dependencies.
 | ||||
|                     if source_name.is_some_and(|source_name| source_name == name) { | ||||
|                         warn!("{name} has a dependency on itself"); | ||||
|  | @ -249,12 +249,12 @@ impl PubGrubRequirement { | |||
|                 } | ||||
| 
 | ||||
|                 Ok(Self { | ||||
|                     package: PubGrubPackage::Package { | ||||
|                     package: PubGrubPackage::from(PubGrubPackageInner::Package { | ||||
|                         name: requirement.name.clone(), | ||||
|                         extra, | ||||
|                         marker: None, | ||||
|                         url: Some(expected.clone()), | ||||
|                     }, | ||||
|                     }), | ||||
|                     version: Range::full(), | ||||
|                 }) | ||||
|             } | ||||
|  | @ -275,12 +275,12 @@ impl PubGrubRequirement { | |||
|                 } | ||||
| 
 | ||||
|                 Ok(Self { | ||||
|                     package: PubGrubPackage::Package { | ||||
|                     package: PubGrubPackage::from(PubGrubPackageInner::Package { | ||||
|                         name: requirement.name.clone(), | ||||
|                         extra, | ||||
|                         marker: None, | ||||
|                         url: Some(expected.clone()), | ||||
|                     }, | ||||
|                     }), | ||||
|                     version: Range::full(), | ||||
|                 }) | ||||
|             } | ||||
|  | @ -301,12 +301,12 @@ impl PubGrubRequirement { | |||
|                 } | ||||
| 
 | ||||
|                 Ok(Self { | ||||
|                     package: PubGrubPackage::Package { | ||||
|                     package: PubGrubPackage::from(PubGrubPackageInner::Package { | ||||
|                         name: requirement.name.clone(), | ||||
|                         extra, | ||||
|                         marker: None, | ||||
|                         url: Some(expected.clone()), | ||||
|                     }, | ||||
|                     }), | ||||
|                     version: Range::full(), | ||||
|                 }) | ||||
|             } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| pub(crate) use crate::pubgrub::dependencies::{PubGrubDependencies, PubGrubRequirement}; | ||||
| pub(crate) use crate::pubgrub::distribution::PubGrubDistribution; | ||||
| pub(crate) use crate::pubgrub::package::{PubGrubPackage, PubGrubPython}; | ||||
| pub(crate) use crate::pubgrub::package::{PubGrubPackage, PubGrubPackageInner, PubGrubPython}; | ||||
| pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority}; | ||||
| pub(crate) use crate::pubgrub::report::PubGrubReportFormatter; | ||||
| pub(crate) use crate::pubgrub::specifier::PubGrubSpecifier; | ||||
|  |  | |||
|  | @ -1,9 +1,36 @@ | |||
| use distribution_types::VerbatimParsedUrl; | ||||
| use pep508_rs::MarkerTree; | ||||
| use std::fmt::{Display, Formatter}; | ||||
| use std::ops::Deref; | ||||
| use std::sync::Arc; | ||||
| use uv_normalize::{ExtraName, PackageName}; | ||||
| 
 | ||||
| use crate::resolver::Urls; | ||||
| 
 | ||||
| /// [`Arc`] wrapper around [`PubGrubPackageInner`] to make cloning (inside PubGrub) cheap.
 | ||||
| #[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] | ||||
| pub struct PubGrubPackage(Arc<PubGrubPackageInner>); | ||||
| 
 | ||||
| impl Deref for PubGrubPackage { | ||||
|     type Target = PubGrubPackageInner; | ||||
| 
 | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for PubGrubPackage { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         Display::fmt(&self.0, f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<PubGrubPackageInner> for PubGrubPackage { | ||||
|     fn from(package: PubGrubPackageInner) -> Self { | ||||
|         Self(Arc::new(package)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A PubGrub-compatible wrapper around a "Python package", with two notable characteristics:
 | ||||
| ///
 | ||||
| /// 1. Includes a [`PubGrubPackage::Root`] variant, to satisfy PubGrub's requirement that a
 | ||||
|  | @ -12,7 +39,7 @@ use crate::resolver::Urls; | |||
| ///    package (e.g., `black[colorama]`), and mark it as a dependency of the real package (e.g.,
 | ||||
| ///    `black`). We then discard the virtual packages at the end of the resolution process.
 | ||||
| #[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] | ||||
| pub enum PubGrubPackage { | ||||
| pub enum PubGrubPackageInner { | ||||
|     /// The root package, which is used to start the resolution process.
 | ||||
|     Root(Option<PackageName>), | ||||
|     /// A Python version.
 | ||||
|  | @ -91,19 +118,19 @@ impl PubGrubPackage { | |||
|     ) -> Self { | ||||
|         let url = urls.get(&name).cloned(); | ||||
|         if let Some(extra) = extra { | ||||
|             Self::Extra { | ||||
|             Self(Arc::new(PubGrubPackageInner::Extra { | ||||
|                 name, | ||||
|                 extra, | ||||
|                 marker, | ||||
|                 url, | ||||
|             } | ||||
|             })) | ||||
|         } else { | ||||
|             Self::Package { | ||||
|             Self(Arc::new(PubGrubPackageInner::Package { | ||||
|                 name, | ||||
|                 extra, | ||||
|                 marker, | ||||
|                 url, | ||||
|             } | ||||
|             })) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -116,7 +143,7 @@ pub enum PubGrubPython { | |||
|     Target, | ||||
| } | ||||
| 
 | ||||
| impl std::fmt::Display for PubGrubPackage { | ||||
| impl std::fmt::Display for PubGrubPackageInner { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Root(name) => { | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ use pep440_rs::Version; | |||
| use uv_normalize::PackageName; | ||||
| 
 | ||||
| use crate::pubgrub::package::PubGrubPackage; | ||||
| use crate::pubgrub::PubGrubPackageInner; | ||||
| 
 | ||||
| /// A prioritization map to guide the PubGrub resolution process.
 | ||||
| ///
 | ||||
|  | @ -24,14 +25,14 @@ impl PubGrubPriorities { | |||
|     /// Add a [`PubGrubPackage`] to the priority map.
 | ||||
|     pub(crate) fn insert(&mut self, package: &PubGrubPackage, version: &Range<Version>) { | ||||
|         let next = self.0.len(); | ||||
|         match package { | ||||
|             PubGrubPackage::Root(_) => {} | ||||
|             PubGrubPackage::Python(_) => {} | ||||
|         match &**package { | ||||
|             PubGrubPackageInner::Root(_) => {} | ||||
|             PubGrubPackageInner::Python(_) => {} | ||||
| 
 | ||||
|             PubGrubPackage::Extra { | ||||
|             PubGrubPackageInner::Extra { | ||||
|                 name, url: None, .. | ||||
|             } | ||||
|             | PubGrubPackage::Package { | ||||
|             | PubGrubPackageInner::Package { | ||||
|                 name, url: None, .. | ||||
|             } => { | ||||
|                 match self.0.entry(name.clone()) { | ||||
|  | @ -66,10 +67,10 @@ impl PubGrubPriorities { | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             PubGrubPackage::Extra { | ||||
|             PubGrubPackageInner::Extra { | ||||
|                 name, url: Some(_), .. | ||||
|             } | ||||
|             | PubGrubPackage::Package { | ||||
|             | PubGrubPackageInner::Package { | ||||
|                 name, url: Some(_), .. | ||||
|             } => { | ||||
|                 match self.0.entry(name.clone()) { | ||||
|  | @ -101,11 +102,11 @@ impl PubGrubPriorities { | |||
| 
 | ||||
|     /// Return the [`PubGrubPriority`] of the given package, if it exists.
 | ||||
|     pub(crate) fn get(&self, package: &PubGrubPackage) -> Option<PubGrubPriority> { | ||||
|         match package { | ||||
|             PubGrubPackage::Root(_) => Some(PubGrubPriority::Root), | ||||
|             PubGrubPackage::Python(_) => Some(PubGrubPriority::Root), | ||||
|             PubGrubPackage::Extra { name, .. } => self.0.get(name).copied(), | ||||
|             PubGrubPackage::Package { name, .. } => self.0.get(name).copied(), | ||||
|         match &**package { | ||||
|             PubGrubPackageInner::Root(_) => Some(PubGrubPriority::Root), | ||||
|             PubGrubPackageInner::Python(_) => Some(PubGrubPriority::Root), | ||||
|             PubGrubPackageInner::Extra { name, .. } => self.0.get(name).copied(), | ||||
|             PubGrubPackageInner::Package { name, .. } => self.0.get(name).copied(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ use crate::candidate_selector::CandidateSelector; | |||
| use crate::python_requirement::PythonRequirement; | ||||
| use crate::resolver::{IncompletePackage, UnavailablePackage, UnavailableReason}; | ||||
| 
 | ||||
| use super::PubGrubPackage; | ||||
| use super::{PubGrubPackage, PubGrubPackageInner}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct PubGrubReportFormatter<'a> { | ||||
|  | @ -44,7 +44,7 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason> | |||
|                 format!("we are solving dependencies of {package} {version}") | ||||
|             } | ||||
|             External::NoVersions(package, set) => { | ||||
|                 if matches!(package, PubGrubPackage::Python(_)) { | ||||
|                 if matches!(&**package, PubGrubPackageInner::Python(_)) { | ||||
|                     if let Some(python) = self.python_requirement { | ||||
|                         if python.target() == python.installed() { | ||||
|                             // Simple case, the installed version is the same as the target version
 | ||||
|  | @ -107,11 +107,11 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason> | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             External::Custom(package, set, reason) => match package { | ||||
|                 PubGrubPackage::Root(Some(name)) => { | ||||
|             External::Custom(package, set, reason) => match &**package { | ||||
|                 PubGrubPackageInner::Root(Some(name)) => { | ||||
|                     format!("{name} cannot be used because {reason}") | ||||
|                 } | ||||
|                 PubGrubPackage::Root(None) => { | ||||
|                 PubGrubPackageInner::Root(None) => { | ||||
|                     format!("your requirements cannot be used because {reason}") | ||||
|                 } | ||||
|                 _ => match reason { | ||||
|  | @ -131,12 +131,12 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason> | |||
|             External::FromDependencyOf(package, package_set, dependency, dependency_set) => { | ||||
|                 let package_set = self.simplify_set(package_set, package); | ||||
|                 let dependency_set = self.simplify_set(dependency_set, dependency); | ||||
|                 match package { | ||||
|                     PubGrubPackage::Root(Some(name)) => format!( | ||||
|                 match &**package { | ||||
|                     PubGrubPackageInner::Root(Some(name)) => format!( | ||||
|                         "{name} depends on {}", | ||||
|                         PackageRange::dependency(dependency, &dependency_set) | ||||
|                     ), | ||||
|                     PubGrubPackage::Root(None) => format!( | ||||
|                     PubGrubPackageInner::Root(None) => format!( | ||||
|                         "you require {}", | ||||
|                         PackageRange::dependency(dependency, &dependency_set) | ||||
|                     ), | ||||
|  | @ -157,15 +157,22 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason> | |||
|         // by package first.
 | ||||
|         terms_vec.sort_by(|&(pkg1, _), &(pkg2, _)| pkg1.cmp(pkg2)); | ||||
|         match terms_vec.as_slice() { | ||||
|             [] | [(PubGrubPackage::Root(_), _)] => "the requirements are unsatisfiable".into(), | ||||
|             [(package @ PubGrubPackage::Package { .. }, Term::Positive(range))] => { | ||||
|             [] => "the requirements are unsatisfiable".into(), | ||||
|             [(root, _)] if matches!(&**(*root), PubGrubPackageInner::Root(_)) => { | ||||
|                 "the requirements are unsatisfiable".into() | ||||
|             } | ||||
|             [(package, Term::Positive(range))] | ||||
|                 if matches!(&**(*package), PubGrubPackageInner::Package { .. }) => | ||||
|             { | ||||
|                 let range = self.simplify_set(range, package); | ||||
|                 format!( | ||||
|                     "{} cannot be used", | ||||
|                     PackageRange::compatibility(package, &range) | ||||
|                 ) | ||||
|             } | ||||
|             [(package @ PubGrubPackage::Package { .. }, Term::Negative(range))] => { | ||||
|             [(package, Term::Negative(range))] | ||||
|                 if matches!(&**(*package), PubGrubPackageInner::Package { .. }) => | ||||
|             { | ||||
|                 let range = self.simplify_set(range, package); | ||||
|                 format!( | ||||
|                     "{} must be used", | ||||
|  | @ -339,13 +346,13 @@ impl PubGrubReportFormatter<'_> { | |||
|                 let dependency_set2 = self.simplify_set(dependency_set2, dependency2); | ||||
|                 let dependency2 = PackageRange::dependency(dependency2, &dependency_set2); | ||||
| 
 | ||||
|                 match package1 { | ||||
|                     PubGrubPackage::Root(Some(name)) => format!( | ||||
|                 match &**package1 { | ||||
|                     PubGrubPackageInner::Root(Some(name)) => format!( | ||||
|                         "{name} depends on {}and {}", | ||||
|                         Padded::new("", &dependency1, " "), | ||||
|                         dependency2, | ||||
|                     ), | ||||
|                     PubGrubPackage::Root(None) => format!( | ||||
|                     PubGrubPackageInner::Root(None) => format!( | ||||
|                         "you require {}and {}", | ||||
|                         Padded::new("", &dependency1, " "), | ||||
|                         dependency2, | ||||
|  | @ -402,7 +409,7 @@ impl PubGrubReportFormatter<'_> { | |||
|     ) -> IndexSet<PubGrubHint> { | ||||
|         /// Returns `true` if pre-releases were allowed for a package.
 | ||||
|         fn allowed_prerelease(package: &PubGrubPackage, selector: &CandidateSelector) -> bool { | ||||
|             let PubGrubPackage::Package { name, .. } = package else { | ||||
|             let PubGrubPackageInner::Package { name, .. } = &**package else { | ||||
|                 return false; | ||||
|             }; | ||||
|             selector.prerelease_strategy().allows(name) | ||||
|  | @ -460,7 +467,7 @@ impl PubGrubReportFormatter<'_> { | |||
|                         let no_find_links = | ||||
|                             index_locations.flat_index().peekable().peek().is_none(); | ||||
| 
 | ||||
|                         if let PubGrubPackage::Package { name, .. } = package { | ||||
|                         if let PubGrubPackageInner::Package { name, .. } = &**package { | ||||
|                             // Add hints due to the package being entirely unavailable.
 | ||||
|                             match unavailable_packages.get(name) { | ||||
|                                 Some(UnavailablePackage::NoIndex) => { | ||||
|  | @ -970,9 +977,9 @@ impl<T: std::fmt::Display> std::fmt::Display for Padded<'_, T> { | |||
| } | ||||
| 
 | ||||
| fn fmt_package(package: &PubGrubPackage) -> String { | ||||
|     match package { | ||||
|         PubGrubPackage::Root(Some(name)) => name.to_string(), | ||||
|         PubGrubPackage::Root(None) => "you require".to_string(), | ||||
|     match &**package { | ||||
|         PubGrubPackageInner::Root(Some(name)) => name.to_string(), | ||||
|         PubGrubPackageInner::Root(None) => "you require".to_string(), | ||||
|         _ => format!("{package}"), | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ use crate::dependency_provider::UvDependencyProvider; | |||
| use crate::editables::Editables; | ||||
| use crate::pins::FilePins; | ||||
| use crate::preferences::Preferences; | ||||
| use crate::pubgrub::{PubGrubDistribution, PubGrubPackage}; | ||||
| use crate::pubgrub::{PubGrubDistribution, PubGrubPackageInner}; | ||||
| use crate::redirect::url_to_precise; | ||||
| use crate::resolution::AnnotatedDist; | ||||
| use crate::resolver::FxOnceMap; | ||||
|  | @ -55,8 +55,8 @@ impl ResolutionGraph { | |||
|         let mut extras = FxHashMap::default(); | ||||
|         let mut diagnostics = Vec::new(); | ||||
|         for (package, version) in selection { | ||||
|             match package { | ||||
|                 PubGrubPackage::Package { | ||||
|             match &**package { | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, | ||||
|                     extra: Some(extra), | ||||
|                     marker: None, | ||||
|  | @ -95,7 +95,7 @@ impl ResolutionGraph { | |||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 PubGrubPackage::Package { | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, | ||||
|                     extra: Some(extra), | ||||
|                     marker: None, | ||||
|  | @ -159,8 +159,8 @@ impl ResolutionGraph { | |||
|             FxHashMap::with_capacity_and_hasher(selection.len(), BuildHasherDefault::default()); | ||||
| 
 | ||||
|         for (package, version) in selection { | ||||
|             match package { | ||||
|                 PubGrubPackage::Package { | ||||
|             match &**package { | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, | ||||
|                     extra: None, | ||||
|                     marker: None, | ||||
|  | @ -229,7 +229,7 @@ impl ResolutionGraph { | |||
|                     }); | ||||
|                     inverse.insert(name, index); | ||||
|                 } | ||||
|                 PubGrubPackage::Package { | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, | ||||
|                     extra: None, | ||||
|                     marker: None, | ||||
|  | @ -328,16 +328,16 @@ impl ResolutionGraph { | |||
|                         continue; | ||||
|                     } | ||||
| 
 | ||||
|                     let PubGrubPackage::Package { | ||||
|                     let PubGrubPackageInner::Package { | ||||
|                         name: self_name, .. | ||||
|                     } = self_package | ||||
|                     } = &**self_package | ||||
|                     else { | ||||
|                         continue; | ||||
|                     }; | ||||
|                     let PubGrubPackage::Package { | ||||
|                     let PubGrubPackageInner::Package { | ||||
|                         name: dependency_name, | ||||
|                         .. | ||||
|                     } = dependency_package | ||||
|                     } = &**dependency_package | ||||
|                     else { | ||||
|                         continue; | ||||
|                     }; | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ use distribution_types::DistributionMetadata; | |||
| use pep440_rs::Version; | ||||
| 
 | ||||
| use crate::candidate_selector::{CandidateDist, CandidateSelector}; | ||||
| use crate::pubgrub::PubGrubPackage; | ||||
| use crate::pubgrub::{PubGrubPackage, PubGrubPackageInner}; | ||||
| use crate::resolver::Request; | ||||
| use crate::{InMemoryIndex, ResolveError, VersionsResponse}; | ||||
| 
 | ||||
|  | @ -53,12 +53,12 @@ impl BatchPrefetcher { | |||
|         index: &InMemoryIndex, | ||||
|         selector: &CandidateSelector, | ||||
|     ) -> anyhow::Result<(), ResolveError> { | ||||
|         let PubGrubPackage::Package { | ||||
|         let PubGrubPackageInner::Package { | ||||
|             name, | ||||
|             extra: None, | ||||
|             marker: None, | ||||
|             url: None, | ||||
|         } = &next | ||||
|         } = &**next | ||||
|         else { | ||||
|             return Ok(()); | ||||
|         }; | ||||
|  | @ -163,7 +163,10 @@ impl BatchPrefetcher { | |||
|     /// Each time we tried a version for a package, we register that here.
 | ||||
|     pub(crate) fn version_tried(&mut self, package: PubGrubPackage) { | ||||
|         // Only track base packages, no virtual packages from extras.
 | ||||
|         if matches!(package, PubGrubPackage::Package { extra: Some(_), .. }) { | ||||
|         if matches!( | ||||
|             &*package, | ||||
|             PubGrubPackageInner::Package { extra: Some(_), .. } | ||||
|         ) { | ||||
|             return; | ||||
|         } | ||||
|         *self.tried_versions.entry(package).or_default() += 1; | ||||
|  |  | |||
|  | @ -43,8 +43,8 @@ use crate::manifest::Manifest; | |||
| use crate::pins::FilePins; | ||||
| use crate::preferences::Preferences; | ||||
| use crate::pubgrub::{ | ||||
|     PubGrubDependencies, PubGrubDistribution, PubGrubPackage, PubGrubPriorities, PubGrubPython, | ||||
|     PubGrubRequirement, PubGrubSpecifier, | ||||
|     PubGrubDependencies, PubGrubDistribution, PubGrubPackage, PubGrubPackageInner, | ||||
|     PubGrubPriorities, PubGrubPython, PubGrubRequirement, PubGrubSpecifier, | ||||
| }; | ||||
| use crate::python_requirement::PythonRequirement; | ||||
| use crate::resolution::ResolutionGraph; | ||||
|  | @ -401,7 +401,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|         visited: &mut FxHashSet<PackageName>, | ||||
|         request_sink: Sender<Request>, | ||||
|     ) -> Result<ResolutionGraph, ResolveError> { | ||||
|         let root = PubGrubPackage::Root(self.project.clone()); | ||||
|         let root = PubGrubPackage::from(PubGrubPackageInner::Root(self.project.clone())); | ||||
|         let mut prefetcher = BatchPrefetcher::default(); | ||||
|         let mut state = SolveState { | ||||
|             pubgrub: State::init(root.clone(), MIN_VERSION.clone()), | ||||
|  | @ -480,7 +480,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                         .expect("a package was chosen but we don't have a term."); | ||||
| 
 | ||||
|                     // Check if the decision was due to the package being unavailable
 | ||||
|                     if let PubGrubPackage::Package { ref name, .. } = state.next { | ||||
|                     if let PubGrubPackageInner::Package { ref name, .. } = &*state.next { | ||||
|                         if let Some(entry) = self.unavailable_packages.get(name) { | ||||
|                             state | ||||
|                                 .pubgrub | ||||
|  | @ -530,7 +530,10 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                                 .add_incompatibility(Incompatibility::from_dependency( | ||||
|                                     package.clone(), | ||||
|                                     Range::singleton(version.clone()), | ||||
|                                     (PubGrubPackage::Python(kind), python_version.clone()), | ||||
|                                     ( | ||||
|                                         PubGrubPackage::from(PubGrubPackageInner::Python(kind)), | ||||
|                                         python_version.clone(), | ||||
|                                     ), | ||||
|                                 )); | ||||
|                         } | ||||
|                         state | ||||
|  | @ -633,11 +636,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|         package: &PubGrubPackage, | ||||
|         request_sink: &Sender<Request>, | ||||
|     ) -> Result<(), ResolveError> { | ||||
|         match package { | ||||
|             PubGrubPackage::Root(_) => {} | ||||
|             PubGrubPackage::Python(_) => {} | ||||
|             PubGrubPackage::Extra { .. } => {} | ||||
|             PubGrubPackage::Package { | ||||
|         match &**package { | ||||
|             PubGrubPackageInner::Root(_) => {} | ||||
|             PubGrubPackageInner::Python(_) => {} | ||||
|             PubGrubPackageInner::Extra { .. } => {} | ||||
|             PubGrubPackageInner::Package { | ||||
|                 name, url: None, .. | ||||
|             } => { | ||||
|                 // Verify that the package is allowed under the hash-checking policy.
 | ||||
|  | @ -650,7 +653,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                     request_sink.blocking_send(Request::Package(name.clone()))?; | ||||
|                 } | ||||
|             } | ||||
|             PubGrubPackage::Package { | ||||
|             PubGrubPackageInner::Package { | ||||
|                 name, | ||||
|                 url: Some(url), | ||||
|                 .. | ||||
|  | @ -684,12 +687,12 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|         // Iterate over the potential packages, and fetch file metadata for any of them. These
 | ||||
|         // represent our current best guesses for the versions that we _might_ select.
 | ||||
|         for (package, range) in packages { | ||||
|             let PubGrubPackage::Package { | ||||
|             let PubGrubPackageInner::Package { | ||||
|                 name, | ||||
|                 extra: None, | ||||
|                 marker: None, | ||||
|                 url: None, | ||||
|             } = package | ||||
|             } = &**package | ||||
|             else { | ||||
|                 continue; | ||||
|             }; | ||||
|  | @ -711,10 +714,12 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|         visited: &mut FxHashSet<PackageName>, | ||||
|         request_sink: &Sender<Request>, | ||||
|     ) -> Result<Option<ResolverVersion>, ResolveError> { | ||||
|         match package { | ||||
|             PubGrubPackage::Root(_) => Ok(Some(ResolverVersion::Available(MIN_VERSION.clone()))), | ||||
|         match &**package { | ||||
|             PubGrubPackageInner::Root(_) => { | ||||
|                 Ok(Some(ResolverVersion::Available(MIN_VERSION.clone()))) | ||||
|             } | ||||
| 
 | ||||
|             PubGrubPackage::Python(PubGrubPython::Installed) => { | ||||
|             PubGrubPackageInner::Python(PubGrubPython::Installed) => { | ||||
|                 let version = self.python_requirement.installed(); | ||||
|                 if range.contains(version) { | ||||
|                     Ok(Some(ResolverVersion::Available(version.deref().clone()))) | ||||
|  | @ -723,7 +728,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             PubGrubPackage::Python(PubGrubPython::Target) => { | ||||
|             PubGrubPackageInner::Python(PubGrubPython::Target) => { | ||||
|                 let version = self.python_requirement.target(); | ||||
|                 if range.contains(version) { | ||||
|                     Ok(Some(ResolverVersion::Available(version.deref().clone()))) | ||||
|  | @ -732,12 +737,12 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             PubGrubPackage::Extra { | ||||
|             PubGrubPackageInner::Extra { | ||||
|                 name, | ||||
|                 url: Some(url), | ||||
|                 .. | ||||
|             } | ||||
|             | PubGrubPackage::Package { | ||||
|             | PubGrubPackageInner::Package { | ||||
|                 name, | ||||
|                 url: Some(url), | ||||
|                 .. | ||||
|  | @ -833,10 +838,10 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 Ok(Some(ResolverVersion::Available(version.clone()))) | ||||
|             } | ||||
| 
 | ||||
|             PubGrubPackage::Extra { | ||||
|             PubGrubPackageInner::Extra { | ||||
|                 name, url: None, .. | ||||
|             } | ||||
|             | PubGrubPackage::Package { | ||||
|             | PubGrubPackageInner::Package { | ||||
|                 name, url: None, .. | ||||
|             } => { | ||||
|                 // Wait for the metadata to be available.
 | ||||
|  | @ -916,7 +921,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 let version = candidate.version().clone(); | ||||
| 
 | ||||
|                 // Emit a request to fetch the metadata for this version.
 | ||||
|                 if matches!(package, PubGrubPackage::Package { .. }) { | ||||
|                 if matches!(&**package, PubGrubPackageInner::Package { .. }) { | ||||
|                     if self.index.distributions().register(candidate.version_id()) { | ||||
|                         let request = Request::from(dist.for_resolution()); | ||||
|                         request_sink.blocking_send(request)?; | ||||
|  | @ -937,8 +942,8 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|         priorities: &mut PubGrubPriorities, | ||||
|         request_sink: &Sender<Request>, | ||||
|     ) -> Result<Dependencies, ResolveError> { | ||||
|         match package { | ||||
|             PubGrubPackage::Root(_) => { | ||||
|         match &**package { | ||||
|             PubGrubPackageInner::Root(_) => { | ||||
|                 // Add the root requirements.
 | ||||
|                 let dependencies = PubGrubDependencies::from_requirements( | ||||
|                     &self.requirements, | ||||
|  | @ -1021,9 +1026,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|                 Ok(Dependencies::Available(dependencies.into())) | ||||
|             } | ||||
| 
 | ||||
|             PubGrubPackage::Python(_) => Ok(Dependencies::Available(Vec::default())), | ||||
|             PubGrubPackageInner::Python(_) => Ok(Dependencies::Available(Vec::default())), | ||||
| 
 | ||||
|             PubGrubPackage::Package { | ||||
|             PubGrubPackageInner::Package { | ||||
|                 name, | ||||
|                 extra, | ||||
|                 marker: _marker, | ||||
|  | @ -1192,28 +1197,28 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
|             } | ||||
| 
 | ||||
|             // Add a dependency on both the extra and base package.
 | ||||
|             PubGrubPackage::Extra { | ||||
|             PubGrubPackageInner::Extra { | ||||
|                 name, | ||||
|                 extra, | ||||
|                 marker: _marker, | ||||
|                 url, | ||||
|             } => Ok(Dependencies::Available(vec![ | ||||
|                 ( | ||||
|                     PubGrubPackage::Package { | ||||
|                     PubGrubPackage::from(PubGrubPackageInner::Package { | ||||
|                         name: name.clone(), | ||||
|                         extra: None, | ||||
|                         marker: None, | ||||
|                         url: url.clone(), | ||||
|                     }, | ||||
|                     }), | ||||
|                     Range::singleton(version.clone()), | ||||
|                 ), | ||||
|                 ( | ||||
|                     PubGrubPackage::Package { | ||||
|                     PubGrubPackage::from(PubGrubPackageInner::Package { | ||||
|                         name: name.clone(), | ||||
|                         extra: Some(extra.clone()), | ||||
|                         marker: None, | ||||
|                         url: url.clone(), | ||||
|                     }, | ||||
|                     }), | ||||
|                     Range::singleton(version.clone()), | ||||
|                 ), | ||||
|             ])), | ||||
|  | @ -1438,18 +1443,18 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |||
| 
 | ||||
|     fn on_progress(&self, package: &PubGrubPackage, version: &Version) { | ||||
|         if let Some(reporter) = self.reporter.as_ref() { | ||||
|             match package { | ||||
|                 PubGrubPackage::Root(_) => {} | ||||
|                 PubGrubPackage::Python(_) => {} | ||||
|                 PubGrubPackage::Extra { .. } => {} | ||||
|                 PubGrubPackage::Package { | ||||
|             match &**package { | ||||
|                 PubGrubPackageInner::Root(_) => {} | ||||
|                 PubGrubPackageInner::Python(_) => {} | ||||
|                 PubGrubPackageInner::Extra { .. } => {} | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, | ||||
|                     url: Some(url), | ||||
|                     .. | ||||
|                 } => { | ||||
|                     reporter.on_progress(name, &VersionOrUrlRef::Url(&url.verbatim)); | ||||
|                 } | ||||
|                 PubGrubPackage::Package { | ||||
|                 PubGrubPackageInner::Package { | ||||
|                     name, url: None, .. | ||||
|                 } => { | ||||
|                     reporter.on_progress(name, &VersionOrUrlRef::Version(version)); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 konsti
						konsti