mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-30 03:27:31 +00:00
Simplify available package version ranges when the name includes markers or extras (#6162)
There were different `PubGrubPackage` types so they never matched the available versions set! Luckily, the available versions are agnostic to the markers and optional dependencies so we can just broaden to using `PackageName` as a lookup key. Addresses yet another complaint in https://github.com/astral-sh/uv/issues/5046
This commit is contained in:
parent
05cceee523
commit
ea636bbe61
5 changed files with 24 additions and 46 deletions
|
|
@ -120,7 +120,7 @@ pub(crate) type ErrorTree = DerivationTree<PubGrubPackage, Range<Version>, Unava
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NoSolutionError {
|
pub struct NoSolutionError {
|
||||||
error: pubgrub::NoSolutionError<UvDependencyProvider>,
|
error: pubgrub::NoSolutionError<UvDependencyProvider>,
|
||||||
available_versions: FxHashMap<PubGrubPackage, BTreeSet<Version>>,
|
available_versions: FxHashMap<PackageName, BTreeSet<Version>>,
|
||||||
selector: CandidateSelector,
|
selector: CandidateSelector,
|
||||||
python_requirement: PythonRequirement,
|
python_requirement: PythonRequirement,
|
||||||
index_locations: IndexLocations,
|
index_locations: IndexLocations,
|
||||||
|
|
@ -135,7 +135,7 @@ impl NoSolutionError {
|
||||||
/// Create a new [`NoSolutionError`] from a [`pubgrub::NoSolutionError`].
|
/// Create a new [`NoSolutionError`] from a [`pubgrub::NoSolutionError`].
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
error: pubgrub::NoSolutionError<UvDependencyProvider>,
|
error: pubgrub::NoSolutionError<UvDependencyProvider>,
|
||||||
available_versions: FxHashMap<PubGrubPackage, BTreeSet<Version>>,
|
available_versions: FxHashMap<PackageName, BTreeSet<Version>>,
|
||||||
selector: CandidateSelector,
|
selector: CandidateSelector,
|
||||||
python_requirement: PythonRequirement,
|
python_requirement: PythonRequirement,
|
||||||
index_locations: IndexLocations,
|
index_locations: IndexLocations,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ use super::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct PubGrubReportFormatter<'a> {
|
pub(crate) struct PubGrubReportFormatter<'a> {
|
||||||
/// The versions that were available for each package
|
/// The versions that were available for each package
|
||||||
pub(crate) available_versions: &'a FxHashMap<PubGrubPackage, BTreeSet<Version>>,
|
pub(crate) available_versions: &'a FxHashMap<PackageName, BTreeSet<Version>>,
|
||||||
|
|
||||||
/// The versions that were available for each package
|
/// The versions that were available for each package
|
||||||
pub(crate) python_requirement: &'a PythonRequirement,
|
pub(crate) python_requirement: &'a PythonRequirement,
|
||||||
|
|
@ -87,7 +87,7 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason>
|
||||||
// Note that sometimes we do not have a range of available versions, e.g.,
|
// Note that sometimes we do not have a range of available versions, e.g.,
|
||||||
// when a package is from a non-registry source. In that case, we cannot
|
// when a package is from a non-registry source. In that case, we cannot
|
||||||
// perform further simplicifaction of the range.
|
// perform further simplicifaction of the range.
|
||||||
if let Some(available_versions) = self.available_versions.get(package) {
|
if let Some(available_versions) = package.name().and_then(|name| self.available_versions.get(name)) {
|
||||||
update_availability_range(&complement, available_versions)
|
update_availability_range(&complement, available_versions)
|
||||||
} else {
|
} else {
|
||||||
complement
|
complement
|
||||||
|
|
@ -484,10 +484,13 @@ impl PubGrubReportFormatter<'_> {
|
||||||
set: &'a Range<Version>,
|
set: &'a Range<Version>,
|
||||||
package: &PubGrubPackage,
|
package: &PubGrubPackage,
|
||||||
) -> Cow<'a, Range<Version>> {
|
) -> Cow<'a, Range<Version>> {
|
||||||
|
let Some(name) = package.name() else {
|
||||||
|
return Cow::Borrowed(set);
|
||||||
|
};
|
||||||
if set == &Range::full() {
|
if set == &Range::full() {
|
||||||
Cow::Borrowed(set)
|
Cow::Borrowed(set)
|
||||||
} else {
|
} else {
|
||||||
Cow::Owned(set.simplify(self.available_versions.get(package).into_iter().flatten()))
|
Cow::Owned(set.simplify(self.available_versions.get(name).into_iter().flatten()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -695,13 +698,17 @@ impl PubGrubReportFormatter<'_> {
|
||||||
range: self.simplify_set(set, package).into_owned(),
|
range: self.simplify_set(set, package).into_owned(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if let Some(version) = self.available_versions.get(package).and_then(|versions| {
|
} else if let Some(version) = package
|
||||||
versions
|
.name()
|
||||||
.iter()
|
.and_then(|name| self.available_versions.get(name))
|
||||||
.rev()
|
.and_then(|versions| {
|
||||||
.filter(|version| version.any_prerelease())
|
versions
|
||||||
.find(|version| set.contains(version))
|
.iter()
|
||||||
}) {
|
.rev()
|
||||||
|
.filter(|version| version.any_prerelease())
|
||||||
|
.find(|version| set.contains(version))
|
||||||
|
})
|
||||||
|
{
|
||||||
// There are pre-release versions available for the package.
|
// There are pre-release versions available for the package.
|
||||||
if selector.prerelease_strategy().allows(name, markers) != AllowPrerelease::Yes {
|
if selector.prerelease_strategy().allows(name, markers) != AllowPrerelease::Yes {
|
||||||
hints.insert(PubGrubHint::PrereleaseAvailable {
|
hints.insert(PubGrubHint::PrereleaseAvailable {
|
||||||
|
|
|
||||||
|
|
@ -1963,9 +1963,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
|
|
||||||
let mut available_versions = FxHashMap::default();
|
let mut available_versions = FxHashMap::default();
|
||||||
for package in err.packages() {
|
for package in err.packages() {
|
||||||
let PubGrubPackageInner::Package { name, .. } = &**package else {
|
let Some(name) = package.name() else { continue };
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if !visited.contains(name) {
|
if !visited.contains(name) {
|
||||||
// Avoid including available versions for packages that exist in the derivation
|
// Avoid including available versions for packages that exist in the derivation
|
||||||
// tree, but were never visited during resolution. We _may_ have metadata for
|
// tree, but were never visited during resolution. We _may_ have metadata for
|
||||||
|
|
@ -1977,7 +1975,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
if let VersionsResponse::Found(ref version_maps) = *response {
|
if let VersionsResponse::Found(ref version_maps) = *response {
|
||||||
for version_map in version_maps {
|
for version_map in version_maps {
|
||||||
available_versions
|
available_versions
|
||||||
.entry(package.clone())
|
.entry(name.clone())
|
||||||
.or_insert_with(BTreeSet::new)
|
.or_insert_with(BTreeSet::new)
|
||||||
.extend(version_map.iter().map(|(version, _)| version.clone()));
|
.extend(version_map.iter().map(|(version, _)| version.clone()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ fn conflict_in_fork() -> Result<()> {
|
||||||
And because package-a{sys_platform == 'darwin'}==1.0.0 depends on package-b and package-c, we can conclude that package-a{sys_platform == 'darwin'}==1.0.0 cannot be used.
|
And because package-a{sys_platform == 'darwin'}==1.0.0 depends on package-b and package-c, we can conclude that package-a{sys_platform == 'darwin'}==1.0.0 cannot be used.
|
||||||
And because only the following versions of package-a{sys_platform == 'darwin'} are available:
|
And because only the following versions of package-a{sys_platform == 'darwin'} are available:
|
||||||
package-a{sys_platform == 'darwin'}==1.0.0
|
package-a{sys_platform == 'darwin'}==1.0.0
|
||||||
package-a{sys_platform == 'darwin'}>=2
|
package-a{sys_platform == 'darwin'}>2
|
||||||
and your project depends on package-a{sys_platform == 'darwin'}<2, we can conclude that your project's requirements are unsatisfiable.
|
and your project depends on package-a{sys_platform == 'darwin'}<2, we can conclude that your project's requirements are unsatisfiable.
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
@ -2875,7 +2875,7 @@ fn fork_non_local_fork_marker_transitive() -> Result<()> {
|
||||||
╰─▶ Because package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}>=2.0.0 and only package-c{sys_platform == 'darwin'}<=2.0.0 is available, we can conclude that package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}==2.0.0.
|
╰─▶ Because package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}>=2.0.0 and only package-c{sys_platform == 'darwin'}<=2.0.0 is available, we can conclude that package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}==2.0.0.
|
||||||
And because only the following versions of package-c{sys_platform == 'linux'} are available:
|
And because only the following versions of package-c{sys_platform == 'linux'} are available:
|
||||||
package-c{sys_platform == 'linux'}==1.0.0
|
package-c{sys_platform == 'linux'}==1.0.0
|
||||||
package-c{sys_platform == 'linux'}>=2.0.0
|
package-c{sys_platform == 'linux'}>2.0.0
|
||||||
and package-a==1.0.0 depends on package-c{sys_platform == 'linux'}<2.0.0, we can conclude that package-a==1.0.0 and package-b==1.0.0 are incompatible.
|
and package-a==1.0.0 depends on package-c{sys_platform == 'linux'}<2.0.0, we can conclude that package-a==1.0.0 and package-b==1.0.0 are incompatible.
|
||||||
And because your project depends on package-a==1.0.0 and package-b==1.0.0, we can conclude that your project's requirements are unsatisfiable.
|
And because your project depends on package-a==1.0.0 and package-b==1.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||||
"###
|
"###
|
||||||
|
|
|
||||||
|
|
@ -7993,34 +7993,7 @@ fn universal_requires_python_incomplete() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: The requested Python version 3.7 is not available; 3.12.[X] will be used to build dependencies instead.
|
warning: The requested Python version 3.7 is not available; 3.12.[X] will be used to build dependencies instead.
|
||||||
× No solution found when resolving dependencies:
|
× No solution found when resolving dependencies:
|
||||||
╰─▶ Because only the following versions of uv{python_full_version >= '3.8'} are available:
|
╰─▶ Because only uv{python_full_version >= '3.8'}<=0.1.24 is available and the requested Python version (>=3.7) does not satisfy Python>=3.8, we can conclude that all versions of uv{python_full_version >= '3.8'} are incompatible.
|
||||||
uv{python_full_version >= '3.8'}==0.0.5
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.0
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.1
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.2
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.3
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.4
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.5
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.6
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.7
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.8
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.9
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.10
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.11
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.12
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.13
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.14
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.15
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.16
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.17
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.18
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.19
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.20
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.21
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.22
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.23
|
|
||||||
uv{python_full_version >= '3.8'}==0.1.24
|
|
||||||
and the requested Python version (>=3.7) does not satisfy Python>=3.8, we can conclude that all versions of uv{python_full_version >= '3.8'} are incompatible.
|
|
||||||
And because you require uv{python_full_version >= '3.8'}, we can conclude that your requirements are unsatisfiable.
|
And because you require uv{python_full_version >= '3.8'}, we can conclude that your requirements are unsatisfiable.
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue