Apply extra to overrides and constraints (#4829)

This is an attempt to solve https://github.com/astral-sh/uv/issues/ by
applying the extra marker of the requirement to overrides and
constraints.

Say in `a` we have a requirements
```
b==1; python_version < "3.10"
c==1; extra == "feature"
```

and overrides
```
b==2; python_version < "3.10"
b==3; python_version >= "3.10"
c==2; python_version < "3.10"
c==3; python_version >= "3.10"
```

Our current strategy is to discard the markers in the original
requirements. This means that on 3.12 for `a` we install `b==3`, but it
also means that we add `c` to `a` without `a[feature]`, causing #4826.
With this PR, the new requirement become,

```
b==2; python_version < "3.10"
b==3; python_version >= "3.10"
c==2; python_version < "3.10" and extra == "feature"
c==3; python_version >= "3.10" and extra == "feature"
```

allowing to override markers while preserving optional dependencies as
such.

Fixes #4826
This commit is contained in:
konsti 2024-07-09 20:37:24 +02:00 committed by GitHub
parent 0a04108a15
commit 53db63f6dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 159 additions and 30 deletions

View file

@ -1897,6 +1897,28 @@ impl MarkerTree {
}
}
}
/// Find a top level `extra == "..."` expression.
///
/// ASSUMPTION: There is one `extra = "..."`, and it's either the only marker or part of the
/// main conjunction.
pub fn top_level_extra(&self) -> Option<&MarkerExpression> {
match &self {
MarkerTree::Expression(extra_expression @ MarkerExpression::Extra { .. }) => {
Some(extra_expression)
}
MarkerTree::And(and) => and.iter().find_map(|marker| {
if let MarkerTree::Expression(extra_expression @ MarkerExpression::Extra { .. }) =
marker
{
Some(extra_expression)
} else {
None
}
}),
MarkerTree::Expression(_) | MarkerTree::Or(_) => None,
}
}
}
impl Display for MarkerTree {