Reduce ambiguity in conflicting extras example (#10877)

## Summary

Closes https://github.com/astral-sh/uv/issues/10378.
This commit is contained in:
Charlie Marsh
2025-01-22 19:09:49 -05:00
committed by GitHub
parent 4051cff582
commit 2df3f0e782
3 changed files with 44 additions and 52 deletions
+22 -26
View File
@@ -504,48 +504,44 @@ pub struct ToolUv {
)]
pub environments: Option<SupportedEnvironments>,
/// Conflicting extras or groups may be declared here.
/// Declare collections of extras or dependency groups that are conflicting
/// (i.e., mutually exclusive).
///
/// It's useful to declare conflicts when, for example, two or more extras
/// have mutually incompatible dependencies. Extra `foo` might depend
/// on `numpy==2.0.0` while extra `bar` might depend on `numpy==2.1.0`.
/// These extras cannot be activated at the same time. This usually isn't
/// a problem for pip-style workflows, but when using projects in uv that
/// support with universal resolution, it will try to produce a resolution
/// that satisfies both extras simultaneously.
/// It's useful to declare conflicts when two or more extras have mutually
/// incompatible dependencies. For example, extra `foo` might depend
/// on `numpy==2.0.0` while extra `bar` depends on `numpy==2.1.0`. While these
/// dependencies conflict, it may be the case that users are not expected to
/// activate both `foo` and `bar` at the same time, making it possible to
/// generate a universal resolution for the project despite the incompatibility.
///
/// When this happens, resolution will fail, because one cannot install
/// both `numpy 2.0.0` and `numpy 2.1.0` into the same environment.
///
/// To work around this, you may specify `foo` and `bar` as conflicting
/// extras (you can do the same with groups). When doing universal
/// resolution in project mode, these extras will get their own "forks"
/// distinct from one another in order to permit conflicting dependencies.
/// In exchange, if one tries to install from the lock file with both
/// conflicting extras activated, installation will fail.
/// By making such conflicts explicit, uv can generate a universal resolution
/// for a project, taking into account that certain combinations of extras and
/// groups are mutually exclusive. In exchange, installation will fail if a
/// user attempts to activate both conflicting extras.
#[cfg_attr(
feature = "schemars",
schemars(description = "A list sets of conflicting groups or extras.")
schemars(description = "A list of sets of conflicting groups or extras.")
)]
#[option(
default = r#"[]"#,
value_type = "list[list[dict]]",
example = r#"
# Require that `package[test1]` and `package[test2]`
# requirements are resolved in different forks so that they
# cannot conflict with one another.
# Require that `package[extra1]` and `package[extra2]` are resolved
# in different forks so that they cannot conflict with one another.
conflicts = [
[
{ extra = "test1" },
{ extra = "test2" },
{ extra = "extra1" },
{ extra = "extra2" },
]
]
# Or, to declare conflicting groups:
# Require that the dependency groups `group1` and `group2`
# are resolved in different forks so that they cannot conflict
# with one another.
conflicts = [
[
{ group = "test1" },
{ group = "test2" },
{ group = "group1" },
{ group = "group2" },
]
]
"#
+21 -25
View File
@@ -1,25 +1,20 @@
## Project metadata
### [`conflicts`](#conflicts) {: #conflicts }
Conflicting extras or groups may be declared here.
Declare collections of extras or dependency groups that are conflicting
(i.e., mutually exclusive).
It's useful to declare conflicts when, for example, two or more extras
have mutually incompatible dependencies. Extra `foo` might depend
on `numpy==2.0.0` while extra `bar` might depend on `numpy==2.1.0`.
These extras cannot be activated at the same time. This usually isn't
a problem for pip-style workflows, but when using projects in uv that
support with universal resolution, it will try to produce a resolution
that satisfies both extras simultaneously.
It's useful to declare conflicts when two or more extras have mutually
incompatible dependencies. For example, extra `foo` might depend
on `numpy==2.0.0` while extra `bar` depends on `numpy==2.1.0`. While these
dependencies conflict, it may be the case that users are not expected to
activate both `foo` and `bar` at the same time, making it possible to
generate a universal resolution for the project despite the incompatibility.
When this happens, resolution will fail, because one cannot install
both `numpy 2.0.0` and `numpy 2.1.0` into the same environment.
To work around this, you may specify `foo` and `bar` as conflicting
extras (you can do the same with groups). When doing universal
resolution in project mode, these extras will get their own "forks"
distinct from one another in order to permit conflicting dependencies.
In exchange, if one tries to install from the lock file with both
conflicting extras activated, installation will fail.
By making such conflicts explicit, uv can generate a universal resolution
for a project, taking into account that certain combinations of extras and
groups are mutually exclusive. In exchange, installation will fail if a
user attempts to activate both conflicting extras.
**Default value**: `[]`
@@ -29,21 +24,22 @@ conflicting extras activated, installation will fail.
```toml title="pyproject.toml"
[tool.uv]
# Require that `package[test1]` and `package[test2]`
# requirements are resolved in different forks so that they
# cannot conflict with one another.
# Require that `package[extra1]` and `package[extra2]` are resolved
# in different forks so that they cannot conflict with one another.
conflicts = [
[
{ extra = "test1" },
{ extra = "test2" },
{ extra = "extra1" },
{ extra = "extra2" },
]
]
# Or, to declare conflicting groups:
# Require that the dependency groups `group1` and `group2`
# are resolved in different forks so that they cannot conflict
# with one another.
conflicts = [
[
{ group = "test1" },
{ group = "test2" },
{ group = "group1" },
{ group = "group2" },
]
]
```
+1 -1
View File
@@ -88,7 +88,7 @@
]
},
"conflicts": {
"description": "A list sets of conflicting groups or extras.",
"description": "A list of sets of conflicting groups or extras.",
"anyOf": [
{
"$ref": "#/definitions/SchemaConflicts"