mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00

With the change, we remove the special casing of workspace dependencies and resolve `tool.uv` for all git and directory distributions. This gives us support for non-editable workspace dependencies and path dependencies in other workspaces. It removes a lot of special casing around workspaces. These changes are the groundwork for supporting `tool.uv` with dynamic metadata. The basis for this change is moving `Requirement` from `distribution-types` to `pypi-types` and the lowering logic from `uv-requirements` to `uv-distribution`. This changes should be split out in separate PRs. I've included an example workspace `albatross-root-workspace2` where `bird-feeder` depends on `a` from another workspace `ab`. There's a bunch of failing tests and regressed error messages that still need fixing. It does fix the audited package count for the workspace tests.
50 lines
1.7 KiB
Rust
50 lines
1.7 KiB
Rust
use std::hash::BuildHasherDefault;
|
|
|
|
use either::Either;
|
|
use pypi_types::Requirement;
|
|
use rustc_hash::FxHashMap;
|
|
|
|
use uv_normalize::PackageName;
|
|
|
|
/// A set of overrides for a set of requirements.
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct Overrides(FxHashMap<PackageName, Vec<Requirement>>);
|
|
|
|
impl Overrides {
|
|
/// Create a new set of overrides from a set of requirements.
|
|
pub 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)
|
|
}
|
|
|
|
/// Return an iterator over all [`Requirement`]s in the override set.
|
|
pub fn requirements(&self) -> impl Iterator<Item = &Requirement> {
|
|
self.0.values().flat_map(|requirements| requirements.iter())
|
|
}
|
|
|
|
/// Get the overrides for a package.
|
|
pub fn get(&self, name: &PackageName) -> Option<&Vec<Requirement>> {
|
|
self.0.get(name)
|
|
}
|
|
|
|
/// Apply the overrides to a set of requirements.
|
|
pub fn apply<'a>(
|
|
&'a self,
|
|
requirements: impl IntoIterator<Item = &'a Requirement>,
|
|
) -> impl Iterator<Item = &Requirement> {
|
|
requirements.into_iter().flat_map(|requirement| {
|
|
if let Some(overrides) = self.get(&requirement.name) {
|
|
Either::Left(overrides.iter())
|
|
} else {
|
|
Either::Right(std::iter::once(requirement))
|
|
}
|
|
})
|
|
}
|
|
}
|