Integrate system keyring via `native` keyring provider backend

This commit is contained in:
John Mumm 2025-07-03 15:10:06 +02:00
parent fe47f54c38
commit 7f8b563158
No known key found for this signature in database
GPG Key ID: 73D2271AFDC26EA8
8 changed files with 253 additions and 10 deletions

52
Cargo.lock generated
View File

@ -1043,6 +1043,35 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5" checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5"
[[package]]
name = "dbus"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
dependencies = [
"libc",
"libdbus-sys",
"winapi",
]
[[package]]
name = "dbus-secret-service"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b"
dependencies = [
"aes",
"block-padding",
"cbc",
"dbus",
"futures-util",
"hkdf",
"num",
"once_cell",
"rand",
"sha2",
]
[[package]] [[package]]
name = "deadpool" name = "deadpool"
version = "0.10.0" version = "0.10.0"
@ -2206,6 +2235,19 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "keyring"
version = "4.0.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb06f73ca0ea1cbd3858e54404585e33dccb860cb4fc8a66ad5e75a5736f3f19"
dependencies = [
"byteorder",
"dbus-secret-service",
"log",
"security-framework",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "kurbo" name = "kurbo"
version = "0.8.3" version = "0.8.3"
@ -2236,6 +2278,15 @@ version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "libdbus-sys"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
dependencies = [
"pkg-config",
]
[[package]] [[package]]
name = "libmimalloc-sys" name = "libmimalloc-sys"
version = "0.1.43" version = "0.1.43"
@ -5072,6 +5123,7 @@ dependencies = [
"futures", "futures",
"http", "http",
"insta", "insta",
"keyring",
"percent-encoding", "percent-encoding",
"reqwest", "reqwest",
"reqwest-middleware", "reqwest-middleware",

View File

@ -124,6 +124,7 @@ indoc = { version = "2.0.5" }
itertools = { version = "0.14.0" } itertools = { version = "0.14.0" }
jiff = { version = "0.2.0", features = ["serde"] } jiff = { version = "0.2.0", features = ["serde"] }
junction = { version = "1.2.0" } junction = { version = "1.2.0" }
keyring = { version = "4.0.0-rc.1", features = ["encrypted"] }
mailparse = { version = "0.16.0" } mailparse = { version = "0.16.0" }
md-5 = { version = "0.10.6" } md-5 = { version = "0.10.6" }
memchr = { version = "2.7.4" } memchr = { version = "2.7.4" }

View File

@ -21,6 +21,7 @@ async-trait = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
http = { workspace = true } http = { workspace = true }
keyring = { workspace = true }
percent-encoding = { workspace = true } percent-encoding = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
reqwest-middleware = { workspace = true } reqwest-middleware = { workspace = true }

View File

@ -1,11 +1,21 @@
use std::{io::Write, process::Stdio}; use rustc_hash::FxHashSet;
use std::{
io::Write,
process::Stdio,
sync::{LazyLock, RwLock},
};
use tokio::process::Command; use tokio::process::Command;
use tracing::{instrument, trace, warn}; use tracing::{debug, instrument, trace, warn};
use uv_redacted::DisplaySafeUrl; use uv_redacted::DisplaySafeUrl;
use uv_warnings::warn_user_once; use uv_warnings::warn_user_once;
use crate::credentials::Credentials; use crate::credentials::Credentials;
/// Keyring credentials that have been stored during an invocation of uv.
static STORED_KEYRING_URLS: LazyLock<StoredKeyringUrls> = LazyLock::new(StoredKeyringUrls::new);
/// Service name prefix for storing credentials in a keyring.
static UV_SERVICE_PREFIX: &str = "uv-credentials-";
/// A backend for retrieving credentials from a keyring. /// A backend for retrieving credentials from a keyring.
/// ///
/// See pip's implementation for reference /// See pip's implementation for reference
@ -17,13 +27,22 @@ pub struct KeyringProvider {
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum KeyringProviderBackend { pub(crate) enum KeyringProviderBackend {
/// Use the `keyring` command to fetch credentials. /// Use system keyring integration to fetch credentials.
Native,
/// Use the external `keyring` command to fetch credentials.
Subprocess, Subprocess,
#[cfg(test)] #[cfg(test)]
Dummy(Vec<(String, &'static str, &'static str)>), Dummy(Vec<(String, &'static str, &'static str)>),
} }
impl KeyringProvider { impl KeyringProvider {
/// Create a new [`KeyringProvider::Native`].
pub fn native() -> Self {
Self {
backend: KeyringProviderBackend::Native,
}
}
/// Create a new [`KeyringProvider::Subprocess`]. /// Create a new [`KeyringProvider::Subprocess`].
pub fn subprocess() -> Self { pub fn subprocess() -> Self {
Self { Self {
@ -31,6 +50,61 @@ impl KeyringProvider {
} }
} }
/// Store credentials for the given [`Url`] to the keyring if the
/// keyring provider backend is `Native`.
#[instrument(skip_all, fields(url = % url.to_string(), username))]
pub fn store_if_native(&self, url: &DisplaySafeUrl, credentials: &Credentials) {
let Some(username) = credentials.username() else {
trace!("Unable to store credentials in keyring for {url} due to missing username");
return;
};
let Some(password) = credentials.password() else {
trace!("Unable to store credentials in keyring for {url} due to missing password");
return;
};
match &self.backend {
KeyringProviderBackend::Native => {
// Only store credentials if not already stored during this uv invocation.
if !STORED_KEYRING_URLS.contains(url) {
self.store_native(url.as_str(), username, password);
STORED_KEYRING_URLS.insert(url.clone());
}
}
KeyringProviderBackend::Subprocess => {
trace!("Storing credentials is not supported for `subprocess` keyring");
}
#[cfg(test)]
KeyringProviderBackend::Dummy(_) => {}
}
}
/// Store credentials to the system keyring for the given `service_name`/`username`
/// pair.
#[instrument(skip(self))]
fn store_native(&self, service: &str, username: &str, password: &str) {
let prefixed_service = format!("{UV_SERVICE_PREFIX}{service}");
let entry = match keyring::Entry::new(&prefixed_service, username) {
Ok(entry) => entry,
Err(err) => {
warn_user_once!(
"Unable to store credentials for {service} in the system keyring: {err}"
);
return;
}
};
match entry.set_password(password) {
Ok(()) => {
debug!("Storing credentials for {service} in system keyring");
}
Err(err) => {
warn_user_once!(
"Unable to store credentials for {service} in the system keyring: {err}"
);
}
}
}
/// Fetch credentials for the given [`Url`] from the keyring. /// Fetch credentials for the given [`Url`] from the keyring.
/// ///
/// Returns [`None`] if no password was found for the username or if any errors /// Returns [`None`] if no password was found for the username or if any errors
@ -55,6 +129,7 @@ impl KeyringProvider {
// <https://github.com/pypa/pip/blob/ae5fff36b0aad6e5e0037884927eaa29163c0611/src/pip/_internal/network/auth.py#L376C1-L379C14> // <https://github.com/pypa/pip/blob/ae5fff36b0aad6e5e0037884927eaa29163c0611/src/pip/_internal/network/auth.py#L376C1-L379C14>
trace!("Checking keyring for URL {url}"); trace!("Checking keyring for URL {url}");
let mut credentials = match self.backend { let mut credentials = match self.backend {
KeyringProviderBackend::Native => self.fetch_native(url.as_str(), username),
KeyringProviderBackend::Subprocess => { KeyringProviderBackend::Subprocess => {
self.fetch_subprocess(url.as_str(), username).await self.fetch_subprocess(url.as_str(), username).await
} }
@ -72,6 +147,7 @@ impl KeyringProvider {
}; };
trace!("Checking keyring for host {host}"); trace!("Checking keyring for host {host}");
credentials = match self.backend { credentials = match self.backend {
KeyringProviderBackend::Native => self.fetch_native(&host, username),
KeyringProviderBackend::Subprocess => self.fetch_subprocess(&host, username).await, KeyringProviderBackend::Subprocess => self.fetch_subprocess(&host, username).await,
#[cfg(test)] #[cfg(test)]
KeyringProviderBackend::Dummy(ref store) => { KeyringProviderBackend::Dummy(ref store) => {
@ -175,6 +251,27 @@ impl KeyringProvider {
} }
} }
#[instrument(skip(self))]
fn fetch_native(&self, service: &str, username: Option<&str>) -> Option<(String, String)> {
let prefixed_service = format!("{UV_SERVICE_PREFIX}{service}");
let username = username?;
if let Ok(entry) = keyring::Entry::new(&prefixed_service, username) {
match entry.get_password() {
Ok(password) => return Some((username.to_string(), password)),
Err(keyring::Error::NoEntry) => {
debug!("No entry found in system keyring for {service}");
}
Err(err) => {
warn_user_once!(
"Unable to fetch credentials for {service} from system keyring: {}",
err
);
}
}
}
None
}
#[cfg(test)] #[cfg(test)]
fn fetch_dummy( fn fetch_dummy(
store: &Vec<(String, &'static str, &'static str)>, store: &Vec<(String, &'static str, &'static str)>,
@ -213,6 +310,23 @@ impl KeyringProvider {
} }
} }
/// Keyring credentials that have been stored during an invocation of uv.
struct StoredKeyringUrls(RwLock<FxHashSet<DisplaySafeUrl>>);
impl StoredKeyringUrls {
pub(crate) fn new() -> Self {
Self(RwLock::new(FxHashSet::default()))
}
pub(crate) fn contains(&self, url: &DisplaySafeUrl) -> bool {
self.0.read().unwrap().contains(url)
}
pub(crate) fn insert(&self, url: DisplaySafeUrl) -> bool {
self.0.write().unwrap().insert(url)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -217,7 +217,14 @@ impl Middleware for AuthMiddleware {
if credentials.password().is_some() { if credentials.password().is_some() {
trace!("Request for {url} is fully authenticated"); trace!("Request for {url} is fully authenticated");
return self return self
.complete_request(None, request, extensions, next, auth_policy) .complete_request(
None,
request,
extensions,
next,
maybe_index_url,
auth_policy,
)
.await; .await;
} }
@ -299,7 +306,14 @@ impl Middleware for AuthMiddleware {
trace!("Retrying request for {url} with credentials from cache {credentials:?}"); trace!("Retrying request for {url} with credentials from cache {credentials:?}");
retry_request = credentials.authenticate(retry_request); retry_request = credentials.authenticate(retry_request);
return self return self
.complete_request(None, retry_request, extensions, next, auth_policy) .complete_request(
None,
retry_request,
extensions,
next,
maybe_index_url,
auth_policy,
)
.await; .await;
} }
} }
@ -323,6 +337,7 @@ impl Middleware for AuthMiddleware {
retry_request, retry_request,
extensions, extensions,
next, next,
maybe_index_url,
auth_policy, auth_policy,
) )
.await; .await;
@ -333,7 +348,14 @@ impl Middleware for AuthMiddleware {
trace!("Retrying request for {url} with username from cache {credentials:?}"); trace!("Retrying request for {url} with username from cache {credentials:?}");
retry_request = credentials.authenticate(retry_request); retry_request = credentials.authenticate(retry_request);
return self return self
.complete_request(None, retry_request, extensions, next, auth_policy) .complete_request(
None,
retry_request,
extensions,
next,
maybe_index_url,
auth_policy,
)
.await; .await;
} }
} }
@ -358,6 +380,7 @@ impl AuthMiddleware {
request: Request, request: Request,
extensions: &mut Extensions, extensions: &mut Extensions,
next: Next<'_>, next: Next<'_>,
index_url: Option<&DisplaySafeUrl>,
auth_policy: AuthPolicy, auth_policy: AuthPolicy,
) -> reqwest_middleware::Result<Response> { ) -> reqwest_middleware::Result<Response> {
let Some(credentials) = credentials else { let Some(credentials) = credentials else {
@ -375,6 +398,9 @@ impl AuthMiddleware {
.as_ref() .as_ref()
.is_ok_and(|response| response.error_for_status_ref().is_ok()) .is_ok_and(|response| response.error_for_status_ref().is_ok())
{ {
if let (Some(index_url), Some(keyring)) = (index_url, &self.keyring) {
keyring.store_if_native(index_url, &credentials);
}
trace!("Updating cached credentials for {url} to {credentials:?}"); trace!("Updating cached credentials for {url} to {credentials:?}");
self.cache().insert(&url, credentials); self.cache().insert(&url, credentials);
} }
@ -399,7 +425,14 @@ impl AuthMiddleware {
if credentials.password().is_some() { if credentials.password().is_some() {
trace!("Request for {url} already contains username and password"); trace!("Request for {url} already contains username and password");
return self return self
.complete_request(Some(credentials), request, extensions, next, auth_policy) .complete_request(
Some(credentials),
request,
extensions,
next,
index_url,
auth_policy,
)
.await; .await;
} }
@ -420,7 +453,14 @@ impl AuthMiddleware {
// Do not insert already-cached credentials // Do not insert already-cached credentials
let credentials = None; let credentials = None;
return self return self
.complete_request(credentials, request, extensions, next, auth_policy) .complete_request(
credentials,
request,
extensions,
next,
index_url,
auth_policy,
)
.await; .await;
} }
@ -458,8 +498,15 @@ impl AuthMiddleware {
Some(credentials) Some(credentials)
}; };
self.complete_request(credentials, request, extensions, next, auth_policy) self.complete_request(
.await credentials,
request,
extensions,
next,
index_url,
auth_policy,
)
.await
} }
/// Fetch credentials for a URL. /// Fetch credentials for a URL.

View File

@ -9,6 +9,8 @@ pub enum KeyringProviderType {
/// Do not use keyring for credential lookup. /// Do not use keyring for credential lookup.
#[default] #[default]
Disabled, Disabled,
/// Use the system keyring for credential lookup.
Native,
/// Use the `keyring` command for credential lookup. /// Use the `keyring` command for credential lookup.
Subprocess, Subprocess,
// /// Not yet implemented // /// Not yet implemented
@ -22,6 +24,7 @@ impl KeyringProviderType {
pub fn to_provider(&self) -> Option<KeyringProvider> { pub fn to_provider(&self) -> Option<KeyringProvider> {
match self { match self {
Self::Disabled => None, Self::Disabled => None,
Self::Native => Some(KeyringProvider::native()),
Self::Subprocess => Some(KeyringProvider::subprocess()), Self::Subprocess => Some(KeyringProvider::subprocess()),
} }
} }

View File

@ -148,6 +148,7 @@ uv run [OPTIONS] [COMMAND]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-run--link-mode"><a href="#uv-run--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-run--link-mode"><a href="#uv-run--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -506,6 +507,7 @@ uv add [OPTIONS] <PACKAGES|--requirements <REQUIREMENTS>>
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-add--link-mode"><a href="#uv-add--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-add--link-mode"><a href="#uv-add--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -699,6 +701,7 @@ uv remove [OPTIONS] <PACKAGES>...
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-remove--link-mode"><a href="#uv-remove--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-remove--link-mode"><a href="#uv-remove--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -880,6 +883,7 @@ uv version [OPTIONS] [VALUE]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-version--link-mode"><a href="#uv-version--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-version--link-mode"><a href="#uv-version--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -1077,6 +1081,7 @@ uv sync [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-sync--link-mode"><a href="#uv-sync--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-sync--link-mode"><a href="#uv-sync--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -1317,6 +1322,7 @@ uv lock [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-lock--link-mode"><a href="#uv-lock--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-lock--link-mode"><a href="#uv-lock--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used when building source distributions.</p> <p>This option is only used when building source distributions.</p>
@ -1495,6 +1501,7 @@ uv export [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-export--link-mode"><a href="#uv-export--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-export--link-mode"><a href="#uv-export--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used when building source distributions.</p> <p>This option is only used when building source distributions.</p>
@ -1686,6 +1693,7 @@ uv tree [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-tree--link-mode"><a href="#uv-tree--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-tree--link-mode"><a href="#uv-tree--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used when building source distributions.</p> <p>This option is only used when building source distributions.</p>
@ -1950,6 +1958,7 @@ uv tool run [OPTIONS] [COMMAND]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-tool-run--link-mode"><a href="#uv-tool-run--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-tool-run--link-mode"><a href="#uv-tool-run--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -2124,6 +2133,7 @@ uv tool install [OPTIONS] <PACKAGE>
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-tool-install--link-mode"><a href="#uv-tool-install--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-tool-install--link-mode"><a href="#uv-tool-install--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -2290,6 +2300,7 @@ uv tool upgrade [OPTIONS] <NAME>...
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-tool-upgrade--link-mode"><a href="#uv-tool-upgrade--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-tool-upgrade--link-mode"><a href="#uv-tool-upgrade--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -3461,6 +3472,7 @@ uv pip compile [OPTIONS] <SRC_FILE|--group <GROUP>>
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-compile--link-mode"><a href="#uv-pip-compile--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-pip-compile--link-mode"><a href="#uv-pip-compile--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used when building source distributions.</p> <p>This option is only used when building source distributions.</p>
@ -3752,6 +3764,7 @@ uv pip sync [OPTIONS] <SRC_FILE>...
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-sync--link-mode"><a href="#uv-pip-sync--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-pip-sync--link-mode"><a href="#uv-pip-sync--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -4021,6 +4034,7 @@ uv pip install [OPTIONS] <PACKAGE|--requirements <REQUIREMENTS>|--editable <EDIT
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-install--link-mode"><a href="#uv-pip-install--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-pip-install--link-mode"><a href="#uv-pip-install--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p> <p>Defaults to <code>clone</code> (also known as Copy-on-Write) on macOS, and <code>hardlink</code> on Linux and Windows.</p>
@ -4263,6 +4277,7 @@ uv pip uninstall [OPTIONS] <PACKAGE|--requirements <REQUIREMENTS>>
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-uninstall--managed-python"><a href="#uv-pip-uninstall--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p> </ul></dd><dt id="uv-pip-uninstall--managed-python"><a href="#uv-pip-uninstall--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p>
<p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p> <p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p>
@ -4441,6 +4456,7 @@ uv pip list [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-list--managed-python"><a href="#uv-pip-list--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p> </ul></dd><dt id="uv-pip-list--managed-python"><a href="#uv-pip-list--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p>
<p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p> <p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p>
@ -4616,6 +4632,7 @@ uv pip tree [OPTIONS]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-pip-tree--managed-python"><a href="#uv-pip-tree--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p> </ul></dd><dt id="uv-pip-tree--managed-python"><a href="#uv-pip-tree--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p>
<p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p> <p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p>
@ -4808,6 +4825,7 @@ uv venv [OPTIONS] [PATH]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-venv--link-mode"><a href="#uv-venv--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-venv--link-mode"><a href="#uv-venv--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used for installing seed packages.</p> <p>This option is only used for installing seed packages.</p>
@ -4963,6 +4981,7 @@ uv build [OPTIONS] [SRC]
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-build--link-mode"><a href="#uv-build--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p> </ul></dd><dt id="uv-build--link-mode"><a href="#uv-build--link-mode"><code>--link-mode</code></a> <i>link-mode</i></dt><dd><p>The method to use when installing packages from the global cache.</p>
<p>This option is only used when building source distributions.</p> <p>This option is only used when building source distributions.</p>
@ -5114,6 +5133,7 @@ uv publish --publish-url https://upload.pypi.org/legacy/ --check-url https://pyp
<p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p> <p>May also be set with the <code>UV_KEYRING_PROVIDER</code> environment variable.</p><p>Possible values:</p>
<ul> <ul>
<li><code>disabled</code>: Do not use keyring for credential lookup</li> <li><code>disabled</code>: Do not use keyring for credential lookup</li>
<li><code>native</code>: Use the system keyring for credential lookup</li>
<li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li> <li><code>subprocess</code>: Use the <code>keyring</code> command for credential lookup</li>
</ul></dd><dt id="uv-publish--managed-python"><a href="#uv-publish--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p> </ul></dd><dt id="uv-publish--managed-python"><a href="#uv-publish--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p>
<p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p> <p>By default, uv prefers using Python versions it manages. However, it will use system Python versions if a uv-managed Python is not installed. This option disables use of system Python versions.</p>

5
uv.schema.json generated
View File

@ -1123,6 +1123,11 @@
"type": "string", "type": "string",
"const": "disabled" "const": "disabled"
}, },
{
"description": "Use the system keyring for credential lookup.",
"type": "string",
"const": "native"
},
{ {
"description": "Use the `keyring` command for credential lookup.", "description": "Use the `keyring` command for credential lookup.",
"type": "string", "type": "string",