mirror of
https://github.com/astral-sh/uv.git
synced 2025-12-04 00:54:42 +00:00
Enable package overrides in pip-compile (#631)
## Summary This PR enables overrides to be passed to `pip-compile` and `pip-install` via a new `--overrides` flag. When overrides are provided, we effectively replace any requirements that are overridden with the overridden versions. This is applied at all depths of the tree. The merge semantics are such that we replace _all_ requirements of a package with _all_ requirements from the overrides files. So, for example, if a package declares: ``` foo >= 1.0; python_version < '3.11' foo < 1.0; python_version >= '3.11' ``` And the user provides an override like: ``` foo >= 2.0 ``` Then _both_ of the `foo` requirements in the package will be replaced with the override. If instead, the user provided an override like: ``` foo >= 2.0; python_version < '3.11' foo < 3.0; python_version >= '3.11' ``` Then we'd replace _both_ of the original `foo` requirements with both of these overrides. (In technical terms, for each package in the requirements file, we flat-map over its overrides.) Closes https://github.com/astral-sh/puffin/issues/511.
This commit is contained in:
parent
e51b397779
commit
69581c03c3
13 changed files with 284 additions and 17 deletions
45
crates/puffin-resolver/src/overrides.rs
Normal file
45
crates/puffin-resolver/src/overrides.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use itertools::Either;
|
||||
use std::hash::BuildHasherDefault;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use pep508_rs::Requirement;
|
||||
use puffin_normalize::PackageName;
|
||||
|
||||
/// A set of overrides for a set of requirements.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(crate) struct Overrides(FxHashMap<PackageName, Vec<Requirement>>);
|
||||
|
||||
impl Overrides {
|
||||
/// Create a new set of overrides from a set of requirements.
|
||||
pub(crate) fn from_requirements(requirements: Vec<Requirement>) -> Self {
|
||||
let mut overrides: FxHashMap<PackageName, Vec<Requirement>> =
|
||||
FxHashMap::with_capacity_and_hasher(requirements.len(), BuildHasherDefault::default());
|
||||
for requirement in requirements {
|
||||
overrides
|
||||
.entry(requirement.name.clone())
|
||||
.or_default()
|
||||
.push(requirement);
|
||||
}
|
||||
Self(overrides)
|
||||
}
|
||||
|
||||
/// Get the overrides for a package.
|
||||
pub(crate) fn get(&self, name: &PackageName) -> Option<&Vec<Requirement>> {
|
||||
self.0.get(name)
|
||||
}
|
||||
|
||||
/// Apply the overrides to a set of requirements.
|
||||
pub(crate) fn apply<'a>(
|
||||
&'a self,
|
||||
requirements: &'a [Requirement],
|
||||
) -> impl Iterator<Item = &Requirement> {
|
||||
requirements.iter().flat_map(|requirement| {
|
||||
if let Some(overrides) = self.get(&requirement.name) {
|
||||
Either::Left(overrides.iter())
|
||||
} else {
|
||||
Either::Right(std::iter::once(requirement))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue