Move "Conflicting dependencies" to the "Resolution" page (#14633)

This commit is contained in:
Zanie Blue 2025-07-15 16:47:43 -05:00 committed by GitHub
parent 863e73a841
commit 8d6d0678a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 118 additions and 84 deletions

View File

@ -196,41 +196,6 @@ To target this environment, you'd export `UV_PROJECT_ENVIRONMENT=/usr/local`.
environment. The `--active` flag can be used to opt-in to respecting `VIRTUAL_ENV`. The environment. The `--active` flag can be used to opt-in to respecting `VIRTUAL_ENV`. The
`--no-active` flag can be used to silence the warning. `--no-active` flag can be used to silence the warning.
## Limited resolution environments
If your project supports a more limited set of platforms or Python versions, you can constrain the
set of solved platforms via the `environments` setting, which accepts a list of PEP 508 environment
markers. For example, to constrain the lockfile to macOS and Linux, and exclude Windows:
```toml title="pyproject.toml"
[tool.uv]
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]
```
See the [resolution documentation](../resolution.md#limited-resolution-environments) for more.
## Required environments
If your project _must_ support a specific platform or Python version, you can mark that platform as
required via the `required-environments` setting. For example, to require that the project supports
Intel macOS:
```toml title="pyproject.toml"
[tool.uv]
required-environments = [
"sys_platform == 'darwin' and platform_machine == 'x86_64'",
]
```
The `required-environments` setting is only relevant for packages that do not publish a source
distribution (like PyTorch), as such packages can _only_ be installed on environments covered by the
set of pre-built binary distributions (wheels) published by that package.
See the [resolution documentation](../resolution.md#required-environments) for more.
## Build isolation ## Build isolation
By default, uv builds all packages in isolated virtual environments, as per By default, uv builds all packages in isolated virtual environments, as per
@ -401,33 +366,12 @@ in the deployed environment without a dependency on the originating source code.
## Conflicting dependencies ## Conflicting dependencies
uv requires that all optional dependencies ("extras") declared by the project are compatible with uv requires resolves all project dependencies together, including optional dependencies ("extras")
each other and resolves all optional dependencies together when creating the lockfile. and dependency groups. If dependencies declared in one section are not compatible with those in
another section, uv will fail to resolve the requirements of the project with an error.
If optional dependencies declared in one extra are not compatible with those in another extra, uv uv supports explicit declaration of conflicting dependency groups. For example, to declare that the
will fail to resolve the requirements of the project with an error. `optional-dependency` groups `extra1` and `extra2` are incompatible:
To work around this, uv supports declaring conflicting extras. For example, consider two sets of
optional dependencies that conflict with one another:
```toml title="pyproject.toml"
[project.optional-dependencies]
extra1 = ["numpy==2.1.2"]
extra2 = ["numpy==2.0.0"]
```
If you run `uv lock` with the above dependencies, resolution will fail:
```console
$ uv lock
x No solution found when resolving dependencies:
`-> Because myproject[extra2] depends on numpy==2.0.0 and myproject[extra1] depends on numpy==2.1.2, we can conclude that myproject[extra1] and
myproject[extra2] are incompatible.
And because your project requires myproject[extra1] and myproject[extra2], we can conclude that your projects's requirements are unsatisfiable.
```
But if you specify that `extra1` and `extra2` are conflicting, uv will resolve them separately.
Specify conflicts in the `tool.uv` section:
```toml title="pyproject.toml" ```toml title="pyproject.toml"
[tool.uv] [tool.uv]
@ -439,25 +383,9 @@ conflicts = [
] ]
``` ```
Now, running `uv lock` will succeed. Note though, that now you cannot install both `extra1` and Or, to declare the development dependency groups `group1` and `group2` incompatible:
`extra2` at the same time:
```console
$ uv sync --extra extra1 --extra extra2
Resolved 3 packages in 14ms
error: extra `extra1`, extra `extra2` are incompatible with the declared conflicts: {`myproject[extra1]`, `myproject[extra2]`}
```
This error occurs because installing both `extra1` and `extra2` would result in installing two
different versions of a package into the same environment.
The above strategy for dealing with conflicting extras also works with dependency groups:
```toml title="pyproject.toml" ```toml title="pyproject.toml"
[dependency-groups]
group1 = ["numpy==2.1.2"]
group2 = ["numpy==2.0.0"]
[tool.uv] [tool.uv]
conflicts = [ conflicts = [
[ [
@ -467,4 +395,39 @@ conflicts = [
] ]
``` ```
The only difference with conflicting extras is that you need to use `group` instead of `extra`. See the [resolution documentation](../resolution.md#conflicting-dependencies) for more.
## Limited resolution environments
If your project supports a more limited set of platforms or Python versions, you can constrain the
set of solved platforms via the `environments` setting, which accepts a list of PEP 508 environment
markers. For example, to constrain the lockfile to macOS and Linux, and exclude Windows:
```toml title="pyproject.toml"
[tool.uv]
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]
```
See the [resolution documentation](../resolution.md#limited-resolution-environments) for more.
## Required environments
If your project _must_ support a specific platform or Python version, you can mark that platform as
required via the `required-environments` setting. For example, to require that the project supports
Intel macOS:
```toml title="pyproject.toml"
[tool.uv]
required-environments = [
"sys_platform == 'darwin' and platform_machine == 'x86_64'",
]
```
The `required-environments` setting is only relevant for packages that do not publish a source
distribution (like PyTorch), as such packages can _only_ be installed on environments covered by the
set of pre-built binary distributions (wheels) published by that package.
See the [resolution documentation](../resolution.md#required-environments) for more.

View File

@ -453,6 +453,77 @@ though only `name`, `version`, `requires-dist`, `requires-python`, and `provides
uv. The `version` field is also considered optional. If omitted, the metadata will be used for all uv. The `version` field is also considered optional. If omitted, the metadata will be used for all
versions of the specified package. versions of the specified package.
## Conflicting dependencies
uv requires that all optional dependencies ("extras") declared by the project are compatible with
each other and resolves all optional dependencies together when creating the lockfile.
If optional dependencies declared in one extra are not compatible with those in another extra, uv
will fail to resolve the requirements of the project with an error.
To work around this, uv supports declaring conflicting extras. For example, consider two sets of
optional dependencies that conflict with one another:
```toml title="pyproject.toml"
[project.optional-dependencies]
extra1 = ["numpy==2.1.2"]
extra2 = ["numpy==2.0.0"]
```
If you run `uv lock` with the above dependencies, resolution will fail:
```console
$ uv lock
x No solution found when resolving dependencies:
`-> Because myproject[extra2] depends on numpy==2.0.0 and myproject[extra1] depends on numpy==2.1.2, we can conclude that myproject[extra1] and
myproject[extra2] are incompatible.
And because your project requires myproject[extra1] and myproject[extra2], we can conclude that your projects's requirements are unsatisfiable.
```
But if you specify that `extra1` and `extra2` are conflicting, uv will resolve them separately.
Specify conflicts in the `tool.uv` section:
```toml title="pyproject.toml"
[tool.uv]
conflicts = [
[
{ extra = "extra1" },
{ extra = "extra2" },
],
]
```
Now, running `uv lock` will succeed. Note though, that now you cannot install both `extra1` and
`extra2` at the same time:
```console
$ uv sync --extra extra1 --extra extra2
Resolved 3 packages in 14ms
error: extra `extra1`, extra `extra2` are incompatible with the declared conflicts: {`myproject[extra1]`, `myproject[extra2]`}
```
This error occurs because installing both `extra1` and `extra2` would result in installing two
different versions of a package into the same environment.
The above strategy for dealing with conflicting extras also works with dependency groups:
```toml title="pyproject.toml"
[dependency-groups]
group1 = ["numpy==2.1.2"]
group2 = ["numpy==2.0.0"]
[tool.uv]
conflicts = [
[
{ group = "group1" },
{ group = "group2" },
],
]
```
The only difference from conflicting extras is that you need to use the `group` key instead of
`extra`.
## Lower bounds ## Lower bounds
By default, `uv add` adds lower bounds to dependencies and, when using uv to manage projects, uv By default, `uv add` adds lower bounds to dependencies and, when using uv to manage projects, uv
@ -513,11 +584,6 @@ reading and extracting archives in the following formats:
- lzma tarball (`.tar.lzma`) - lzma tarball (`.tar.lzma`)
- zip (`.zip`) - zip (`.zip`)
## Learn more
For more details about the internals of the resolver, see the
[resolver reference](../reference/resolver-internals.md) documentation.
## Lockfile versioning ## Lockfile versioning
The `uv.lock` file uses a versioned schema. The schema version is included in the `version` field of The `uv.lock` file uses a versioned schema. The schema version is included in the `version` field of
@ -539,3 +605,8 @@ other words, lockfiles may only be rejected across minor releases.
The `revision` field of the lockfile is used to track backwards compatible changes to the lockfile. The `revision` field of the lockfile is used to track backwards compatible changes to the lockfile.
For example, adding a new field to distributions. Changes to the revision will not cause older For example, adding a new field to distributions. Changes to the revision will not cause older
versions of uv to error. versions of uv to error.
## Learn more
For more details about the internals of the resolver, see the
[resolver reference](../reference/resolver-internals.md) documentation.