Track Markers via a PubGrub package variant (#4123)
## Summary This PR adds a lowering similar to that seen in https://github.com/astral-sh/uv/pull/3100, but this time, for markers. Like `PubGrubPackageInner::Extra`, we now have `PubGrubPackageInner::Marker`. The dependencies of the `Marker` are `PubGrubPackageInner::Package` with and without the marker. As an example of why this is useful: assume we have `urllib3>=1.22.0` as a direct dependency. Later, we see `urllib3 ; python_version > '3.7'` as a transitive dependency. As-is, we might (for some reason) pick a very old version of `urllib3` to satisfy `urllib3 ; python_version > '3.7'`, then attempt to fetch its dependencies, which could even involve building a very old version of `urllib3 ; python_version > '3.7'`. Once we fetch the dependencies, we would see that `urllib3` at the same version is _also_ a dependency (because we tack it on). In the new scheme though, as soon as we "choose" the very old version of `urllib3 ; python_version > '3.7'`, we'd then see that `urllib3` (the base package) is also a dependency; so we see a conflict before we even fetch the dependencies of the old variant. With this, I can successfully resolve the case in #4099. Closes https://github.com/astral-sh/uv/issues/4099.
This commit is contained in:
@@ -112,7 +112,7 @@ impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ResolveError {
|
||||
|
||||
/// Given a [`DerivationTree`], collapse any [`External::FromDependencyOf`] incompatibilities
|
||||
/// wrap an [`PubGrubPackageInner::Extra`] package.
|
||||
fn collapse_extra_proxies(
|
||||
fn collapse_proxies(
|
||||
derivation_tree: &mut DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>,
|
||||
) {
|
||||
match derivation_tree {
|
||||
@@ -125,20 +125,32 @@ fn collapse_extra_proxies(
|
||||
(
|
||||
DerivationTree::External(External::FromDependencyOf(package, ..)),
|
||||
ref mut cause,
|
||||
) if matches!(&**package, PubGrubPackageInner::Extra { .. }) => {
|
||||
collapse_extra_proxies(cause);
|
||||
) if matches!(
|
||||
&**package,
|
||||
PubGrubPackageInner::Extra { .. }
|
||||
| PubGrubPackageInner::Marker { .. }
|
||||
| PubGrubPackageInner::Dev { .. }
|
||||
) =>
|
||||
{
|
||||
collapse_proxies(cause);
|
||||
*derivation_tree = cause.clone();
|
||||
}
|
||||
(
|
||||
ref mut cause,
|
||||
DerivationTree::External(External::FromDependencyOf(package, ..)),
|
||||
) if matches!(&**package, PubGrubPackageInner::Extra { .. }) => {
|
||||
collapse_extra_proxies(cause);
|
||||
) if matches!(
|
||||
&**package,
|
||||
PubGrubPackageInner::Extra { .. }
|
||||
| PubGrubPackageInner::Marker { .. }
|
||||
| PubGrubPackageInner::Dev { .. }
|
||||
) =>
|
||||
{
|
||||
collapse_proxies(cause);
|
||||
*derivation_tree = cause.clone();
|
||||
}
|
||||
_ => {
|
||||
collapse_extra_proxies(Arc::make_mut(&mut derived.cause1));
|
||||
collapse_extra_proxies(Arc::make_mut(&mut derived.cause2));
|
||||
collapse_proxies(Arc::make_mut(&mut derived.cause1));
|
||||
collapse_proxies(Arc::make_mut(&mut derived.cause2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,7 +168,7 @@ impl From<pubgrub::error::PubGrubError<UvDependencyProvider>> for ResolveError {
|
||||
}
|
||||
pubgrub::error::PubGrubError::Failure(inner) => Self::Failure(inner),
|
||||
pubgrub::error::PubGrubError::NoSolution(mut derivation_tree) => {
|
||||
collapse_extra_proxies(&mut derivation_tree);
|
||||
collapse_proxies(&mut derivation_tree);
|
||||
|
||||
Self::NoSolution(NoSolutionError {
|
||||
derivation_tree,
|
||||
@@ -232,8 +244,9 @@ impl NoSolutionError {
|
||||
let mut available_versions = IndexMap::default();
|
||||
for package in self.derivation_tree.packages() {
|
||||
match &**package {
|
||||
PubGrubPackageInner::Root(_) => {}
|
||||
PubGrubPackageInner::Python(_) => {}
|
||||
PubGrubPackageInner::Root { .. } => {}
|
||||
PubGrubPackageInner::Python { .. } => {}
|
||||
PubGrubPackageInner::Marker { .. } => {}
|
||||
PubGrubPackageInner::Extra { .. } => {}
|
||||
PubGrubPackageInner::Dev { .. } => {}
|
||||
PubGrubPackageInner::Package { name, .. } => {
|
||||
|
||||
@@ -136,6 +136,9 @@ fn add_requirements(
|
||||
|
||||
dependencies.push((package.clone(), version.clone()));
|
||||
}
|
||||
PubGrubPackageInner::Marker { .. } => {
|
||||
dependencies.push((package.clone(), version.clone()));
|
||||
}
|
||||
PubGrubPackageInner::Extra { name, extra, .. } => {
|
||||
// Recursively add the dependencies of the current package (e.g., `black` depending on
|
||||
// `black[colorama]`).
|
||||
@@ -272,13 +275,12 @@ impl PubGrubRequirement {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: requirement.name.clone(),
|
||||
package: PubGrubPackage::from_url(
|
||||
requirement.name.clone(),
|
||||
extra,
|
||||
dev: None,
|
||||
marker: requirement.marker.clone(),
|
||||
url: Some(expected.clone()),
|
||||
}),
|
||||
requirement.marker.clone(),
|
||||
expected.clone(),
|
||||
),
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
@@ -299,13 +301,12 @@ impl PubGrubRequirement {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: requirement.name.clone(),
|
||||
package: PubGrubPackage::from_url(
|
||||
requirement.name.clone(),
|
||||
extra,
|
||||
dev: None,
|
||||
marker: requirement.marker.clone(),
|
||||
url: Some(expected.clone()),
|
||||
}),
|
||||
requirement.marker.clone(),
|
||||
expected.clone(),
|
||||
),
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
@@ -341,13 +342,12 @@ impl PubGrubRequirement {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: requirement.name.clone(),
|
||||
package: PubGrubPackage::from_url(
|
||||
requirement.name.clone(),
|
||||
extra,
|
||||
dev: None,
|
||||
marker: requirement.marker.clone(),
|
||||
url: Some(expected.clone()),
|
||||
}),
|
||||
requirement.marker.clone(),
|
||||
expected.clone(),
|
||||
),
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -119,10 +119,19 @@ pub enum PubGrubPackageInner {
|
||||
marker: Option<MarkerTree>,
|
||||
url: Option<VerbatimParsedUrl>,
|
||||
},
|
||||
/// A proxy package for a base package with a marker (e.g., `black; python_version >= "3.6"`).
|
||||
///
|
||||
/// If a requirement has an extra _and_ a marker, it will be represented via the `Extra` variant
|
||||
/// rather than the `Marker` variant.
|
||||
Marker {
|
||||
name: PackageName,
|
||||
marker: MarkerTree,
|
||||
url: Option<VerbatimParsedUrl>,
|
||||
},
|
||||
}
|
||||
|
||||
impl PubGrubPackage {
|
||||
/// Create a [`PubGrubPackage`] from a package name and optional extra name.
|
||||
/// Create a [`PubGrubPackage`] from a package name and version.
|
||||
pub(crate) fn from_package(
|
||||
name: PackageName,
|
||||
extra: Option<ExtraName>,
|
||||
@@ -143,6 +152,8 @@ impl PubGrubPackage {
|
||||
marker,
|
||||
url,
|
||||
}))
|
||||
} else if let Some(marker) = marker {
|
||||
Self(Arc::new(PubGrubPackageInner::Marker { name, marker, url }))
|
||||
} else {
|
||||
Self(Arc::new(PubGrubPackageInner::Package {
|
||||
name,
|
||||
@@ -153,6 +164,43 @@ impl PubGrubPackage {
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a [`PubGrubPackage`] from a package name and URL.
|
||||
pub(crate) fn from_url(
|
||||
name: PackageName,
|
||||
extra: Option<ExtraName>,
|
||||
mut marker: Option<MarkerTree>,
|
||||
url: VerbatimParsedUrl,
|
||||
) -> Self {
|
||||
// Remove all extra expressions from the marker, since we track extras
|
||||
// separately. This also avoids an issue where packages added via
|
||||
// extras end up having two distinct marker expressions, which in turn
|
||||
// makes them two distinct packages. This results in PubGrub being
|
||||
// unable to unify version constraints across such packages.
|
||||
marker = marker.and_then(|m| m.simplify_extras_with(|_| true));
|
||||
if let Some(extra) = extra {
|
||||
Self(Arc::new(PubGrubPackageInner::Extra {
|
||||
name,
|
||||
extra,
|
||||
marker,
|
||||
url: Some(url),
|
||||
}))
|
||||
} else if let Some(marker) = marker {
|
||||
Self(Arc::new(PubGrubPackageInner::Marker {
|
||||
name,
|
||||
marker,
|
||||
url: Some(url),
|
||||
}))
|
||||
} else {
|
||||
Self(Arc::new(PubGrubPackageInner::Package {
|
||||
name,
|
||||
extra,
|
||||
dev: None,
|
||||
marker,
|
||||
url: Some(url),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
|
||||
@@ -202,6 +250,7 @@ impl std::fmt::Display for PubGrubPackageInner {
|
||||
} => {
|
||||
write!(f, "{name}[{extra}]{{{marker}}}")
|
||||
}
|
||||
Self::Marker { name, marker, .. } => write!(f, "{name}{{{marker}}}"),
|
||||
Self::Extra { name, extra, .. } => write!(f, "{name}[{extra}]"),
|
||||
Self::Dev { name, dev, .. } => write!(f, "{name}:{dev}"),
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ impl PubGrubPriorities {
|
||||
PubGrubPackageInner::Root(_) => {}
|
||||
PubGrubPackageInner::Python(_) => {}
|
||||
|
||||
PubGrubPackageInner::Extra {
|
||||
PubGrubPackageInner::Marker {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Dev {
|
||||
@@ -70,7 +73,10 @@ impl PubGrubPriorities {
|
||||
}
|
||||
}
|
||||
}
|
||||
PubGrubPackageInner::Extra {
|
||||
PubGrubPackageInner::Marker {
|
||||
name, url: Some(_), ..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name, url: Some(_), ..
|
||||
}
|
||||
| PubGrubPackageInner::Dev {
|
||||
@@ -111,6 +117,7 @@ impl PubGrubPriorities {
|
||||
match &**package {
|
||||
PubGrubPackageInner::Root(_) => Some(PubGrubPriority::Root),
|
||||
PubGrubPackageInner::Python(_) => Some(PubGrubPriority::Root),
|
||||
PubGrubPackageInner::Marker { name, .. } => self.0.get(name).copied(),
|
||||
PubGrubPackageInner::Extra { name, .. } => self.0.get(name).copied(),
|
||||
PubGrubPackageInner::Dev { name, .. } => self.0.get(name).copied(),
|
||||
PubGrubPackageInner::Package { name, .. } => self.0.get(name).copied(),
|
||||
|
||||
@@ -57,7 +57,7 @@ impl BatchPrefetcher {
|
||||
name,
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: _marker,
|
||||
marker: None,
|
||||
url: None,
|
||||
} = &**next
|
||||
else {
|
||||
@@ -166,11 +166,15 @@ impl BatchPrefetcher {
|
||||
// Only track base packages, no virtual packages from extras.
|
||||
if matches!(
|
||||
&*package,
|
||||
PubGrubPackageInner::Package { extra: Some(_), .. }
|
||||
PubGrubPackageInner::Package {
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: None,
|
||||
..
|
||||
}
|
||||
) {
|
||||
return;
|
||||
*self.tried_versions.entry(package).or_default() += 1;
|
||||
}
|
||||
*self.tried_versions.entry(package).or_default() += 1;
|
||||
}
|
||||
|
||||
/// After 5, 10, 20, 40 tried versions, prefetch that many versions to start early but not
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::thread;
|
||||
|
||||
use dashmap::DashMap;
|
||||
use futures::{FutureExt, StreamExt, TryFutureExt};
|
||||
use itertools::Itertools;
|
||||
use pubgrub::error::PubGrubError;
|
||||
use pubgrub::range::Range;
|
||||
use pubgrub::solver::{Incompatibility, State};
|
||||
@@ -579,9 +580,16 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
match &**package {
|
||||
PubGrubPackageInner::Root(_) => {}
|
||||
PubGrubPackageInner::Python(_) => {}
|
||||
PubGrubPackageInner::Extra { .. } => {}
|
||||
PubGrubPackageInner::Dev { .. } => {}
|
||||
PubGrubPackageInner::Package {
|
||||
PubGrubPackageInner::Marker {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Dev {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Package {
|
||||
name, url: None, ..
|
||||
} => {
|
||||
// Verify that the package is allowed under the hash-checking policy.
|
||||
@@ -594,7 +602,22 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
request_sink.blocking_send(Request::Package(name.clone()))?;
|
||||
}
|
||||
}
|
||||
PubGrubPackageInner::Package {
|
||||
PubGrubPackageInner::Marker {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
}
|
||||
| PubGrubPackageInner::Dev {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
}
|
||||
| PubGrubPackageInner::Package {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
@@ -615,7 +638,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
}
|
||||
|
||||
/// Visit the set of [`PubGrubPackage`] candidates prior to selection. This allows us to fetch
|
||||
/// metadata for all of the packages in parallel.
|
||||
/// metadata for all packages in parallel.
|
||||
fn pre_visit<'data>(
|
||||
packages: impl Iterator<Item = (&'data PubGrubPackage, &'data Range<Version>)>,
|
||||
request_sink: &Sender<Request>,
|
||||
@@ -627,7 +650,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
name,
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: _marker,
|
||||
marker: None,
|
||||
url: None,
|
||||
} = &**package
|
||||
else {
|
||||
@@ -662,7 +685,12 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
PubGrubPackageInner::Extra {
|
||||
PubGrubPackageInner::Marker {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
@@ -758,7 +786,10 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
Ok(Some(ResolverVersion::Available(version.clone())))
|
||||
}
|
||||
|
||||
PubGrubPackageInner::Extra {
|
||||
PubGrubPackageInner::Marker {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Extra {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackageInner::Dev {
|
||||
@@ -888,6 +919,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
// extras are enabled, we shouldn't need to fork.
|
||||
PubGrubPackageInner::Root(_) | PubGrubPackageInner::Python(_) => unreachable!(),
|
||||
PubGrubPackageInner::Package { ref name, .. }
|
||||
| PubGrubPackageInner::Marker { ref name, .. }
|
||||
| PubGrubPackageInner::Extra { ref name, .. }
|
||||
| PubGrubPackageInner::Dev { ref name, .. } => name,
|
||||
};
|
||||
@@ -980,21 +1012,6 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
} => {
|
||||
// If we're excluding transitive dependencies, short-circuit.
|
||||
if self.dependency_mode.is_direct() {
|
||||
// If a package has a marker, add a dependency from it to the
|
||||
// same package without markers.
|
||||
if marker.is_some() {
|
||||
return Ok(Dependencies::Available(vec![(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: extra.clone(),
|
||||
dev: dev.clone(),
|
||||
marker: None,
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
)]));
|
||||
}
|
||||
|
||||
// If an extra is provided, wait for the metadata to be available, since it's
|
||||
// still required for generating the lock file.
|
||||
let dist = match url {
|
||||
@@ -1132,90 +1149,82 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
}
|
||||
}
|
||||
|
||||
// If a package has a marker, add a dependency from it to the
|
||||
// same package without markers.
|
||||
//
|
||||
// At time of writing, AG doesn't fully understand why we need
|
||||
// this, but one explanation is that without it, there is no
|
||||
// way to connect two different `PubGrubPackage` values with
|
||||
// the same package name but different markers. With different
|
||||
// markers, they would be considered wholly distinct packages.
|
||||
// But this dependency-on-itself-without-markers forces PubGrub
|
||||
// to unify the constraints across what would otherwise be two
|
||||
// distinct packages.
|
||||
if marker.is_some() {
|
||||
dependencies.push(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: extra.clone(),
|
||||
dev: dev.clone(),
|
||||
marker: None,
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Dependencies::Available(dependencies.into()))
|
||||
}
|
||||
|
||||
// Add a dependency on both the extra and base package.
|
||||
// Add a dependency on both the marker and base package.
|
||||
PubGrubPackageInner::Marker { name, marker, url } => Ok(Dependencies::Available(
|
||||
[None, Some(marker)]
|
||||
.into_iter()
|
||||
.map(move |marker| {
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: marker.cloned(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
|
||||
// Add a dependency on both the extra and base package, with and without the marker.
|
||||
PubGrubPackageInner::Extra {
|
||||
name,
|
||||
extra,
|
||||
marker,
|
||||
url,
|
||||
} => Ok(Dependencies::Available(vec![
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: marker.clone(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: Some(extra.clone()),
|
||||
dev: None,
|
||||
marker: marker.clone(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
])),
|
||||
} => Ok(Dependencies::Available(
|
||||
[None, marker.as_ref()]
|
||||
.into_iter()
|
||||
.dedup()
|
||||
.flat_map(move |marker| {
|
||||
[None, Some(extra)].into_iter().map(move |extra| {
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: extra.cloned(),
|
||||
dev: None,
|
||||
marker: marker.cloned(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
|
||||
// Add a dependency on both the development dependency group and base package.
|
||||
// Add a dependency on both the development dependency group and base package, with and
|
||||
// without the marker.
|
||||
PubGrubPackageInner::Dev {
|
||||
name,
|
||||
dev,
|
||||
marker,
|
||||
url,
|
||||
} => Ok(Dependencies::Available(vec![
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
dev: None,
|
||||
marker: marker.clone(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
dev: Some(dev.clone()),
|
||||
marker: marker.clone(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
])),
|
||||
} => Ok(Dependencies::Available(
|
||||
[None, marker.as_ref()]
|
||||
.into_iter()
|
||||
.dedup()
|
||||
.flat_map(move |marker| {
|
||||
[None, Some(dev)].into_iter().map(move |dev| {
|
||||
(
|
||||
PubGrubPackage::from(PubGrubPackageInner::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
dev: dev.cloned(),
|
||||
marker: marker.cloned(),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Range::singleton(version.clone()),
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1444,6 +1453,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||
match &**package {
|
||||
PubGrubPackageInner::Root(_) => {}
|
||||
PubGrubPackageInner::Python(_) => {}
|
||||
PubGrubPackageInner::Marker { .. } => {}
|
||||
PubGrubPackageInner::Extra { .. } => {}
|
||||
PubGrubPackageInner::Dev { .. } => {}
|
||||
PubGrubPackageInner::Package {
|
||||
@@ -1569,6 +1579,28 @@ impl SolveState {
|
||||
dependencies.entry(names).or_default().insert(versions);
|
||||
}
|
||||
|
||||
PubGrubPackageInner::Marker {
|
||||
name: ref dependency_name,
|
||||
..
|
||||
} => {
|
||||
if self_name == dependency_name {
|
||||
continue;
|
||||
}
|
||||
let names = ResolutionDependencyNames {
|
||||
from: self_name.clone(),
|
||||
to: dependency_name.clone(),
|
||||
};
|
||||
let versions = ResolutionDependencyVersions {
|
||||
from_version: self_version.clone(),
|
||||
from_extra: self_extra.clone(),
|
||||
from_dev: self_dev.clone(),
|
||||
to_version: dependency_version.clone(),
|
||||
to_extra: None,
|
||||
to_dev: None,
|
||||
};
|
||||
dependencies.entry(names).or_default().insert(versions);
|
||||
}
|
||||
|
||||
PubGrubPackageInner::Extra {
|
||||
name: ref dependency_name,
|
||||
extra: ref dependency_extra,
|
||||
|
||||
@@ -802,7 +802,6 @@ fn fork_non_local_fork_marker_transitive() -> Result<()> {
|
||||
warning: `uv lock` is experimental and may change without warning.
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ 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 package-c{sys_platform == 'darwin'}==2.0.0 depends on package-c==2.0.0 and package-c{sys_platform == 'linux'}==1.0.0 depends on package-c==1.0.0, we can conclude that package-b==1.0.0 and package-c{sys_platform == 'linux'}==1.0.0 are incompatible.
|
||||
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'}>=2.0.0
|
||||
|
||||
Reference in New Issue
Block a user