Skip to content

Commit

Permalink
Add UV_FIND_LINKS environment variable support for the `--find-link…
Browse files Browse the repository at this point in the history
…s` command-line option (#7912)

## Summary

This PR adds support for the `UV_FIND_LINKS` environment variable as an
alternative to the `--find-links` command-line option, as requested in
#1839.

## Test Plan

A unit test was added to validate that setting `UV_FIND_LINKS` provided
the same result as a link provided with the `--find-links` command-line
option.

---------

Co-authored-by: Charlie Marsh <[email protected]>
  • Loading branch information
SethMMorton and charliermarsh authored Oct 4, 2024
1 parent fc49587 commit c591636
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 11 deletions.
23 changes: 21 additions & 2 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,18 @@ fn parse_index_url(input: &str) -> Result<Maybe<IndexUrl>, String> {
}
}

/// Parse a string into an [`FlatIndexLocation`], mapping the empty string to `None`.
fn parse_flat_index(input: &str) -> Result<Maybe<FlatIndexLocation>, String> {
if input.is_empty() {
Ok(Maybe::None)
} else {
match FlatIndexLocation::from_str(input) {
Ok(url) => Ok(Maybe::Some(url)),
Err(err) => Err(err.to_string()),
}
}
}

/// Parse a string into an [`Url`], mapping the empty string to `None`.
fn parse_insecure_host(input: &str) -> Result<Maybe<TrustedHost>, String> {
if input.is_empty() {
Expand Down Expand Up @@ -3730,8 +3742,15 @@ pub struct IndexArgs {
///
/// If a URL, the page must contain a flat list of links to package files adhering to the
/// formats described above.
#[arg(long, short, help_heading = "Index options")]
pub find_links: Option<Vec<FlatIndexLocation>>,
#[arg(
long,
short,
env = "UV_FIND_LINKS",
value_delimiter = ' ',
value_parser = parse_flat_index,
help_heading = "Index options"
)]
pub find_links: Option<Vec<Maybe<FlatIndexLocation>>>,

/// Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those
/// provided via `--find-links`.
Expand Down
33 changes: 24 additions & 9 deletions crates/uv-cli/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,19 @@ impl From<IndexArgs> for PipOptions {

Self {
index_url: index_url.and_then(Maybe::into_option),
extra_index_url: extra_index_url.map(|extra_index_urls| {
extra_index_urls
extra_index_url: extra_index_url.map(|extra_index_url| {
extra_index_url
.into_iter()
.filter_map(Maybe::into_option)
.collect()
}),
no_index: if no_index { Some(true) } else { None },
find_links,
find_links: find_links.map(|find_links| {
find_links
.into_iter()
.filter_map(Maybe::into_option)
.collect()
}),
..PipOptions::default()
}
}
Expand Down Expand Up @@ -243,8 +248,8 @@ pub fn resolver_options(

ResolverOptions {
index_url: index_args.index_url.and_then(Maybe::into_option),
extra_index_url: index_args.extra_index_url.map(|extra_index_urls| {
extra_index_urls
extra_index_url: index_args.extra_index_url.map(|extra_index_url| {
extra_index_url
.into_iter()
.filter_map(Maybe::into_option)
.collect()
Expand All @@ -254,7 +259,12 @@ pub fn resolver_options(
} else {
None
},
find_links: index_args.find_links,
find_links: index_args.find_links.map(|find_links| {
find_links
.into_iter()
.filter_map(Maybe::into_option)
.collect()
}),
upgrade: flag(upgrade, no_upgrade),
upgrade_package: Some(upgrade_package),
index_strategy,
Expand Down Expand Up @@ -327,8 +337,8 @@ pub fn resolver_installer_options(

ResolverInstallerOptions {
index_url: index_args.index_url.and_then(Maybe::into_option),
extra_index_url: index_args.extra_index_url.map(|extra_index_urls| {
extra_index_urls
extra_index_url: index_args.extra_index_url.map(|extra_index_url| {
extra_index_url
.into_iter()
.filter_map(Maybe::into_option)
.collect()
Expand All @@ -338,7 +348,12 @@ pub fn resolver_installer_options(
} else {
None
},
find_links: index_args.find_links,
find_links: index_args.find_links.map(|find_links| {
find_links
.into_iter()
.filter_map(Maybe::into_option)
.collect()
}),
upgrade: flag(upgrade, no_upgrade),
upgrade_package: if upgrade_package.is_empty() {
None
Expand Down
27 changes: 27 additions & 0 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4593,6 +4593,33 @@ fn find_links_requirements_txt() -> Result<()> {
Ok(())
}

/// Compile using the `UV_FIND_LINKS` environment variable
#[test]
fn find_links_uv_env_var() -> Result<()> {
let context = TestContext::new("3.12");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("tqdm")?;

uv_snapshot!(context.filters(), context.pip_compile()
.arg("requirements.in")
.arg("--no-index")
.env("UV_FIND_LINKS", "https://download.pytorch.org/whl/torch_stable.html"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --no-index
tqdm==4.64.1
# via -r requirements.in
----- stderr -----
Resolved 1 package in [TIME]
"###
);

Ok(())
}

/// `extras==0.0.2` fails to build (i.e., it always throws). Since `extras==0.0.1` is pinned, we
/// should never even attempt to build `extras==0.0.2`, despite an unpinned `extras[dev]`
/// requirement.
Expand Down
2 changes: 2 additions & 0 deletions docs/configuration/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ uv accepts the following command-line arguments as environment variables:
URL as the base index for searching for packages.
- `UV_EXTRA_INDEX_URL`: Equivalent to the `--extra-index-url` command-line argument. If set, uv will
use this space-separated list of URLs as additional indexes when searching for packages.
- `UV_FIND_LINKS`: Equivalent to the `--find-links` command-line argument. If set, uv will use this
space-separated list of additional locations to search for packages.
- `UV_CACHE_DIR`: Equivalent to the `--cache-dir` command-line argument. If set, uv will use this
directory for caching instead of the default cache directory.
- `UV_NO_CACHE`: Equivalent to the `--no-cache` command-line argument. If set, uv will not use the
Expand Down
15 changes: 15 additions & 0 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ uv run [OPTIONS] <COMMAND>

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Run without updating the <code>uv.lock</code> file.</p>

<p>Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the source of truth. If the lockfile is missing, uv will exit with an error. If the <code>pyproject.toml</code> includes changes to dependencies that have not been included in the lockfile yet, they will not be present in the environment.</p>
Expand Down Expand Up @@ -692,6 +693,7 @@ uv add [OPTIONS] <PACKAGES|--requirements <REQUIREMENTS>>

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Add dependencies without re-locking the project.</p>

<p>The project environment will not be synced.</p>
Expand Down Expand Up @@ -1009,6 +1011,7 @@ uv remove [OPTIONS] <PACKAGES>...

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Remove dependencies without re-locking the project.</p>

<p>The project environment will not be synced.</p>
Expand Down Expand Up @@ -1314,6 +1317,7 @@ uv sync [OPTIONS]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Sync without updating the <code>uv.lock</code> file.</p>

<p>Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the source of truth. If the lockfile is missing, uv will exit with an error. If the <code>pyproject.toml</code> includes changes to dependencies that have not been included in the lockfile yet, they will not be present in the environment.</p>
Expand Down Expand Up @@ -1617,6 +1621,7 @@ uv lock [OPTIONS]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Assert that a <code>uv.lock</code> exists, without updating it</p>

</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>
Expand Down Expand Up @@ -1896,6 +1901,7 @@ uv export [OPTIONS]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--format</code> <i>format</i></dt><dd><p>The format to which <code>uv.lock</code> should be exported.</p>

<p>At present, only <code>requirements-txt</code> is supported.</p>
Expand Down Expand Up @@ -2204,6 +2210,7 @@ uv tree [OPTIONS]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--frozen</code></dt><dd><p>Display the requirements without locking the project.</p>

<p>If the lockfile is missing, uv will exit with an error.</p>
Expand Down Expand Up @@ -2575,6 +2582,7 @@ uv tool run [OPTIONS] [COMMAND]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--from</code> <i>from</i></dt><dd><p>Use the given package to provide the command.</p>

<p>By default, the package name is assumed to match the command name.</p>
Expand Down Expand Up @@ -2863,6 +2871,7 @@ uv tool install [OPTIONS] <PACKAGE>

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--force</code></dt><dd><p>Force installation of the tool.</p>

<p>Will replace any existing entry points with the same name in the executable directory.</p>
Expand Down Expand Up @@ -3147,6 +3156,7 @@ uv tool upgrade [OPTIONS] <NAME>...

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--index-strategy</code> <i>index-strategy</i></dt><dd><p>The strategy to use when resolving against multiple index URLs.</p>
Expand Down Expand Up @@ -4711,6 +4721,7 @@ uv pip compile [OPTIONS] <SRC_FILE>...

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--generate-hashes</code></dt><dd><p>Include distribution hashes in the output file</p>

</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>
Expand Down Expand Up @@ -5099,6 +5110,7 @@ uv pip sync [OPTIONS] <SRC_FILE>...

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--index-strategy</code> <i>index-strategy</i></dt><dd><p>The strategy to use when resolving against multiple index URLs.</p>
Expand Down Expand Up @@ -5441,6 +5453,7 @@ uv pip install [OPTIONS] <PACKAGE|--requirement <REQUIREMENT>|--editable <EDITAB

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--index-strategy</code> <i>index-strategy</i></dt><dd><p>The strategy to use when resolving against multiple index URLs.</p>
Expand Down Expand Up @@ -6610,6 +6623,7 @@ uv venv [OPTIONS] [PATH]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--index-strategy</code> <i>index-strategy</i></dt><dd><p>The strategy to use when resolving against multiple index URLs.</p>
Expand Down Expand Up @@ -6857,6 +6871,7 @@ uv build [OPTIONS] [SRC]

<p>If a URL, the page must contain a flat list of links to package files adhering to the formats described above.</p>

<p>May also be set with the <code>UV_FIND_LINKS</code> environment variable.</p>
</dd><dt><code>--help</code>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>

</dd><dt><code>--index-strategy</code> <i>index-strategy</i></dt><dd><p>The strategy to use when resolving against multiple index URLs.</p>
Expand Down

0 comments on commit c591636

Please sign in to comment.