mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-26 22:04:29 +00:00
Add support for named and explicit indexes (#7481)
## Summary This PR adds a first-class API for defining registry indexes, beyond our existing `--index-url` and `--extra-index-url` setup. Specifically, you now define indexes like so in a `uv.toml` or `pyproject.toml` file: ```toml [[tool.uv.index]] name = "pytorch" url = "https://download.pytorch.org/whl/cu121" ``` You can also provide indexes via `--index` and `UV_INDEX`, and override the default index with `--default-index` and `UV_DEFAULT_INDEX`. ### Index priority Indexes are prioritized in the order in which they're defined, such that the first-defined index has highest priority. Indexes are also inherited from parent configuration (e.g., the user-level `uv.toml`), but are placed after any indexes in the current project, matching our semantics for other array-based configuration values. You can mix `--index` and `--default-index` with the legacy `--index-url` and `--extra-index-url` settings; the latter two are merely treated as unnamed `[[tool.uv.index]]` entries. ### Index pinning If an index includes a name (which is optional), it can then be referenced via `tool.uv.sources`: ```toml [[tool.uv.index]] name = "pytorch" url = "https://download.pytorch.org/whl/cu121" [tool.uv.sources] torch = { index = "pytorch" } ``` If an index is marked as `explicit = true`, it can _only_ be used via such references, and will never be searched implicitly: ```toml [[tool.uv.index]] name = "pytorch" url = "https://download.pytorch.org/whl/cu121" explicit = true [tool.uv.sources] torch = { index = "pytorch" } ``` Indexes defined outside of the current project (e.g., in the user-level `uv.toml`) can _not_ be explicitly selected. (As of now, we only support using a single index for a given `tool.uv.sources` definition.) ### Default index By default, we include PyPI as the default index. This remains true even if the user defines a `[[tool.uv.index]]` -- PyPI is still used as a fallback. You can mark an index as `default = true` to (1) disable the use of PyPI, and (2) bump it to the bottom of the prioritized list, such that it's used only if a package does not exist on a prior index: ```toml [[tool.uv.index]] name = "pytorch" url = "https://download.pytorch.org/whl/cu121" default = true ``` ### Name reuse If a name is reused, the higher-priority index with that name is used, while the lower-priority indexes are ignored entirely. For example, given: ```toml [[tool.uv.index]] name = "pytorch" url = "https://download.pytorch.org/whl/cu121" [[tool.uv.index]] name = "pytorch" url = "https://test.pypi.org/simple" ``` The `https://test.pypi.org/simple` index would be ignored entirely, since it's lower-priority than `https://download.pytorch.org/whl/cu121` but shares the same name. Closes #171. ## Future work - Users should be able to provide authentication for named indexes via environment variables. - `uv add` should automatically write `--index` entries to the `pyproject.toml` file. - Users should be able to provide multiple indexes for a given package, stratified by platform: ```toml [tool.uv.sources] torch = [ { index = "cpu", markers = "sys_platform == 'darwin'" }, { index = "gpu", markers = "sys_platform != 'darwin'" }, ] ``` - Users should be able to specify a proxy URL for a given index, to avoid writing user-specific URLs to a lockfile: ```toml [[tool.uv.index]] name = "test" url = "https://private.org/simple" proxy = "http://<omitted>/pypi/simple" ```
This commit is contained in:
parent
34be3af84f
commit
5b391770df
51 changed files with 3526 additions and 658 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use async_http_range_reader::AsyncHttpRangeReader;
|
||||
use futures::{FutureExt, TryStreamExt};
|
||||
use http::HeaderMap;
|
||||
use itertools::Either;
|
||||
use reqwest::{Client, Response, StatusCode};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use std::collections::BTreeMap;
|
||||
|
|
@ -16,7 +17,7 @@ use uv_configuration::KeyringProviderType;
|
|||
use uv_configuration::{IndexStrategy, TrustedHost};
|
||||
use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename};
|
||||
use uv_distribution_types::{
|
||||
BuiltDist, File, FileLocation, IndexCapabilities, IndexUrl, IndexUrls, Name,
|
||||
BuiltDist, File, FileLocation, Index, IndexCapabilities, IndexUrl, IndexUrls, Name,
|
||||
};
|
||||
use uv_metadata::{read_metadata_async_seek, read_metadata_async_stream};
|
||||
use uv_normalize::PackageName;
|
||||
|
|
@ -204,8 +205,15 @@ impl RegistryClient {
|
|||
pub async fn simple(
|
||||
&self,
|
||||
package_name: &PackageName,
|
||||
index: Option<&IndexUrl>,
|
||||
) -> Result<Vec<(IndexUrl, OwnedArchive<SimpleMetadata>)>, Error> {
|
||||
let mut it = self.index_urls.indexes().peekable();
|
||||
let indexes = if let Some(index) = index {
|
||||
Either::Left(std::iter::once(index))
|
||||
} else {
|
||||
Either::Right(self.index_urls.indexes().map(Index::url))
|
||||
};
|
||||
|
||||
let mut it = indexes.peekable();
|
||||
if it.peek().is_none() {
|
||||
return Err(ErrorKind::NoIndex(package_name.to_string()).into());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue