This commit is contained in:
Anoop Rehman 2025-12-16 11:27:07 +01:00 committed by GitHub
commit 1c85e9552f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 9 deletions

View File

@ -1233,7 +1233,7 @@ impl RegistryClient {
std::io::Error::new(
std::io::ErrorKind::TimedOut,
format!(
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).",
"Failed to download distribution due to network timeout ({}s).\nTry increasing UV_HTTP_TIMEOUT to a larger integer value (in seconds), e.g., UV_HTTP_TIMEOUT=60",
self.timeout().as_secs()
),
)

View File

@ -93,7 +93,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
io::Error::new(
io::ErrorKind::TimedOut,
format!(
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).",
"Failed to download distribution due to network timeout ({}s).\nTry increasing UV_HTTP_TIMEOUT to a larger integer value (in seconds), e.g., UV_HTTP_TIMEOUT=60",
self.client.unmanaged.timeout().as_secs()
),
)

View File

@ -608,11 +608,15 @@ impl EnvironmentOptions {
pub fn new() -> Result<Self, Error> {
// Timeout options, matching https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout
// `UV_REQUEST_TIMEOUT` is provided for backwards compatibility with v0.1.6
let http_timeout = parse_integer_environment_variable(EnvVars::UV_HTTP_TIMEOUT)?
let http_timeout = parse_integer_environment_variable(EnvVars::UV_HTTP_TIMEOUT, true)?
.or(parse_integer_environment_variable(
EnvVars::UV_REQUEST_TIMEOUT,
true,
)?)
.or(parse_integer_environment_variable(
EnvVars::HTTP_TIMEOUT,
true,
)?)
.or(parse_integer_environment_variable(EnvVars::HTTP_TIMEOUT)?)
.map(Duration::from_secs);
Ok(Self {
@ -625,9 +629,15 @@ impl EnvironmentOptions {
EnvVars::UV_PYTHON_INSTALL_REGISTRY,
)?,
concurrency: Concurrency {
downloads: parse_integer_environment_variable(EnvVars::UV_CONCURRENT_DOWNLOADS)?,
builds: parse_integer_environment_variable(EnvVars::UV_CONCURRENT_BUILDS)?,
installs: parse_integer_environment_variable(EnvVars::UV_CONCURRENT_INSTALLS)?,
downloads: parse_integer_environment_variable(
EnvVars::UV_CONCURRENT_DOWNLOADS,
false,
)?,
builds: parse_integer_environment_variable(EnvVars::UV_CONCURRENT_BUILDS, false)?,
installs: parse_integer_environment_variable(
EnvVars::UV_CONCURRENT_INSTALLS,
false,
)?,
},
install_mirrors: PythonInstallMirrors {
python_install_mirror: parse_string_environment_variable(
@ -644,12 +654,13 @@ impl EnvironmentOptions {
lfs: parse_boolish_environment_variable(EnvVars::UV_GIT_LFS)?,
upload_http_timeout: parse_integer_environment_variable(
EnvVars::UV_UPLOAD_HTTP_TIMEOUT,
true,
)?
.map(Duration::from_secs)
.or(http_timeout)
.unwrap_or(Duration::from_secs(15 * 60)),
http_timeout: http_timeout.unwrap_or(Duration::from_secs(30)),
http_retries: parse_integer_environment_variable(EnvVars::UV_HTTP_RETRIES)?
http_retries: parse_integer_environment_variable(EnvVars::UV_HTTP_RETRIES, false)?
.unwrap_or(uv_client::DEFAULT_RETRIES),
#[cfg(feature = "tracing-durations-export")]
tracing_durations_file: parse_path_environment_variable(
@ -732,7 +743,15 @@ fn parse_string_environment_variable(name: &'static str) -> Result<Option<String
}
}
fn parse_integer_environment_variable<T>(name: &'static str) -> Result<Option<T>, Error>
/// Parse an integer environment variable.
///
/// If `is_duration` is `true`, this function will check if the value ends with "s" and provide
/// a helpful error message, as duration environment variables expect an integer value in seconds
/// (not a string like "60s").
fn parse_integer_environment_variable<T>(
name: &'static str,
is_duration: bool,
) -> Result<Option<T>, Error>
where
T: std::str::FromStr + Copy,
<T as std::str::FromStr>::Err: std::fmt::Display,
@ -754,6 +773,15 @@ where
return Ok(None);
}
// For duration variables, check if the value ends with "s" and provide a helpful error message
if is_duration && value.trim_end().ends_with('s') {
return Err(Error::InvalidEnvironmentVariable {
name: name.to_string(),
value: value.clone(),
err: "expected an integer value in seconds (e.g., 30), not a string with units (e.g., 30s)".to_string(),
});
}
match value.parse::<T>() {
Ok(v) => Ok(Some(v)),
Err(err) => Err(Error::InvalidEnvironmentVariable {