Support --with-requirements script.py and -r script.py to include inline dependency metadata from another script (#12763)

## Summary

Closes #6542 

## Test Plan

`cargo test`
This commit is contained in:
Ahmed Ilyas 2025-09-05 18:45:46 +02:00 committed by GitHub
parent e136a51f3d
commit 6eefde28e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 410 additions and 9 deletions

1
Cargo.lock generated
View file

@ -6189,6 +6189,7 @@ dependencies = [
"uv-redacted", "uv-redacted",
"uv-requirements-txt", "uv-requirements-txt",
"uv-resolver", "uv-resolver",
"uv-scripts",
"uv-types", "uv-types",
"uv-warnings", "uv-warnings",
"uv-workspace", "uv-workspace",

View file

@ -1836,7 +1836,7 @@ pub struct PipInstallArgs {
#[arg(group = "sources")] #[arg(group = "sources")]
pub package: Vec<String>, pub package: Vec<String>,
/// Install all packages listed in the given `requirements.txt` or `pylock.toml` files. /// Install all packages listed in the given `requirements.txt`, PEP 723 scripts, or `pylock.toml` files.
/// ///
/// If a `pyproject.toml`, `setup.py`, or `setup.cfg` file is provided, uv will extract the /// If a `pyproject.toml`, `setup.py`, or `setup.cfg` file is provided, uv will extract the
/// requirements for the relevant project. /// requirements for the relevant project.
@ -3205,7 +3205,8 @@ pub struct RunArgs {
#[arg(long)] #[arg(long)]
pub with_editable: Vec<comma::CommaSeparatedRequirements>, pub with_editable: Vec<comma::CommaSeparatedRequirements>,
/// Run with all packages listed in the given `requirements.txt` files. /// Run with all packages listed in the given `requirements.txt` files or PEP 723 Python
/// scripts.
/// ///
/// The same environment semantics as `--with` apply. /// The same environment semantics as `--with` apply.
/// ///
@ -4575,7 +4576,8 @@ pub struct ToolRunArgs {
#[arg(long)] #[arg(long)]
pub with_editable: Vec<comma::CommaSeparatedRequirements>, pub with_editable: Vec<comma::CommaSeparatedRequirements>,
/// Run with all packages listed in the given `requirements.txt` files. /// Run with all packages listed in the given `requirements.txt` files or PEP 723 Python
/// scripts.
#[arg(long, value_delimiter = ',', value_parser = parse_maybe_file_path)] #[arg(long, value_delimiter = ',', value_parser = parse_maybe_file_path)]
pub with_requirements: Vec<Maybe<PathBuf>>, pub with_requirements: Vec<Maybe<PathBuf>>,
@ -4705,7 +4707,8 @@ pub struct ToolInstallArgs {
#[arg(short = 'w', long)] #[arg(short = 'w', long)]
pub with: Vec<comma::CommaSeparatedRequirements>, pub with: Vec<comma::CommaSeparatedRequirements>,
/// Include all requirements listed in the given `requirements.txt` files. /// Run with all packages listed in the given `requirements.txt` files or PEP 723 Python
/// scripts.
#[arg(long, value_delimiter = ',', value_parser = parse_maybe_file_path)] #[arg(long, value_delimiter = ',', value_parser = parse_maybe_file_path)]
pub with_requirements: Vec<Maybe<PathBuf>>, pub with_requirements: Vec<Maybe<PathBuf>>,

View file

@ -31,6 +31,7 @@ uv-pypi-types = { workspace = true }
uv-redacted = { workspace = true } uv-redacted = { workspace = true }
uv-requirements-txt = { workspace = true, features = ["http"] } uv-requirements-txt = { workspace = true, features = ["http"] }
uv-resolver = { workspace = true, features = ["clap"] } uv-resolver = { workspace = true, features = ["clap"] }
uv-scripts = { workspace = true }
uv-types = { workspace = true } uv-types = { workspace = true }
uv-warnings = { workspace = true } uv-warnings = { workspace = true }
uv-workspace = { workspace = true } uv-workspace = { workspace = true }

View file

@ -13,6 +13,8 @@ pub enum RequirementsSource {
Package(RequirementsTxtRequirement), Package(RequirementsTxtRequirement),
/// An editable path was provided on the command line (e.g., `pip install -e ../flask`). /// An editable path was provided on the command line (e.g., `pip install -e ../flask`).
Editable(RequirementsTxtRequirement), Editable(RequirementsTxtRequirement),
/// Dependencies were provided via a PEP 723 script.
Pep723Script(PathBuf),
/// Dependencies were provided via a `pylock.toml` file. /// Dependencies were provided via a `pylock.toml` file.
PylockToml(PathBuf), PylockToml(PathBuf),
/// Dependencies were provided via a `requirements.txt` file (e.g., `pip install -r requirements.txt`). /// Dependencies were provided via a `requirements.txt` file (e.g., `pip install -r requirements.txt`).
@ -44,6 +46,12 @@ impl RequirementsSource {
.is_some_and(|file_name| file_name.to_str().is_some_and(is_pylock_toml)) .is_some_and(|file_name| file_name.to_str().is_some_and(is_pylock_toml))
{ {
Ok(Self::PylockToml(path)) Ok(Self::PylockToml(path))
} else if path
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("py") || ext.eq_ignore_ascii_case("pyw"))
{
// TODO(blueraft): Support scripts without an extension.
Ok(Self::Pep723Script(path))
} else if path } else if path
.extension() .extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("toml")) .is_some_and(|ext| ext.eq_ignore_ascii_case("toml"))
@ -290,6 +298,7 @@ impl std::fmt::Display for RequirementsSource {
Self::Editable(path) => write!(f, "-e {path:?}"), Self::Editable(path) => write!(f, "-e {path:?}"),
Self::PylockToml(path) Self::PylockToml(path)
| Self::RequirementsTxt(path) | Self::RequirementsTxt(path)
| Self::Pep723Script(path)
| Self::PyprojectToml(path) | Self::PyprojectToml(path)
| Self::SetupPy(path) | Self::SetupPy(path)
| Self::SetupCfg(path) | Self::SetupCfg(path)

View file

@ -37,7 +37,7 @@ use tracing::instrument;
use uv_cache_key::CanonicalUrl; use uv_cache_key::CanonicalUrl;
use uv_client::BaseClientBuilder; use uv_client::BaseClientBuilder;
use uv_configuration::{DependencyGroups, NoBinary, NoBuild}; use uv_configuration::{DependencyGroups, NoBinary, NoBuild};
use uv_distribution_types::Requirement; use uv_distribution_types::{Index, Requirement};
use uv_distribution_types::{ use uv_distribution_types::{
IndexUrl, NameRequirementSpecification, UnresolvedRequirement, IndexUrl, NameRequirementSpecification, UnresolvedRequirement,
UnresolvedRequirementSpecification, UnresolvedRequirementSpecification,
@ -45,6 +45,7 @@ use uv_distribution_types::{
use uv_fs::{CWD, Simplified}; use uv_fs::{CWD, Simplified};
use uv_normalize::{ExtraName, PackageName, PipGroupName}; use uv_normalize::{ExtraName, PackageName, PipGroupName};
use uv_requirements_txt::{RequirementsTxt, RequirementsTxtRequirement}; use uv_requirements_txt::{RequirementsTxt, RequirementsTxtRequirement};
use uv_scripts::{Pep723Error, Pep723Item, Pep723Script};
use uv_warnings::warn_user; use uv_warnings::warn_user;
use uv_workspace::pyproject::PyProjectToml; use uv_workspace::pyproject::PyProjectToml;
@ -181,6 +182,125 @@ impl RequirementsSpecification {
..Self::default() ..Self::default()
} }
} }
RequirementsSource::Pep723Script(path) => {
let script = match Pep723Script::read(&path).await {
Ok(Some(script)) => Pep723Item::Script(script),
Ok(None) => {
return Err(anyhow::anyhow!(
"`{}` does not contain inline script metadata",
path.user_display(),
));
}
Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
return Err(anyhow::anyhow!(
"Failed to read `{}` (not found)",
path.user_display(),
));
}
Err(err) => return Err(err.into()),
};
let metadata = script.metadata();
let requirements = metadata
.dependencies
.as_ref()
.map(|dependencies| {
dependencies
.iter()
.map(|dependency| {
UnresolvedRequirementSpecification::from(Requirement::from(
dependency.to_owned(),
))
})
.collect::<Vec<UnresolvedRequirementSpecification>>()
})
.unwrap_or_default();
if let Some(tool_uv) = metadata.tool.as_ref().and_then(|tool| tool.uv.as_ref()) {
let constraints = tool_uv
.constraint_dependencies
.as_ref()
.map(|dependencies| {
dependencies
.iter()
.map(|dependency| {
NameRequirementSpecification::from(Requirement::from(
dependency.to_owned(),
))
})
.collect::<Vec<NameRequirementSpecification>>()
})
.unwrap_or_default();
let overrides = tool_uv
.override_dependencies
.as_ref()
.map(|dependencies| {
dependencies
.iter()
.map(|dependency| {
UnresolvedRequirementSpecification::from(Requirement::from(
dependency.to_owned(),
))
})
.collect::<Vec<UnresolvedRequirementSpecification>>()
})
.unwrap_or_default();
Self {
requirements,
constraints,
overrides,
index_url: tool_uv
.top_level
.index_url
.as_ref()
.map(|index| Index::from(index.clone()).url),
extra_index_urls: tool_uv
.top_level
.extra_index_url
.as_ref()
.into_iter()
.flat_map(|urls| {
urls.iter().map(|index| Index::from(index.clone()).url)
})
.collect(),
no_index: tool_uv.top_level.no_index.unwrap_or_default(),
find_links: tool_uv
.top_level
.find_links
.as_ref()
.into_iter()
.flat_map(|urls| {
urls.iter().map(|index| Index::from(index.clone()).url)
})
.collect(),
no_binary: NoBinary::from_args(
tool_uv.top_level.no_binary,
tool_uv
.top_level
.no_binary_package
.clone()
.unwrap_or_default(),
),
no_build: NoBuild::from_args(
tool_uv.top_level.no_build,
tool_uv
.top_level
.no_build_package
.clone()
.unwrap_or_default(),
),
..Self::default()
}
} else {
Self {
requirements,
..Self::default()
}
}
}
RequirementsSource::SetupPy(path) | RequirementsSource::SetupCfg(path) => { RequirementsSource::SetupPy(path) | RequirementsSource::SetupCfg(path) => {
if !path.is_file() { if !path.is_file() {
return Err(anyhow::anyhow!("File not found: `{}`", path.user_display())); return Err(anyhow::anyhow!("File not found: `{}`", path.user_display()));

View file

@ -125,6 +125,9 @@ pub(crate) async fn add(
RequirementsSource::SetupPy(_) => { RequirementsSource::SetupPy(_) => {
bail!("Adding requirements from a `setup.py` is not supported in `uv add`"); bail!("Adding requirements from a `setup.py` is not supported in `uv add`");
} }
RequirementsSource::Pep723Script(_) => {
bail!("Adding requirements from a PEP 723 script is not supported in `uv add`");
}
RequirementsSource::SetupCfg(_) => { RequirementsSource::SetupCfg(_) => {
bail!("Adding requirements from a `setup.cfg` is not supported in `uv add`"); bail!("Adding requirements from a `setup.cfg` is not supported in `uv add`");
} }

View file

@ -757,6 +757,71 @@ werkzeug==3.0.1
Ok(()) Ok(())
} }
#[test]
fn install_with_dependencies_from_script() -> Result<()> {
let context = TestContext::new("3.12");
let script = context.temp_dir.child("script.py");
script.write_str(indoc! {r#"
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "anyio",
# ]
# ///
import anyio
"#})?;
uv_snapshot!(context.pip_install()
.arg("-r")
.arg("script.py")
.arg("--strict"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 3 packages in [TIME]
Prepared 3 packages in [TIME]
Installed 3 packages in [TIME]
+ anyio==4.3.0
+ idna==3.6
+ sniffio==1.3.1
"
);
// Update the script file.
script.write_str(indoc! {r#"
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "anyio",
# "iniconfig",
# ]
# ///
import anyio
"#})?;
uv_snapshot!(context.pip_install()
.arg("-r")
.arg("script.py")
.arg("--strict"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 4 packages in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"
);
Ok(())
}
/// Install a `pyproject.toml` file with a `poetry` section. /// Install a `pyproject.toml` file with a `poetry` section.
#[test] #[test]
fn install_pyproject_toml_poetry() -> Result<()> { fn install_pyproject_toml_poetry() -> Result<()> {

View file

@ -2026,6 +2026,131 @@ fn tool_install_unnamed_with() {
"###); "###);
} }
#[test]
fn tool_install_with_dependencies_from_script() -> Result<()> {
let context = TestContext::new("3.12")
.with_filtered_counts()
.with_filtered_exe_suffix();
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");
let script = context.temp_dir.child("script.py");
script.write_str(indoc! {r#"
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "anyio",
# ]
# ///
import anyio
"#})?;
// script dependencies (anyio) are now installed.
uv_snapshot!(context.filters(), context.tool_install()
.arg("--with-requirements")
.arg("script.py")
.arg("black")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
.env(EnvVars::PATH, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Installed [N] packages in [TIME]
+ anyio==4.3.0
+ black==24.3.0
+ click==8.1.7
+ idna==3.6
+ mypy-extensions==1.0.0
+ packaging==24.0
+ pathspec==0.12.1
+ platformdirs==4.2.0
+ sniffio==1.3.1
Installed 2 executables: black, blackd
");
insta::with_settings!({
filters => context.filters(),
}, {
// We should have a tool receipt
assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r#"
[tool]
requirements = [
{ name = "black" },
{ name = "anyio" },
]
entrypoints = [
{ name = "black", install-path = "[TEMP_DIR]/bin/black", from = "black" },
{ name = "blackd", install-path = "[TEMP_DIR]/bin/blackd", from = "black" },
]
[tool.options]
exclude-newer = "2024-03-25T00:00:00Z"
"#);
});
// Update the script file.
script.write_str(indoc! {r#"
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "anyio",
# "iniconfig",
# ]
# ///
import anyio
"#})?;
// Install `black`
uv_snapshot!(context.filters(), context.tool_install()
.arg("black")
.arg("--with-requirements")
.arg("script.py")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
.env(EnvVars::PATH, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Installed [N] packages in [TIME]
+ iniconfig==2.0.0
Installed 2 executables: black, blackd
");
insta::with_settings!({
filters => context.filters(),
}, {
// We should have a tool receipt
assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r#"
[tool]
requirements = [
{ name = "black" },
{ name = "anyio" },
{ name = "iniconfig" },
]
entrypoints = [
{ name = "black", install-path = "[TEMP_DIR]/bin/black", from = "black" },
{ name = "blackd", install-path = "[TEMP_DIR]/bin/blackd", from = "black" },
]
[tool.options]
exclude-newer = "2024-03-25T00:00:00Z"
"#);
});
Ok(())
}
/// Test installing a tool with additional requirements from a `requirements.txt` file. /// Test installing a tool with additional requirements from a `requirements.txt` file.
#[test] #[test]
fn tool_install_requirements_txt() { fn tool_install_requirements_txt() {

View file

@ -2658,6 +2658,80 @@ fn tool_run_with_incompatible_build_constraints() -> Result<()> {
Ok(()) Ok(())
} }
#[test]
fn tool_run_with_dependencies_from_script() -> Result<()> {
let context = TestContext::new("3.12").with_filtered_counts();
let script = context.temp_dir.child("script.py");
script.write_str(indoc! {r#"
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "anyio",
# ]
# ///
import anyio
"#})?;
// script dependencies (anyio) are now installed.
uv_snapshot!(context.filters(), context.tool_run()
.arg("--with-requirements")
.arg("script.py")
.arg("black")
.arg("script.py")
.arg("-q"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Installed [N] packages in [TIME]
+ anyio==4.3.0
+ black==24.3.0
+ click==8.1.7
+ idna==3.6
+ mypy-extensions==1.0.0
+ packaging==24.0
+ pathspec==0.12.1
+ platformdirs==4.2.0
+ sniffio==1.3.1
");
// Error when the script is not a valid PEP723 script.
let script = context.temp_dir.child("not_pep723_script.py");
script.write_str("import anyio")?;
uv_snapshot!(context.filters(), context.tool_run()
.arg("--with-requirements")
.arg("not_pep723_script.py")
.arg("black"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: `not_pep723_script.py` does not contain inline script metadata
");
// Error when the script doesn't exist.
uv_snapshot!(context.filters(), context.tool_run()
.arg("--with-requirements")
.arg("missing_file.py")
.arg("black"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Failed to read `missing_file.py` (not found)
");
Ok(())
}
/// Test windows runnable types, namely console scripts and legacy setuptools scripts. /// Test windows runnable types, namely console scripts and legacy setuptools scripts.
/// Console Scripts <https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#console-scripts> /// Console Scripts <https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#console-scripts>
/// Legacy Scripts <https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#scripts>. /// Legacy Scripts <https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#scripts>.

View file

@ -611,7 +611,7 @@ used.</p>
<p>When used in a project, these dependencies will be layered on top of the project environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified by the project.</p> <p>When used in a project, these dependencies will be layered on top of the project environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified by the project.</p>
</dd><dt id="uv-run--with-editable"><a href="#uv-run--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Run with the given packages installed in editable mode.</p> </dd><dt id="uv-run--with-editable"><a href="#uv-run--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Run with the given packages installed in editable mode.</p>
<p>When used in a project, these dependencies will be layered on top of the project environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified by the project.</p> <p>When used in a project, these dependencies will be layered on top of the project environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified by the project.</p>
</dd><dt id="uv-run--with-requirements"><a href="#uv-run--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Run with all packages listed in the given <code>requirements.txt</code> files.</p> </dd><dt id="uv-run--with-requirements"><a href="#uv-run--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Run with all packages listed in the given <code>requirements.txt</code> files or PEP 723 Python scripts.</p>
<p>The same environment semantics as <code>--with</code> apply.</p> <p>The same environment semantics as <code>--with</code> apply.</p>
<p>Using <code>pyproject.toml</code>, <code>setup.py</code>, or <code>setup.cfg</code> files is not allowed.</p> <p>Using <code>pyproject.toml</code>, <code>setup.py</code>, or <code>setup.cfg</code> files is not allowed.</p>
</dd></dl> </dd></dl>
@ -2546,7 +2546,7 @@ uv tool run [OPTIONS] [COMMAND]
</dd><dt id="uv-tool-run--with"><a href="#uv-tool-run--with"><code>--with</code></a>, <code>-w</code> <i>with</i></dt><dd><p>Run with the given packages installed</p> </dd><dt id="uv-tool-run--with"><a href="#uv-tool-run--with"><code>--with</code></a>, <code>-w</code> <i>with</i></dt><dd><p>Run with the given packages installed</p>
</dd><dt id="uv-tool-run--with-editable"><a href="#uv-tool-run--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Run with the given packages installed in editable mode</p> </dd><dt id="uv-tool-run--with-editable"><a href="#uv-tool-run--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Run with the given packages installed in editable mode</p>
<p>When used in a project, these dependencies will be layered on top of the uv tool's environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified.</p> <p>When used in a project, these dependencies will be layered on top of the uv tool's environment in a separate, ephemeral environment. These dependencies are allowed to conflict with those specified.</p>
</dd><dt id="uv-tool-run--with-requirements"><a href="#uv-tool-run--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Run with all packages listed in the given <code>requirements.txt</code> files</p> </dd><dt id="uv-tool-run--with-requirements"><a href="#uv-tool-run--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Run with all packages listed in the given <code>requirements.txt</code> files or PEP 723 Python scripts</p>
</dd></dl> </dd></dl>
### uv tool install ### uv tool install
@ -2773,7 +2773,7 @@ uv tool install [OPTIONS] <PACKAGE>
</dd><dt id="uv-tool-install--with"><a href="#uv-tool-install--with"><code>--with</code></a>, <code>-w</code> <i>with</i></dt><dd><p>Include the following additional requirements</p> </dd><dt id="uv-tool-install--with"><a href="#uv-tool-install--with"><code>--with</code></a>, <code>-w</code> <i>with</i></dt><dd><p>Include the following additional requirements</p>
</dd><dt id="uv-tool-install--with-editable"><a href="#uv-tool-install--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Include the given packages in editable mode</p> </dd><dt id="uv-tool-install--with-editable"><a href="#uv-tool-install--with-editable"><code>--with-editable</code></a> <i>with-editable</i></dt><dd><p>Include the given packages in editable mode</p>
</dd><dt id="uv-tool-install--with-executables-from"><a href="#uv-tool-install--with-executables-from"><code>--with-executables-from</code></a> <i>with-executables-from</i></dt><dd><p>Install executables from the following packages</p> </dd><dt id="uv-tool-install--with-executables-from"><a href="#uv-tool-install--with-executables-from"><code>--with-executables-from</code></a> <i>with-executables-from</i></dt><dd><p>Install executables from the following packages</p>
</dd><dt id="uv-tool-install--with-requirements"><a href="#uv-tool-install--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Include all requirements listed in the given <code>requirements.txt</code> files</p> </dd><dt id="uv-tool-install--with-requirements"><a href="#uv-tool-install--with-requirements"><code>--with-requirements</code></a> <i>with-requirements</i></dt><dd><p>Run with all packages listed in the given <code>requirements.txt</code> files or PEP 723 Python scripts</p>
</dd></dl> </dd></dl>
### uv tool upgrade ### uv tool upgrade
@ -4808,7 +4808,7 @@ should be used with caution, as it can modify the system Python installation.</p
<ul> <ul>
<li>Git dependencies are not supported. - Editable installations are not supported. - Local dependencies are not supported, unless they point to a specific wheel (<code>.whl</code>) or source archive (<code>.zip</code>, <code>.tar.gz</code>), as opposed to a directory.</li> <li>Git dependencies are not supported. - Editable installations are not supported. - Local dependencies are not supported, unless they point to a specific wheel (<code>.whl</code>) or source archive (<code>.zip</code>, <code>.tar.gz</code>), as opposed to a directory.</li>
</ul> </ul>
<p>May also be set with the <code>UV_REQUIRE_HASHES</code> environment variable.</p></dd><dt id="uv-pip-install--requirements"><a href="#uv-pip-install--requirements"><code>--requirements</code></a>, <code>--requirement</code>, <code>-r</code> <i>requirements</i></dt><dd><p>Install all packages listed in the given <code>requirements.txt</code> or <code>pylock.toml</code> files.</p> <p>May also be set with the <code>UV_REQUIRE_HASHES</code> environment variable.</p></dd><dt id="uv-pip-install--requirements"><a href="#uv-pip-install--requirements"><code>--requirements</code></a>, <code>--requirement</code>, <code>-r</code> <i>requirements</i></dt><dd><p>Install all packages listed in the given <code>requirements.txt</code>, PEP 723 scripts, or <code>pylock.toml</code> files.</p>
<p>If a <code>pyproject.toml</code>, <code>setup.py</code>, or <code>setup.cfg</code> file is provided, uv will extract the requirements for the relevant project.</p> <p>If a <code>pyproject.toml</code>, <code>setup.py</code>, or <code>setup.cfg</code> file is provided, uv will extract the requirements for the relevant project.</p>
<p>If <code>-</code> is provided, then requirements will be read from stdin.</p> <p>If <code>-</code> is provided, then requirements will be read from stdin.</p>
</dd><dt id="uv-pip-install--resolution"><a href="#uv-pip-install--resolution"><code>--resolution</code></a> <i>resolution</i></dt><dd><p>The strategy to use when selecting between the different compatible versions for a given package requirement.</p> </dd><dt id="uv-pip-install--resolution"><a href="#uv-pip-install--resolution"><code>--resolution</code></a> <i>resolution</i></dt><dd><p>The strategy to use when selecting between the different compatible versions for a given package requirement.</p>