Use owned versions in `PythonRequirement`

This commit is contained in:
Zanie 2024-01-21 10:18:34 -06:00
parent 334dc1ea08
commit 83bda6621c
5 changed files with 26 additions and 36 deletions

View File

@ -130,14 +130,7 @@ pub struct NoSolutionError {
derivation_tree: DerivationTree<PubGrubPackage, Range<Version>>, derivation_tree: DerivationTree<PubGrubPackage, Range<Version>>,
available_versions: FxHashMap<PubGrubPackage, Vec<Version>>, available_versions: FxHashMap<PubGrubPackage, Vec<Version>>,
selector: Option<CandidateSelector>, selector: Option<CandidateSelector>,
python_requirement: Option<SolutionPythonRequirement>, python_requirement: Option<PythonRequirement>,
}
/// Derivative of [`PythonRequirement`] with owned data for error reporting.
#[derive(Debug, Clone)]
pub(crate) struct SolutionPythonRequirement {
pub(crate) installed: Version,
pub(crate) target: Version,
} }
impl std::error::Error for NoSolutionError {} impl std::error::Error for NoSolutionError {}
@ -219,10 +212,7 @@ impl NoSolutionError {
mut self, mut self,
python_requirement: &PythonRequirement, python_requirement: &PythonRequirement,
) -> Self { ) -> Self {
self.python_requirement = Some(SolutionPythonRequirement { self.python_requirement = Some(python_requirement.clone());
target: python_requirement.target().clone(),
installed: python_requirement.installed().clone(),
});
self self
} }
} }

View File

@ -12,8 +12,8 @@ use pubgrub::type_aliases::Map;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use crate::candidate_selector::CandidateSelector; use crate::candidate_selector::CandidateSelector;
use crate::error::SolutionPythonRequirement;
use crate::prerelease_mode::PreReleaseStrategy; use crate::prerelease_mode::PreReleaseStrategy;
use crate::python_requirement::PythonRequirement;
use super::PubGrubPackage; use super::PubGrubPackage;
@ -23,7 +23,7 @@ pub(crate) struct PubGrubReportFormatter<'a> {
pub(crate) available_versions: &'a FxHashMap<PubGrubPackage, Vec<Version>>, pub(crate) available_versions: &'a FxHashMap<PubGrubPackage, Vec<Version>>,
/// The versions that were available for each package /// The versions that were available for each package
pub(crate) python_requirement: Option<&'a SolutionPythonRequirement>, pub(crate) python_requirement: Option<&'a PythonRequirement>,
} }
impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<'_> { impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<'_> {
@ -37,8 +37,8 @@ impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<
External::NoVersions(package, set) => { External::NoVersions(package, set) => {
if matches!(package, PubGrubPackage::Python(_)) { if matches!(package, PubGrubPackage::Python(_)) {
if let Some(python) = self.python_requirement { if let Some(python) = self.python_requirement {
if python.target.release().iter().eq(python if python.target().release().iter().eq(python
.installed .installed()
.release() .release()
.iter() .iter()
.take(2)) .take(2))
@ -50,28 +50,28 @@ impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<
// display instead. // display instead.
return format!( return format!(
"the current {package} version ({}) does not satisfy {}", "the current {package} version ({}) does not satisfy {}",
python.target, python.target(),
PackageRange::compatibility(package, set) PackageRange::compatibility(package, set)
); );
} }
// Complex case, the target was provided and differs from the installed one // Complex case, the target was provided and differs from the installed one
// Determine which Python version requirement was not met // Determine which Python version requirement was not met
if !set.contains(&python.target) { if !set.contains(python.target()) {
return format!( return format!(
"the requested {package} version ({}) does not satisfy {}", "the requested {package} version ({}) does not satisfy {}",
python.target, python.target(),
PackageRange::compatibility(package, set) PackageRange::compatibility(package, set)
); );
} }
// TODO(zanieb): Explain to the user why the installed version is relevant // TODO(zanieb): Explain to the user why the installed version is relevant
// when they provided a target version; probably via a "hint" // when they provided a target version; probably via a "hint"
debug_assert!( debug_assert!(
!set.contains(&python.installed), !set.contains(python.installed()),
"There should not be an incompatibility where the range is satisfied by both Python requirements" "There should not be an incompatibility where the range is satisfied by both Python requirements"
); );
return format!( return format!(
"the current {package} version ({}) does not satisfy {}", "the current {package} version ({}) does not satisfy {}",
python.installed, python.installed(),
PackageRange::compatibility(package, set) PackageRange::compatibility(package, set)
); );
} }

View File

@ -3,30 +3,30 @@ use pep508_rs::MarkerEnvironment;
use puffin_interpreter::Interpreter; use puffin_interpreter::Interpreter;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PythonRequirement<'a> { pub struct PythonRequirement {
/// The installed version of Python. /// The installed version of Python.
installed: &'a Version, installed: Version,
/// The target version of Python; that is, the version of Python for which we are resolving /// The target version of Python; that is, the version of Python for which we are resolving
/// dependencies. This is typically the same as the installed version, but may be different /// dependencies. This is typically the same as the installed version, but may be different
/// when specifying an alternate Python version for the resolution. /// when specifying an alternate Python version for the resolution.
target: &'a Version, target: Version,
} }
impl<'a> PythonRequirement<'a> { impl PythonRequirement {
pub fn new(interpreter: &'a Interpreter, markers: &'a MarkerEnvironment) -> Self { pub fn new(interpreter: &Interpreter, markers: &MarkerEnvironment) -> Self {
Self { Self {
installed: interpreter.version(), installed: interpreter.version().clone(),
target: &markers.python_version.version, target: markers.python_version.version.clone(),
} }
} }
/// Return the installed version of Python. /// Return the installed version of Python.
pub(crate) fn installed(&self) -> &'a Version { pub(crate) fn installed(&self) -> &Version {
self.installed &self.installed
} }
/// Return the target version of Python. /// Return the target version of Python.
pub(crate) fn target(&self) -> &'a Version { pub(crate) fn target(&self) -> &Version {
self.target &self.target
} }
} }

View File

@ -63,7 +63,7 @@ pub struct Resolver<'a, Provider: ResolverProvider> {
overrides: Overrides, overrides: Overrides,
allowed_urls: AllowedUrls, allowed_urls: AllowedUrls,
markers: &'a MarkerEnvironment, markers: &'a MarkerEnvironment,
python_requirement: PythonRequirement<'a>, python_requirement: PythonRequirement,
selector: CandidateSelector, selector: CandidateSelector,
index: &'a InMemoryIndex, index: &'a InMemoryIndex,
/// A map from [`PackageId`] to the `Requires-Python` version specifiers for that package. /// A map from [`PackageId`] to the `Requires-Python` version specifiers for that package.
@ -120,7 +120,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
manifest: Manifest, manifest: Manifest,
options: ResolutionOptions, options: ResolutionOptions,
markers: &'a MarkerEnvironment, markers: &'a MarkerEnvironment,
python_requirement: PythonRequirement<'a>, python_requirement: PythonRequirement,
index: &'a InMemoryIndex, index: &'a InMemoryIndex,
provider: Provider, provider: Provider,
) -> Self { ) -> Self {

View File

@ -52,7 +52,7 @@ pub struct DefaultResolverProvider<'a, Context: BuildContext + Send + Sync> {
/// These are the entries from `--find-links` that act as overrides for index responses. /// These are the entries from `--find-links` that act as overrides for index responses.
flat_index: &'a FlatIndex, flat_index: &'a FlatIndex,
tags: &'a Tags, tags: &'a Tags,
python_requirement: PythonRequirement<'a>, python_requirement: PythonRequirement,
exclude_newer: Option<DateTime<Utc>>, exclude_newer: Option<DateTime<Utc>>,
allowed_yanks: AllowedYanks, allowed_yanks: AllowedYanks,
no_binary: &'a NoBinary, no_binary: &'a NoBinary,
@ -66,7 +66,7 @@ impl<'a, Context: BuildContext + Send + Sync> DefaultResolverProvider<'a, Contex
fetcher: DistributionDatabase<'a, Context>, fetcher: DistributionDatabase<'a, Context>,
flat_index: &'a FlatIndex, flat_index: &'a FlatIndex,
tags: &'a Tags, tags: &'a Tags,
python_requirement: PythonRequirement<'a>, python_requirement: PythonRequirement,
exclude_newer: Option<DateTime<Utc>>, exclude_newer: Option<DateTime<Utc>>,
allowed_yanks: AllowedYanks, allowed_yanks: AllowedYanks,
no_binary: &'a NoBinary, no_binary: &'a NoBinary,