mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Merge a08d1802b5
into f609e1ddaf
This commit is contained in:
commit
7ed590cc3b
9 changed files with 201 additions and 1 deletions
|
@ -379,6 +379,7 @@ pub struct ToolUv {
|
|||
#[serde(flatten)]
|
||||
pub top_level: ResolverInstallerOptions,
|
||||
pub override_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
pub excluded_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
pub constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
pub build_constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
pub sources: Option<BTreeMap<PackageName, Sources>>,
|
||||
|
|
|
@ -111,6 +111,9 @@ pub struct Options {
|
|||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
pub override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
pub excluded_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
|
||||
|
@ -1860,6 +1863,7 @@ pub struct OptionsWire {
|
|||
// `crates/uv-workspace/src/pyproject.rs`. The documentation lives on that struct.
|
||||
// They're respected in both `pyproject.toml` and `uv.toml` files.
|
||||
override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
excluded_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
|
||||
environments: Option<SupportedEnvironments>,
|
||||
|
@ -1928,6 +1932,7 @@ impl From<OptionsWire> for Options {
|
|||
pip,
|
||||
cache_keys,
|
||||
override_dependencies,
|
||||
excluded_dependencies,
|
||||
constraint_dependencies,
|
||||
build_constraint_dependencies,
|
||||
environments,
|
||||
|
@ -1996,6 +2001,7 @@ impl From<OptionsWire> for Options {
|
|||
cache_keys,
|
||||
build_backend,
|
||||
override_dependencies,
|
||||
excluded_dependencies,
|
||||
constraint_dependencies,
|
||||
build_constraint_dependencies,
|
||||
environments,
|
||||
|
|
|
@ -435,6 +435,37 @@ pub struct ToolUv {
|
|||
)]
|
||||
pub override_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
|
||||
/// Excludes to apply when resolving the project's dependencies.
|
||||
///
|
||||
/// Excludes are used to prevent installation of a specific package, even if other dependencies
|
||||
/// require it.
|
||||
///
|
||||
/// Including a package as an exclude will _not_ trigger installation of the package on its
|
||||
/// own; instead, the package must be requested elsewhere in the project's first-party or
|
||||
/// transitive dependencies.
|
||||
///
|
||||
/// !!! note
|
||||
/// In `uv lock`, `uv sync`, and `uv run`, uv will only read `excluded-dependencies` from
|
||||
/// the `pyproject.toml` at the workspace root, and will ignore any declarations in other
|
||||
/// workspace members or `uv.toml` files.
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
schemars(
|
||||
with = "Option<Vec<String>>",
|
||||
description = "PEP 508-style requirements, e.g., `ruff==0.5.0`, or `ruff @ https://...`."
|
||||
)
|
||||
)]
|
||||
#[option(
|
||||
default = "[]",
|
||||
value_type = "list[str]",
|
||||
example = r#"
|
||||
# Always install Werkzeug 2.3.0, regardless of whether transitive dependencies request
|
||||
# a different version.
|
||||
excluded-dependencies = ["numpy"]
|
||||
"#
|
||||
)]
|
||||
pub excluded_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||
|
||||
/// Constraints to apply when resolving the project's dependencies.
|
||||
///
|
||||
/// Constraints are used to restrict the versions of dependencies that are selected during
|
||||
|
|
|
@ -1870,6 +1870,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
@ -1966,6 +1967,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
@ -2177,6 +2179,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
@ -2285,6 +2288,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
@ -2406,6 +2410,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
@ -2501,6 +2506,7 @@ mod tests {
|
|||
"dependency-groups": null,
|
||||
"dev-dependencies": null,
|
||||
"override-dependencies": null,
|
||||
"excluded-dependencies": null,
|
||||
"constraint-dependencies": null,
|
||||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
|
|
|
@ -1711,6 +1711,66 @@ fn lock_project_with_overrides() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
/// Lock a project with `uv.tool.excluded-dependencies`
|
||||
#[test]
|
||||
fn lock_project_with_excluded_dependencies() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["pytest==7.4.0", "requests==2.31.0"]
|
||||
|
||||
[tool.uv]
|
||||
excluded-dependencies = ["pytest"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.lock(), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 11 packages in [TIME]
|
||||
");
|
||||
|
||||
// Re-run with `--locked`.
|
||||
uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 11 packages in [TIME]
|
||||
");
|
||||
|
||||
// Install the dependencies from the lockfile.
|
||||
uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Prepared 9 packages in [TIME]
|
||||
Installed 9 packages in [TIME]
|
||||
+ certifi==2024.2.2
|
||||
+ charset-normalizer==3.3.2
|
||||
+ idna==3.6
|
||||
+ iniconfig==2.0.0
|
||||
+ packaging==24.0
|
||||
+ pluggy==1.4.0
|
||||
+ pytest==7.4.0
|
||||
+ requests==2.31.0
|
||||
+ urllib3==2.2.1
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lock a project with `uv.tool.override-dependencies` that reference `tool.uv.sources`.
|
||||
#[test]
|
||||
|
|
|
@ -3920,6 +3920,61 @@ fn override_dependency_from_pyproject() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Check the `tool.uv.excluded-dependencies` in `pyproject.toml` is respected
|
||||
/// Check that `tool.uv.excluded-dependencies` in `pyproject.toml` excludes dependencies.
|
||||
#[test]
|
||||
fn exclude_dependency_from_pyproject() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"[project]
|
||||
name = "example"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"flask==3.0.0"
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
excluded-dependencies = [
|
||||
"werkzeug"
|
||||
]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.pip_compile()
|
||||
.arg("pyproject.toml")
|
||||
.current_dir(&context.temp_dir)
|
||||
, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile --cache-dir [CACHE_DIR] pyproject.toml
|
||||
blinker==1.7.0
|
||||
# via flask
|
||||
click==8.1.7
|
||||
# via flask
|
||||
flask==3.0.0
|
||||
# via example (pyproject.toml)
|
||||
itsdangerous==2.1.2
|
||||
# via flask
|
||||
jinja2==3.1.3
|
||||
# via flask
|
||||
markupsafe==2.1.5
|
||||
# via
|
||||
# jinja2
|
||||
# werkzeug
|
||||
werkzeug==3.0.1
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 7 packages in [TIME]
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check that `tool.uv.constraint-dependencies` in `pyproject.toml` is respected.
|
||||
#[test]
|
||||
fn constraint_dependency_from_pyproject() -> Result<()> {
|
||||
|
|
|
@ -3987,7 +3987,7 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
|||
|
|
||||
1 | [project]
|
||||
| ^^^^^^^
|
||||
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `no-build-isolation`, `no-build-isolation-package`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
||||
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `no-build-isolation`, `no-build-isolation-package`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `excluded-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
||||
"
|
||||
);
|
||||
|
||||
|
|
|
@ -202,6 +202,37 @@ environments = ["sys_platform == 'darwin'"]
|
|||
|
||||
---
|
||||
|
||||
### [`excluded-dependencies`](#excluded-dependencies) {: #excluded-dependencies }
|
||||
|
||||
Excludes to apply when resolving the project's dependencies.
|
||||
|
||||
Excludes are used to prevent installation of a specific package, even if other dependencies
|
||||
require it.
|
||||
|
||||
Including a package as an exclude will _not_ trigger installation of the package on its
|
||||
own; instead, the package must be requested elsewhere in the project's first-party or
|
||||
transitive dependencies.
|
||||
|
||||
!!! note
|
||||
In `uv lock`, `uv sync`, and `uv run`, uv will only read `excluded-dependencies` from
|
||||
the `pyproject.toml` at the workspace root, and will ignore any declarations in other
|
||||
workspace members or `uv.toml` files.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv]
|
||||
# Always install Werkzeug 2.3.0, regardless of whether transitive dependencies request
|
||||
# a different version.
|
||||
excluded-dependencies = ["numpy"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### [`index`](#index) {: #index }
|
||||
|
||||
The indexes to use when resolving dependencies.
|
||||
|
|
10
uv.schema.json
generated
10
uv.schema.json
generated
|
@ -203,6 +203,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"excluded-dependencies": {
|
||||
"description": "PEP 508-style requirements, e.g., `ruff==0.5.0`, or `ruff @ https://...`.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"extra-index-url": {
|
||||
"description": "Extra URLs of package indexes to use, in addition to `--index-url`.\n\nAccepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)\n(the simple repository API), or a local directory laid out in the same format.\n\nAll indexes provided via this flag take priority over the index specified by\n[`index_url`](#index-url) or [`index`](#index) with `default = true`. When multiple indexes\nare provided, earlier values take priority.\n\nTo control uv's resolution strategy when multiple indexes are present, see\n[`index_strategy`](#index-strategy).\n\n(Deprecated: use `index` instead.)",
|
||||
"type": [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue