mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
uv-resolver: normalize marker expressions (#4017)
This is a quick fix for some flaky tests where the output in the lock file isn't stable because marker expressions can be combined in a non-deterministic order. I believe there is ongoing work to simplify marker expressions which will help here, but I think some kind of normalization is still ultimately needed to guarantee consistent output. I first noticed the flaky test in: https://github.com/astral-sh/uv/pull/4015
This commit is contained in:
parent
3b8f3a7f0d
commit
5c30b39fe3
2 changed files with 30 additions and 1 deletions
|
@ -1881,6 +1881,30 @@ impl MarkerTree {
|
|||
exprs.push(tree);
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalizes this marker tree such that all conjunctions and disjunctions
|
||||
/// are sorted.
|
||||
///
|
||||
/// This is useful in cases where creating conjunctions or disjunctions
|
||||
/// might occur in a non-deterministic order. This routine will erase the
|
||||
/// distinction created by such a construction.
|
||||
pub fn normalize(&mut self) {
|
||||
match *self {
|
||||
MarkerTree::Expression(_) => {}
|
||||
MarkerTree::And(ref mut trees) | MarkerTree::Or(ref mut trees) => {
|
||||
// This is kind of cheesy, because we're doing a recursive call
|
||||
// followed by a sort, and that sort is also recursive (due to
|
||||
// the corresponding Ord impl being recursive).
|
||||
//
|
||||
// We should consider refactoring `MarkerTree` to a "smart
|
||||
// constructor" design that normalizes them by construction.
|
||||
for tree in &mut *trees {
|
||||
tree.normalize();
|
||||
}
|
||||
trees.sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MarkerTree {
|
||||
|
|
|
@ -356,7 +356,12 @@ pub struct Distribution {
|
|||
impl Distribution {
|
||||
fn from_annotated_dist(annotated_dist: &AnnotatedDist) -> Result<Self, LockError> {
|
||||
let id = DistributionId::from_annotated_dist(annotated_dist);
|
||||
let marker = annotated_dist.marker.clone();
|
||||
let mut marker = annotated_dist.marker.clone();
|
||||
// Markers can be combined in an unpredictable order, so normalize them
|
||||
// such that the lock file output is consistent and deterministic.
|
||||
if let Some(ref mut marker) = marker {
|
||||
marker.normalize();
|
||||
}
|
||||
let sdist = SourceDist::from_annotated_dist(annotated_dist)?;
|
||||
let wheels = Wheel::from_annotated_dist(annotated_dist)?;
|
||||
Ok(Distribution {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue