mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-13 09:12:32 +00:00
Add support for package-level conflicts in workspaces (#14906)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
Revives https://github.com/astral-sh/uv/pull/9130 Previously, we allowed scoping conflicting extras or groups to specific packages, e.g. ,`{ package = "foo", extra = "bar" }` for a conflict in `foo[bar]`. Now, we allow dropping the `extra` or `group` bit and using `{ package = "foo" }` directly which declares a conflict with `foo`'s production dependencies. This means you can declare conflicts between workspace members, e.g.: ``` [tool.uv] conflicts = [[{ package = "foo" }, { package = "bar" }]] ``` would not allow `foo` and `bar` to be installed at the same time. Similarly, a conflict can be declared between a package and a group: ``` [tool.uv] conflicts = [[{ package = "foo" }, { group = "lint" }]] ``` which would mean, e.g., that `--only-group lint` would be required for the invocation. As with our existing support for conflicting extras, there are edge-cases here where the resolver will _not_ fail even if there are conflicts that render a particular install target unusable. There's test coverage for some of these. We'll still error at install-time when the conflicting groups are selected. Due to the likelihood of bugs in this feature, I've marked it as a preview feature. I would not recommend reading the commits as there's some slop from not wanting to rebase Andrew's branch. --------- Co-authored-by: Andrew Gallant <andrew@astral.sh>
This commit is contained in:
parent
a9302906ce
commit
8f71d239f8
20 changed files with 1913 additions and 240 deletions
|
|
@ -35,7 +35,7 @@ use uv_pep508::{
|
|||
MarkerEnvironment, MarkerExpression, MarkerOperator, MarkerTree, MarkerValueString,
|
||||
};
|
||||
use uv_platform_tags::Tags;
|
||||
use uv_pypi_types::{ConflictItem, ConflictItemRef, Conflicts, VerbatimParsedUrl};
|
||||
use uv_pypi_types::{ConflictItem, ConflictItemRef, ConflictKindRef, Conflicts, VerbatimParsedUrl};
|
||||
use uv_types::{BuildContext, HashStrategy, InstalledPackagesProvider};
|
||||
use uv_warnings::warn_user_once;
|
||||
|
||||
|
|
@ -946,6 +946,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
let PubGrubDependency {
|
||||
package,
|
||||
version: _,
|
||||
parent: _,
|
||||
url: _,
|
||||
} = dependency;
|
||||
let url = package.name().and_then(|name| state.fork_urls.get(name));
|
||||
|
|
@ -1750,7 +1751,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
&self.conflicts,
|
||||
requirement,
|
||||
None,
|
||||
None,
|
||||
Some(package),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -1866,7 +1867,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
&self.conflicts,
|
||||
requirement,
|
||||
dev.as_ref(),
|
||||
Some(name),
|
||||
Some(package),
|
||||
)
|
||||
})
|
||||
.chain(system_dependencies)
|
||||
|
|
@ -1890,6 +1891,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
marker,
|
||||
}),
|
||||
version: Range::singleton(version.clone()),
|
||||
parent: None,
|
||||
url: None,
|
||||
})
|
||||
.collect(),
|
||||
|
|
@ -1917,6 +1919,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
marker,
|
||||
}),
|
||||
version: Range::singleton(version.clone()),
|
||||
parent: None,
|
||||
url: None,
|
||||
})
|
||||
})
|
||||
|
|
@ -1938,6 +1941,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
marker,
|
||||
}),
|
||||
version: Range::singleton(version.clone()),
|
||||
parent: None,
|
||||
url: None,
|
||||
})
|
||||
.collect(),
|
||||
|
|
@ -2801,6 +2805,7 @@ impl ForkState {
|
|||
let PubGrubDependency {
|
||||
package,
|
||||
version,
|
||||
parent: _,
|
||||
url,
|
||||
} = dependency;
|
||||
|
||||
|
|
@ -2872,6 +2877,7 @@ impl ForkState {
|
|||
let PubGrubDependency {
|
||||
package,
|
||||
version,
|
||||
parent: _,
|
||||
url: _,
|
||||
} = dependency;
|
||||
(package, version)
|
||||
|
|
@ -3654,7 +3660,7 @@ impl Forks {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Create a fork that excludes ALL extras.
|
||||
// Create a fork that excludes ALL conflicts.
|
||||
if let Some(fork_none) = fork.clone().filter(set.iter().cloned().map(Err)) {
|
||||
new.push(fork_none);
|
||||
}
|
||||
|
|
@ -3740,7 +3746,7 @@ impl Fork {
|
|||
|
||||
/// Add a dependency to this fork.
|
||||
fn add_dependency(&mut self, dep: PubGrubDependency) {
|
||||
if let Some(conflicting_item) = dep.package.conflicting_item() {
|
||||
if let Some(conflicting_item) = dep.conflicting_item() {
|
||||
self.conflicts.insert(conflicting_item.to_owned());
|
||||
}
|
||||
self.dependencies.push(dep);
|
||||
|
|
@ -3757,7 +3763,7 @@ impl Fork {
|
|||
if self.env.included_by_marker(marker) {
|
||||
return true;
|
||||
}
|
||||
if let Some(conflicting_item) = dep.package.conflicting_item() {
|
||||
if let Some(conflicting_item) = dep.conflicting_item() {
|
||||
self.conflicts.remove(&conflicting_item);
|
||||
}
|
||||
false
|
||||
|
|
@ -3782,12 +3788,23 @@ impl Fork {
|
|||
) -> Option<Self> {
|
||||
self.env = self.env.filter_by_group(rules)?;
|
||||
self.dependencies.retain(|dep| {
|
||||
let Some(conflicting_item) = dep.package.conflicting_item() else {
|
||||
let Some(conflicting_item) = dep.conflicting_item() else {
|
||||
return true;
|
||||
};
|
||||
if self.env.included_by_group(conflicting_item) {
|
||||
return true;
|
||||
}
|
||||
match conflicting_item.kind() {
|
||||
// We should not filter entire projects unless they're a top-level dependency
|
||||
// Otherwise, we'll fail to solve for children of the project, like extras
|
||||
ConflictKindRef::Project => {
|
||||
if dep.parent.is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ConflictKindRef::Group(_) => {}
|
||||
ConflictKindRef::Extra(_) => {}
|
||||
}
|
||||
self.conflicts.remove(&conflicting_item);
|
||||
false
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue