feat: add support for --no-extra flag and setting (#9387)

<!--  
Thank you for contributing to uv! To help us review effectively, please
ensure that:
- The pull request includes a summary of the change.  
- The title is descriptive and concise.  
- Relevant issues are referenced where applicable.  
-->

## Summary

Resolves #9333  

This pull request introduces support for the `--no-extra` command-line
flag and the corresponding `no-extra` UV setting.

### Behavior
- When `--all-extras` is supplied, the specified extras in `--no-extra`
will be excluded from the installation.
- If `--all-extras` is not supplied, `--no-extra` has no effect and is
safely ignored.

## Test Plan

Since `ExtrasSpecification::from_args` and
`ExtrasSpecification::extra_names` are the most important parts in the
implementation, I added the following tests in the
`uv-configuration/src/extras.rs` module:

- **`test_no_extra_full`**: Verifies behavior when `no_extra` includes
the entire list of extras.
- **`test_no_extra_partial`**: Tests partial exclusion, ensuring only
specified extras are excluded.
- **`test_no_extra_empty`**: Confirms that no extras are excluded if
`no_extra` is empty.
- **`test_no_extra_excessive`**: Ensures the implementation ignores
`no_extra` values that don't match any available extras.
- **`test_no_extra_without_all_extras`**: Validates that `no_extra` has
no effect when `--all-extras` is not supplied.
- **`test_no_extra_without_package_extras`**: Confirms correct behavior
when no extras are available in the package.
- **`test_no_extra_duplicates`**: Verifies that duplicate entries in
`pkg_extras` or `no_extra` do not cause errors.

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
Li-Lun Lin
2024-11-24 10:25:09 +08:00
committed by GitHub
parent c63616c190
commit e485dfd7f1
12 changed files with 297 additions and 32 deletions

View File

@@ -308,6 +308,10 @@ uv run [OPTIONS] [COMMAND]
</dd><dt><code>--no-env-file</code></dt><dd><p>Avoid reading environment variables from a <code>.env</code> file</p>
<p>May also be set with the <code>UV_NO_ENV_FILE</code> environment variable.</p>
</dd><dt><code>--no-extra</code> <i>no-extra</i></dt><dd><p>Exclude the specified optional dependencies, if <code>--all-extras</code> is supplied.</p>
<p>May be provided multiple times.</p>
</dd><dt><code>--no-group</code> <i>no-group</i></dt><dd><p>Exclude dependencies from the specified dependency group.</p>
<p>May be provided multiple times.</p>
@@ -1612,6 +1616,10 @@ uv sync [OPTIONS]
</dd><dt><code>--no-editable</code></dt><dd><p>Install any editable dependencies, including the project and any workspace members, as non-editable</p>
</dd><dt><code>--no-extra</code> <i>no-extra</i></dt><dd><p>Exclude the specified optional dependencies, if <code>--all-extras</code> is supplied.</p>
<p>May be provided multiple times.</p>
</dd><dt><code>--no-group</code> <i>no-group</i></dt><dd><p>Exclude dependencies from the specified dependency group.</p>
<p>May be provided multiple times.</p>
@@ -2286,6 +2294,10 @@ uv export [OPTIONS]
<p>By default, all workspace members and their dependencies are included in the exported requirements file, with all of their dependencies. The <code>--no-emit-workspace</code> option allows exclusion of all the workspace members while retaining their dependencies.</p>
</dd><dt><code>--no-extra</code> <i>no-extra</i></dt><dd><p>Exclude the specified optional dependencies, if <code>--all-extras</code> is supplied.</p>
<p>May be provided multiple times.</p>
</dd><dt><code>--no-group</code> <i>no-group</i></dt><dd><p>Exclude dependencies from the specified dependency group.</p>
<p>May be provided multiple times.</p>

View File

@@ -2431,6 +2431,34 @@ included in the resolution. Equivalent to pip-compile's `--unsafe-package` optio
---
#### [`no-extra`](#pip_no-extra) {: #pip_no-extra }
<span id="no-extra"></span>
Exclude the specified optional dependencies if `all-extras` is supplied.
**Default value**: `[]`
**Type**: `list[str]`
**Example usage**:
=== "pyproject.toml"
```toml
[tool.uv.pip]
all-extras = true
no-extra = ["dev", "docs"]
```
=== "uv.toml"
```toml
[pip]
all-extras = true
no-extra = ["dev", "docs"]
```
---
#### [`no-header`](#pip_no-header) {: #pip_no-header }
<span id="no-header"></span>