mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-12 00:45:35 +00:00
Add UV_HTTP_RETRIES to customize retry counts (#14544)
I want to increase this number in CI and was surprised we didn't support configuration yet.
This commit is contained in:
parent
2e0f399eeb
commit
71470b7b1a
27 changed files with 143 additions and 1 deletions
|
|
@ -6,6 +6,7 @@ use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{env, io, iter};
|
use std::{env, io, iter};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use http::{
|
use http::{
|
||||||
HeaderMap, HeaderName, HeaderValue, Method, StatusCode,
|
HeaderMap, HeaderName, HeaderValue, Method, StatusCode,
|
||||||
|
|
@ -166,6 +167,25 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the retry count from [`EnvVars::UV_HTTP_RETRIES`] if set, otherwise, make no change.
|
||||||
|
///
|
||||||
|
/// Errors when [`EnvVars::UV_HTTP_RETRIES`] is not a valid u32.
|
||||||
|
pub fn retries_from_env(self) -> anyhow::Result<Self> {
|
||||||
|
// TODO(zanieb): We should probably parse this in another layer, but there's not a natural
|
||||||
|
// fit for it right now
|
||||||
|
if let Some(value) = env::var_os(EnvVars::UV_HTTP_RETRIES) {
|
||||||
|
Ok(self.retries(
|
||||||
|
value
|
||||||
|
.to_string_lossy()
|
||||||
|
.as_ref()
|
||||||
|
.parse::<u32>()
|
||||||
|
.context("Failed to parse `UV_HTTP_RETRIES`")?,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn native_tls(mut self, native_tls: bool) -> Self {
|
pub fn native_tls(mut self, native_tls: bool) -> Self {
|
||||||
self.native_tls = native_tls;
|
self.native_tls = native_tls;
|
||||||
|
|
@ -238,7 +258,11 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
|
|
||||||
/// Create a [`RetryPolicy`] for the client.
|
/// Create a [`RetryPolicy`] for the client.
|
||||||
fn retry_policy(&self) -> ExponentialBackoff {
|
fn retry_policy(&self) -> ExponentialBackoff {
|
||||||
ExponentialBackoff::builder().build_with_max_retries(self.retries)
|
let mut builder = ExponentialBackoff::builder();
|
||||||
|
if env::var_os(EnvVars::UV_TEST_NO_HTTP_RETRY_DELAY).is_some() {
|
||||||
|
builder = builder.retry_bounds(Duration::from_millis(0), Duration::from_millis(0));
|
||||||
|
}
|
||||||
|
builder.build_with_max_retries(self.retries)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> BaseClient {
|
pub fn build(&self) -> BaseClient {
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,11 @@ impl<'a> RegistryClientBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn retries_from_env(mut self) -> anyhow::Result<Self> {
|
||||||
|
self.base_client_builder = self.base_client_builder.retries_from_env()?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn native_tls(mut self, native_tls: bool) -> Self {
|
pub fn native_tls(mut self, native_tls: bool) -> Self {
|
||||||
self.base_client_builder = self.base_client_builder.native_tls(native_tls);
|
self.base_client_builder = self.base_client_builder.native_tls(native_tls);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
WheelFilename(#[from] uv_distribution_filename::WheelFilenameError),
|
WheelFilename(#[from] uv_distribution_filename::WheelFilenameError),
|
||||||
|
|
||||||
|
#[error("Failed to construct HTTP client")]
|
||||||
|
ClientError(#[source] anyhow::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,9 @@ impl EnvVars {
|
||||||
/// Timeout (in seconds) for HTTP requests. (default: 30 s)
|
/// Timeout (in seconds) for HTTP requests. (default: 30 s)
|
||||||
pub const UV_HTTP_TIMEOUT: &'static str = "UV_HTTP_TIMEOUT";
|
pub const UV_HTTP_TIMEOUT: &'static str = "UV_HTTP_TIMEOUT";
|
||||||
|
|
||||||
|
/// The number of retries for HTTP requests. (default: 3)
|
||||||
|
pub const UV_HTTP_RETRIES: &'static str = "UV_HTTP_RETRIES";
|
||||||
|
|
||||||
/// Timeout (in seconds) for HTTP requests. Equivalent to `UV_HTTP_TIMEOUT`.
|
/// Timeout (in seconds) for HTTP requests. Equivalent to `UV_HTTP_TIMEOUT`.
|
||||||
pub const UV_REQUEST_TIMEOUT: &'static str = "UV_REQUEST_TIMEOUT";
|
pub const UV_REQUEST_TIMEOUT: &'static str = "UV_REQUEST_TIMEOUT";
|
||||||
|
|
||||||
|
|
@ -659,6 +662,9 @@ impl EnvVars {
|
||||||
#[attr_hidden]
|
#[attr_hidden]
|
||||||
pub const UV_TEST_VENDOR_LINKS_URL: &'static str = "UV_TEST_VENDOR_LINKS_URL";
|
pub const UV_TEST_VENDOR_LINKS_URL: &'static str = "UV_TEST_VENDOR_LINKS_URL";
|
||||||
|
|
||||||
|
/// Used to disable delay for HTTP retries in tests.
|
||||||
|
pub const UV_TEST_NO_HTTP_RETRY_DELAY: &'static str = "UV_TEST_NO_HTTP_RETRY_DELAY";
|
||||||
|
|
||||||
/// Used to set an index url for tests.
|
/// Used to set an index url for tests.
|
||||||
#[attr_hidden]
|
#[attr_hidden]
|
||||||
pub const UV_TEST_INDEX_URL: &'static str = "UV_TEST_INDEX_URL";
|
pub const UV_TEST_INDEX_URL: &'static str = "UV_TEST_INDEX_URL";
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ async fn build_impl(
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::default()
|
let client_builder = BaseClientBuilder::default()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,7 @@ pub(crate) async fn pip_compile(
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ pub(crate) async fn pip_install(
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ pub(crate) async fn pip_list(
|
||||||
let capabilities = IndexCapabilities::default();
|
let capabilities = IndexCapabilities::default();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ pub(crate) async fn pip_sync(
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ pub(crate) async fn pip_tree(
|
||||||
let capabilities = IndexCapabilities::default();
|
let capabilities = IndexCapabilities::default();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ pub(crate) async fn pip_uninstall(
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ pub(crate) async fn add(
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -329,6 +330,7 @@ pub(crate) async fn add(
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(settings.resolver.keyring_provider)
|
.keyring(settings.resolver.keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ async fn init_script(
|
||||||
warn_user_once!("`--package` is a no-op for Python scripts, which are standalone");
|
warn_user_once!("`--package` is a no-op for Python scripts, which are standalone");
|
||||||
}
|
}
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -348,6 +349,7 @@ async fn init_project(
|
||||||
|
|
||||||
let reporter = PythonDownloadReporter::single(printer);
|
let reporter = PythonDownloadReporter::single(printer);
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ pub(crate) async fn lock(
|
||||||
let script = match script {
|
let script = match script {
|
||||||
Some(ScriptPath::Path(path)) => {
|
Some(ScriptPath::Path(path)) => {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -588,6 +589,7 @@ async fn do_lock(
|
||||||
|
|
||||||
// Initialize the client.
|
// Initialize the client.
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(*keyring_provider)
|
.keyring(*keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -690,6 +690,7 @@ impl ScriptInterpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -946,6 +947,7 @@ impl ProjectInterpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::default()
|
let client_builder = BaseClientBuilder::default()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -1656,6 +1658,8 @@ pub(crate) async fn resolve_names(
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()
|
||||||
|
.map_err(uv_requirements::Error::ClientError)?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(*keyring_provider)
|
.keyring(*keyring_provider)
|
||||||
|
|
@ -1813,6 +1817,7 @@ pub(crate) async fn resolve_environment(
|
||||||
} = spec.requirements;
|
} = spec.requirements;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(*keyring_provider)
|
.keyring(*keyring_provider)
|
||||||
|
|
@ -1984,6 +1989,7 @@ pub(crate) async fn sync_environment(
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
@ -2147,6 +2153,7 @@ pub(crate) async fn update_environment(
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(*keyring_provider)
|
.keyring(*keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
// If we're isolating the environment, use an ephemeral virtual environment as the
|
// If we're isolating the environment, use an ephemeral virtual environment as the
|
||||||
// base environment for the project.
|
// base environment for the project.
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -859,6 +860,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
|
|
||||||
let interpreter = {
|
let interpreter = {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -929,6 +931,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -1526,6 +1529,7 @@ impl RunCommand {
|
||||||
.tempfile()?;
|
.tempfile()?;
|
||||||
|
|
||||||
let client = BaseClientBuilder::new()
|
let client = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
||||||
|
|
|
||||||
|
|
@ -623,6 +623,7 @@ pub(super) async fn do_sync(
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.keyring(keyring_provider)
|
.keyring(keyring_provider)
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ pub(crate) async fn tree(
|
||||||
let client = RegistryClientBuilder::new(
|
let client = RegistryClientBuilder::new(
|
||||||
cache.clone().with_refresh(Refresh::All(Timestamp::now())),
|
cache.clone().with_refresh(Refresh::All(Timestamp::now())),
|
||||||
)
|
)
|
||||||
|
.retries_from_env()?
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ pub(crate) async fn publish(
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
let registry_client_builder = RegistryClientBuilder::new(cache.clone())
|
let registry_client_builder = RegistryClientBuilder::new(cache.clone())
|
||||||
|
.retries_from_env()?
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,7 @@ pub(crate) async fn install(
|
||||||
|
|
||||||
// Download and unpack the Python versions concurrently
|
// Download and unpack the Python versions concurrently
|
||||||
let client = uv_client::BaseClientBuilder::new()
|
let client = uv_client::BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
.allow_insecure_host(network_settings.allow_insecure_host.clone())
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ pub(crate) async fn pin(
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ pub(crate) async fn install(
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
@ -97,6 +98,7 @@ pub(crate) async fn install(
|
||||||
let workspace_cache = WorkspaceCache::default();
|
let workspace_cache = WorkspaceCache::default();
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -690,6 +690,7 @@ async fn get_or_create_environment(
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
) -> Result<(ToolRequirement, PythonEnvironment), ProjectError> {
|
) -> Result<(ToolRequirement, PythonEnvironment), ProjectError> {
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ pub(crate) async fn upgrade(
|
||||||
|
|
||||||
let reporter = PythonDownloadReporter::single(printer);
|
let reporter = PythonDownloadReporter::single(printer);
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
.allow_insecure_host(network_settings.allow_insecure_host.clone());
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,9 @@ async fn venv_impl(
|
||||||
.unwrap_or(PathBuf::from(".venv")),
|
.unwrap_or(PathBuf::from(".venv")),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO(zanieb): We don't use [`BaseClientBuilder::retries_from_env`] here because it's a pain
|
||||||
|
// to map into a miette diagnostic. We should just remove miette diagnostics here, we're not
|
||||||
|
// using them elsewhere.
|
||||||
let client_builder = BaseClientBuilder::default()
|
let client_builder = BaseClientBuilder::default()
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
.native_tls(network_settings.native_tls)
|
.native_tls(network_settings.native_tls)
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,66 @@ fn install_package() {
|
||||||
context.assert_command("import flask").success();
|
context.assert_command("import flask").success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn install_http_retries() {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let server = MockServer::start().await;
|
||||||
|
|
||||||
|
// Create a server that always fails, so we can see the number of retries used
|
||||||
|
Mock::given(method("GET"))
|
||||||
|
.respond_with(ResponseTemplate::new(503))
|
||||||
|
.mount(&server)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
|
.arg("anyio")
|
||||||
|
.arg("--index")
|
||||||
|
.arg(server.uri())
|
||||||
|
.env(EnvVars::UV_HTTP_RETRIES, "foo"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: Failed to parse `UV_HTTP_RETRIES`
|
||||||
|
Caused by: invalid digit found in string
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
|
.arg("anyio")
|
||||||
|
.arg("--index")
|
||||||
|
.arg(server.uri())
|
||||||
|
.env(EnvVars::UV_HTTP_RETRIES, "999999999999"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: Failed to parse `UV_HTTP_RETRIES`
|
||||||
|
Caused by: number too large to fit in target type
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
|
.arg("anyio")
|
||||||
|
.arg("--index")
|
||||||
|
.arg(server.uri())
|
||||||
|
.env(EnvVars::UV_HTTP_RETRIES, "5")
|
||||||
|
.env(EnvVars::UV_TEST_NO_HTTP_RETRY_DELAY, "true"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: Request failed after 5 retries
|
||||||
|
Caused by: Failed to fetch: `http://[LOCALHOST]/anyio/`
|
||||||
|
Caused by: HTTP status server error (503 Service Unavailable) for url (http://[LOCALHOST]/anyio/)
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Install a package from a `requirements.txt` into a virtual environment.
|
/// Install a package from a `requirements.txt` into a virtual environment.
|
||||||
#[test]
|
#[test]
|
||||||
fn install_requirements_txt() -> Result<()> {
|
fn install_requirements_txt() -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,10 @@ Equivalent to the `--token` argument for self update. A GitHub token for authent
|
||||||
|
|
||||||
Enables fetching files stored in Git LFS when installing a package from a Git repository.
|
Enables fetching files stored in Git LFS when installing a package from a Git repository.
|
||||||
|
|
||||||
|
### `UV_HTTP_RETRIES`
|
||||||
|
|
||||||
|
The number of retries for HTTP requests. (default: 3)
|
||||||
|
|
||||||
### `UV_HTTP_TIMEOUT`
|
### `UV_HTTP_TIMEOUT`
|
||||||
|
|
||||||
Timeout (in seconds) for HTTP requests. (default: 30 s)
|
Timeout (in seconds) for HTTP requests. (default: 30 s)
|
||||||
|
|
@ -416,6 +420,10 @@ WARNING: `UV_SYSTEM_PYTHON=true` is intended for use in continuous integration (
|
||||||
or containerized environments and should be used with caution, as modifying the system
|
or containerized environments and should be used with caution, as modifying the system
|
||||||
Python can lead to unexpected behavior.
|
Python can lead to unexpected behavior.
|
||||||
|
|
||||||
|
### `UV_TEST_NO_HTTP_RETRY_DELAY`
|
||||||
|
|
||||||
|
Used to disable delay for HTTP retries in tests.
|
||||||
|
|
||||||
### `UV_TOOL_BIN_DIR`
|
### `UV_TOOL_BIN_DIR`
|
||||||
|
|
||||||
Specifies the "bin" directory for installing tool executables.
|
Specifies the "bin" directory for installing tool executables.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue