From 7e44d581cd9d62fbe39182cea0c3fa90eb221fff Mon Sep 17 00:00:00 2001 From: konstin Date: Wed, 6 Aug 2025 12:57:59 +0200 Subject: [PATCH] Don't destructure global networks From reviewing #14687, I was reminded that every base client operation requires manually destructuring the `NetworkSettings`. We can avoid that by passing the global network settings directly. --- crates/uv-client/src/base_client.rs | 27 +++--- crates/uv-client/src/lib.rs | 3 +- crates/uv-client/src/registry_client.rs | 26 ++---- crates/uv-requirements/src/upgrade.rs | 11 ++- crates/uv/src/commands/build_frontend.rs | 8 +- crates/uv/src/commands/pip/compile.rs | 9 +- crates/uv/src/commands/pip/install.rs | 9 +- crates/uv/src/commands/pip/list.rs | 9 +- crates/uv/src/commands/pip/sync.rs | 9 +- crates/uv/src/commands/pip/tree.rs | 9 +- crates/uv/src/commands/pip/uninstall.rs | 9 +- crates/uv/src/commands/project/add.rs | 14 ++- crates/uv/src/commands/project/environment.rs | 3 +- crates/uv/src/commands/project/export.rs | 3 +- crates/uv/src/commands/project/init.rs | 11 +-- crates/uv/src/commands/project/lock.rs | 14 ++- crates/uv/src/commands/project/mod.rs | 38 +++----- crates/uv/src/commands/project/remove.rs | 3 +- crates/uv/src/commands/project/run.rs | 24 ++--- crates/uv/src/commands/project/sync.rs | 12 +-- crates/uv/src/commands/project/tree.rs | 8 +- crates/uv/src/commands/project/version.rs | 3 +- crates/uv/src/commands/publish.rs | 12 ++- crates/uv/src/commands/python/find.rs | 2 +- crates/uv/src/commands/python/install.rs | 6 +- crates/uv/src/commands/python/pin.rs | 6 +- crates/uv/src/commands/self_update.rs | 3 +- crates/uv/src/commands/tool/install.rs | 11 +-- crates/uv/src/commands/tool/run.rs | 6 +- crates/uv/src/commands/tool/upgrade.rs | 8 +- crates/uv/src/commands/venv.rs | 9 +- crates/uv/src/settings.rs | 87 +++++++++---------- crates/uv/tests/it/common/mod.rs | 8 +- 33 files changed, 167 insertions(+), 253 deletions(-) diff --git a/crates/uv-client/src/base_client.rs b/crates/uv-client/src/base_client.rs index aab5f5b70..a517d3c6e 100644 --- a/crates/uv-client/src/base_client.rs +++ b/crates/uv-client/src/base_client.rs @@ -48,6 +48,14 @@ pub const DEFAULT_RETRIES: u32 = 3; /// This is the default used by [`reqwest`]. const DEFAULT_MAX_REDIRECTS: u32 = 10; +/// Global network settings for HTTP client configuration. +#[derive(Debug, Clone, Default)] +pub struct NetworkSettings { + pub connectivity: Connectivity, + pub native_tls: bool, + pub allow_insecure_host: Vec, +} + /// Selectively skip parts or the entire auth middleware. #[derive(Debug, Clone, Copy, Default)] pub enum AuthIntegration { @@ -152,14 +160,11 @@ impl<'a> BaseClientBuilder<'a> { } #[must_use] - pub fn allow_insecure_host(mut self, allow_insecure_host: Vec) -> Self { - self.allow_insecure_host = allow_insecure_host; - self - } - - #[must_use] - pub fn connectivity(mut self, connectivity: Connectivity) -> Self { - self.connectivity = connectivity; + pub fn network_settings(mut self, settings: &NetworkSettings) -> Self { + self.connectivity = settings.connectivity; + self.native_tls = settings.native_tls; + self.allow_insecure_host + .clone_from(&settings.allow_insecure_host); self } @@ -188,12 +193,6 @@ impl<'a> BaseClientBuilder<'a> { } } - #[must_use] - pub fn native_tls(mut self, native_tls: bool) -> Self { - self.native_tls = native_tls; - self - } - #[must_use] pub fn built_in_root_certs(mut self, built_in_root_certs: bool) -> Self { self.built_in_root_certs = built_in_root_certs; diff --git a/crates/uv-client/src/lib.rs b/crates/uv-client/src/lib.rs index e42c86620..95c846725 100644 --- a/crates/uv-client/src/lib.rs +++ b/crates/uv-client/src/lib.rs @@ -1,6 +1,7 @@ pub use base_client::{ AuthIntegration, BaseClient, BaseClientBuilder, DEFAULT_RETRIES, ExtraMiddleware, - RedirectClientWithMiddleware, RequestBuilder, UvRetryableStrategy, is_extended_transient_error, + NetworkSettings, RedirectClientWithMiddleware, RedirectPolicy, RequestBuilder, + UvRetryableStrategy, is_extended_transient_error, }; pub use cached_client::{CacheControl, CachedClient, CachedClientError, DataWithCachePolicy}; pub use error::{Error, ErrorKind, WrappedReqwestError}; diff --git a/crates/uv-client/src/registry_client.rs b/crates/uv-client/src/registry_client.rs index 3a7b049a3..cc5aa2218 100644 --- a/crates/uv-client/src/registry_client.rs +++ b/crates/uv-client/src/registry_client.rs @@ -17,8 +17,8 @@ use url::Url; use uv_auth::Indexes; use uv_cache::{Cache, CacheBucket, CacheEntry, WheelCache}; +use uv_configuration::IndexStrategy; use uv_configuration::KeyringProviderType; -use uv_configuration::{IndexStrategy, TrustedHost}; use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename}; use uv_distribution_types::{ BuiltDist, File, IndexCapabilities, IndexFormat, IndexLocations, IndexMetadataRef, @@ -34,15 +34,15 @@ use uv_redacted::DisplaySafeUrl; use uv_small_str::SmallString; use uv_torch::TorchStrategy; -use crate::base_client::{BaseClientBuilder, ExtraMiddleware, RedirectPolicy}; use crate::cached_client::CacheControl; use crate::flat_index::FlatIndexEntry; use crate::html::SimpleHtml; use crate::remote_metadata::wheel_metadata_from_remote_zip; use crate::rkyvutil::OwnedArchive; use crate::{ - BaseClient, CachedClient, Error, ErrorKind, FlatIndexClient, FlatIndexEntries, - RedirectClientWithMiddleware, + BaseClient, BaseClientBuilder, CachedClient, Error, ErrorKind, ExtraMiddleware, + FlatIndexClient, FlatIndexEntries, NetworkSettings, RedirectClientWithMiddleware, + RedirectPolicy, }; /// A builder for an [`RegistryClient`]. @@ -95,20 +95,6 @@ impl<'a> RegistryClientBuilder<'a> { self } - #[must_use] - pub fn allow_insecure_host(mut self, allow_insecure_host: Vec) -> Self { - self.base_client_builder = self - .base_client_builder - .allow_insecure_host(allow_insecure_host); - self - } - - #[must_use] - pub fn connectivity(mut self, connectivity: Connectivity) -> Self { - self.base_client_builder = self.base_client_builder.connectivity(connectivity); - self - } - #[must_use] pub fn retries(mut self, retries: u32) -> Self { self.base_client_builder = self.base_client_builder.retries(retries); @@ -121,8 +107,8 @@ impl<'a> RegistryClientBuilder<'a> { } #[must_use] - pub fn native_tls(mut self, native_tls: bool) -> Self { - self.base_client_builder = self.base_client_builder.native_tls(native_tls); + pub fn network_settings(mut self, settings: &NetworkSettings) -> Self { + self.base_client_builder = self.base_client_builder.network_settings(settings); self } diff --git a/crates/uv-requirements/src/upgrade.rs b/crates/uv-requirements/src/upgrade.rs index 66c4e96ed..604a6afc2 100644 --- a/crates/uv-requirements/src/upgrade.rs +++ b/crates/uv-requirements/src/upgrade.rs @@ -2,7 +2,7 @@ use std::path::Path; use anyhow::Result; -use uv_client::{BaseClientBuilder, Connectivity}; +use uv_client::{BaseClientBuilder, Connectivity, NetworkSettings}; use uv_configuration::Upgrade; use uv_fs::CWD; use uv_git::ResolvedRepositoryReference; @@ -37,11 +37,18 @@ pub async fn read_requirements_txt( return Ok(Vec::new()); } + // TODO(konsti): Use a better abstraction. + let network_settings = NetworkSettings { + connectivity: Connectivity::Offline, + native_tls: false, + allow_insecure_host: Vec::new(), + }; + // Parse the requirements from the lockfile. let requirements_txt = RequirementsTxt::parse( output_file, &*CWD, - &BaseClientBuilder::new().connectivity(Connectivity::Offline), + &BaseClientBuilder::new().network_settings(&network_settings), ) .await?; diff --git a/crates/uv/src/commands/build_frontend.rs b/crates/uv/src/commands/build_frontend.rs index 726295592..1050e0706 100644 --- a/crates/uv/src/commands/build_frontend.rs +++ b/crates/uv/src/commands/build_frontend.rs @@ -12,7 +12,7 @@ use tracing::instrument; use uv_build_backend::check_direct_build; use uv_cache::{Cache, CacheBucket}; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ BuildKind, BuildOptions, BuildOutput, Concurrency, ConfigSettings, Constraints, DependencyGroupsWithDefaults, HashCheckingMode, IndexStrategy, KeyringProviderType, @@ -47,7 +47,7 @@ use crate::commands::pip::operations; use crate::commands::project::{ProjectError, find_requires_python}; use crate::commands::reporters::PythonDownloadReporter; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverSettings}; +use crate::settings::ResolverSettings; #[derive(Debug, Error)] enum Error { @@ -212,9 +212,7 @@ async fn build_impl( let client_builder = BaseClientBuilder::default() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); // Determine the source to build. let src = if let Some(src) = src { diff --git a/crates/uv/src/commands/pip/compile.rs b/crates/uv/src/commands/pip/compile.rs index 8ea5446d3..d1bb72f52 100644 --- a/crates/uv/src/commands/pip/compile.rs +++ b/crates/uv/src/commands/pip/compile.rs @@ -11,7 +11,7 @@ use rustc_hash::FxHashSet; use tracing::debug; use uv_cache::Cache; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ BuildOptions, Concurrency, ConfigSettings, Constraints, ExportFormat, ExtrasSpecification, IndexStrategy, NoBinary, NoBuild, PackageConfigSettings, Preview, PreviewFeatures, Reinstall, @@ -53,7 +53,6 @@ use crate::commands::pip::loggers::DefaultResolveLogger; use crate::commands::pip::{operations, resolution_environment}; use crate::commands::{ExitStatus, OutputWriter, diagnostics}; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Resolve a set of requirements into a set of pinned versions. #[allow(clippy::fn_params_excessive_bools)] @@ -195,10 +194,8 @@ pub(crate) async fn pip_compile( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Read all requirements from the provided sources. let RequirementsSpecification { diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index da61a0087..7946ce8cf 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -7,7 +7,7 @@ use owo_colors::OwoColorize; use tracing::{Level, debug, enabled, warn}; use uv_cache::Cache; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ BuildOptions, Concurrency, ConfigSettings, Constraints, DryRun, ExtrasSpecification, HashCheckingMode, IndexStrategy, PackageConfigSettings, Preview, PreviewFeatures, Reinstall, @@ -47,7 +47,6 @@ use crate::commands::pip::operations::{report_interpreter, report_target_environ use crate::commands::pip::{operations, resolution_markers, resolution_tags}; use crate::commands::{ExitStatus, diagnostics}; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Install packages into the current environment. #[allow(clippy::fn_params_excessive_bools)] @@ -113,10 +112,8 @@ pub(crate) async fn pip_install( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Read all requirements from the provided sources. let RequirementsSpecification { diff --git a/crates/uv/src/commands/pip/list.rs b/crates/uv/src/commands/pip/list.rs index 95c1aa372..42e88d12b 100644 --- a/crates/uv/src/commands/pip/list.rs +++ b/crates/uv/src/commands/pip/list.rs @@ -14,7 +14,7 @@ use unicode_width::UnicodeWidthStr; use uv_cache::{Cache, Refresh}; use uv_cache_info::Timestamp; use uv_cli::ListFormat; -use uv_client::{BaseClientBuilder, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType, Preview}; use uv_distribution_filename::DistFilename; use uv_distribution_types::{ @@ -33,7 +33,6 @@ use crate::commands::pip::latest::LatestClient; use crate::commands::pip::operations::report_target_environment; use crate::commands::reporters::LatestVersionReporter; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Enumerate the installed packages in the current environment. #[allow(clippy::fn_params_excessive_bools)] @@ -89,10 +88,8 @@ pub(crate) async fn pip_list( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Initialize the registry client. let client = RegistryClientBuilder::try_from(client_builder)? diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index 1b534dd96..5f8481068 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -6,7 +6,7 @@ use owo_colors::OwoColorize; use tracing::{debug, warn}; use uv_cache::Cache; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ BuildOptions, Concurrency, ConfigSettings, Constraints, DryRun, ExtrasSpecification, HashCheckingMode, IndexStrategy, PackageConfigSettings, Preview, PreviewFeatures, Reinstall, @@ -43,7 +43,6 @@ use crate::commands::pip::operations::{report_interpreter, report_target_environ use crate::commands::pip::{operations, resolution_markers, resolution_tags}; use crate::commands::{ExitStatus, diagnostics}; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Install a set of locked requirements into the current Python environment. #[allow(clippy::fn_params_excessive_bools)] @@ -99,10 +98,8 @@ pub(crate) async fn pip_sync( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Initialize a few defaults. let overrides = &[]; diff --git a/crates/uv/src/commands/pip/tree.rs b/crates/uv/src/commands/pip/tree.rs index a288f7ef7..fe949f349 100644 --- a/crates/uv/src/commands/pip/tree.rs +++ b/crates/uv/src/commands/pip/tree.rs @@ -12,7 +12,7 @@ use tokio::sync::Semaphore; use uv_cache::{Cache, Refresh}; use uv_cache_info::Timestamp; -use uv_client::{BaseClientBuilder, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType, Preview}; use uv_distribution_types::{Diagnostic, IndexCapabilities, IndexLocations, Name, RequiresPython}; use uv_installer::SitePackages; @@ -28,7 +28,6 @@ use crate::commands::pip::latest::LatestClient; use crate::commands::pip::operations::report_target_environment; use crate::commands::reporters::LatestVersionReporter; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Display the installed packages in the current environment as a dependency tree. #[allow(clippy::fn_params_excessive_bools)] @@ -88,10 +87,8 @@ pub(crate) async fn pip_tree( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings) + .keyring(keyring_provider); // Initialize the registry client. let client = RegistryClientBuilder::try_from(client_builder)? diff --git a/crates/uv/src/commands/pip/uninstall.rs b/crates/uv/src/commands/pip/uninstall.rs index 2c2b617a2..d0c2d28a0 100644 --- a/crates/uv/src/commands/pip/uninstall.rs +++ b/crates/uv/src/commands/pip/uninstall.rs @@ -6,7 +6,7 @@ use owo_colors::OwoColorize; use tracing::{debug, warn}; use uv_cache::Cache; -use uv_client::BaseClientBuilder; +use uv_client::{BaseClientBuilder, NetworkSettings}; use uv_configuration::{DryRun, KeyringProviderType, Preview}; use uv_distribution_types::Requirement; use uv_distribution_types::{InstalledMetadata, Name, UnresolvedRequirement}; @@ -21,7 +21,6 @@ use uv_requirements::{RequirementsSource, RequirementsSpecification}; use crate::commands::pip::operations::report_target_environment; use crate::commands::{ExitStatus, elapsed}; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Uninstall packages from the current environment. #[allow(clippy::fn_params_excessive_bools)] @@ -43,10 +42,8 @@ pub(crate) async fn pip_uninstall( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Read all requirements from the provided sources. let spec = RequirementsSpecification::from_simple_sources(sources, &client_builder).await?; diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index 25589dd72..d35a72e74 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -15,7 +15,7 @@ use url::Url; use uv_cache::Cache; use uv_cache_key::RepositoryUrl; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ Concurrency, Constraints, DependencyGroups, DependencyGroupsWithDefaults, DevMode, DryRun, EditableMode, ExtrasSpecification, ExtrasSpecificationWithDefaults, InstallOptions, Preview, @@ -59,7 +59,7 @@ use crate::commands::project::{ use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter}; use crate::commands::{ExitStatus, ScriptPath, diagnostics, project}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; /// Add one or more packages to the project requirements. #[allow(clippy::fn_params_excessive_bools)] @@ -189,9 +189,7 @@ pub(crate) async fn add( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); // If we found a script, add to the existing metadata. Otherwise, create a new inline // metadata tag. @@ -343,10 +341,8 @@ pub(crate) async fn add( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(settings.resolver.keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings) + .keyring(settings.resolver.keyring_provider); // Read the requirements. let RequirementsSpecification { diff --git a/crates/uv/src/commands/project/environment.rs b/crates/uv/src/commands/project/environment.rs index 675b1a960..50848fa3d 100644 --- a/crates/uv/src/commands/project/environment.rs +++ b/crates/uv/src/commands/project/environment.rs @@ -8,10 +8,11 @@ use crate::commands::project::{ EnvironmentSpecification, PlatformState, ProjectError, resolve_environment, sync_environment, }; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; use uv_cache::{Cache, CacheBucket}; use uv_cache_key::{cache_digest, hash_digest}; +use uv_client::NetworkSettings; use uv_configuration::{Concurrency, Constraints, Preview}; use uv_distribution_types::{Name, Resolution}; use uv_fs::PythonExt; diff --git a/crates/uv/src/commands/project/export.rs b/crates/uv/src/commands/project/export.rs index 2f1b733d6..3662fbfb9 100644 --- a/crates/uv/src/commands/project/export.rs +++ b/crates/uv/src/commands/project/export.rs @@ -7,6 +7,7 @@ use itertools::Itertools; use owo_colors::OwoColorize; use uv_cache::Cache; +use uv_client::NetworkSettings; use uv_configuration::{ Concurrency, DependencyGroups, EditableMode, ExportFormat, ExtrasSpecification, InstallOptions, Preview, @@ -29,7 +30,7 @@ use crate::commands::project::{ }; use crate::commands::{ExitStatus, OutputWriter, diagnostics}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverSettings}; +use crate::settings::ResolverSettings; #[derive(Debug, Clone)] #[allow(clippy::large_enum_variant)] diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index 98845d1f4..a27a35055 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -10,7 +10,7 @@ use uv_distribution_types::RequiresPython; use tracing::{debug, trace, warn}; use uv_cache::Cache; use uv_cli::AuthorFrom; -use uv_client::BaseClientBuilder; +use uv_client::{BaseClientBuilder, NetworkSettings}; use uv_configuration::{ DependencyGroupsWithDefaults, Preview, ProjectBuildBackend, VersionControlError, VersionControlSystem, @@ -35,7 +35,6 @@ use crate::commands::ExitStatus; use crate::commands::project::{find_requires_python, init_script_python_requirement}; use crate::commands::reporters::PythonDownloadReporter; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Add one or more packages to the project requirements. #[allow(clippy::single_match_else, clippy::fn_params_excessive_bools)] @@ -217,9 +216,7 @@ async fn init_script( } let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); let reporter = PythonDownloadReporter::single(printer); @@ -348,9 +345,7 @@ async fn init_project( let reporter = PythonDownloadReporter::single(printer); let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); // First, determine if there is an request for Python let python_request = if let Some(request) = python { diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index 29fd3b949..213949a57 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -10,7 +10,7 @@ use rustc_hash::{FxBuildHasher, FxHashMap}; use tracing::debug; use uv_cache::Cache; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ Concurrency, Constraints, DependencyGroupsWithDefaults, DryRun, ExtrasSpecification, Preview, PreviewFeatures, Reinstall, Upgrade, @@ -47,7 +47,7 @@ use crate::commands::project::{ use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter}; use crate::commands::{ExitStatus, ScriptPath, diagnostics, pip}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverSettings}; +use crate::settings::ResolverSettings; /// The result of running a lock operation. #[derive(Debug, Clone)] @@ -100,9 +100,7 @@ pub(crate) async fn lock( Some(ScriptPath::Path(path)) => { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); let reporter = PythonDownloadReporter::single(printer); let requires_python = init_script_python_requirement( python.as_deref(), @@ -609,10 +607,8 @@ async fn do_lock( // Initialize the client. let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(*keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(*keyring_provider); index_locations.cache_index_credentials(); diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 73b1f98d2..0e9f6e93c 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -10,7 +10,7 @@ use tracing::{debug, trace, warn}; use uv_cache::{Cache, CacheBucket}; use uv_cache_key::cache_digest; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ Concurrency, Constraints, DependencyGroupsWithDefaults, DryRun, ExtrasSpecification, Preview, PreviewFeatures, Reinstall, Upgrade, @@ -55,9 +55,7 @@ use crate::commands::pip::operations::{Changelog, Modifications}; use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter}; use crate::commands::{capitalize, conjunction, pip}; use crate::printer::Printer; -use crate::settings::{ - InstallerSettingsRef, NetworkSettings, ResolverInstallerSettings, ResolverSettings, -}; +use crate::settings::{InstallerSettingsRef, ResolverInstallerSettings, ResolverSettings}; pub(crate) mod add; pub(crate) mod environment; @@ -694,9 +692,7 @@ impl ScriptInterpreter { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); let reporter = PythonDownloadReporter::single(printer); @@ -978,9 +974,7 @@ impl ProjectInterpreter { let client_builder = BaseClientBuilder::default() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); let reporter = PythonDownloadReporter::single(printer); @@ -1709,10 +1703,8 @@ pub(crate) async fn resolve_names( let client_builder = BaseClientBuilder::new() .retries_from_env() .map_err(uv_requirements::Error::ClientError)? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(*keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(*keyring_provider); index_locations.cache_index_credentials(); @@ -1876,10 +1868,8 @@ pub(crate) async fn resolve_environment( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(*keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(*keyring_provider); // Determine the tags, markers, and interpreter to use for resolution. let tags = interpreter.tags()?; @@ -2057,10 +2047,8 @@ pub(crate) async fn sync_environment( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); let site_packages = SitePackages::from_environment(&venv)?; @@ -2229,10 +2217,8 @@ pub(crate) async fn update_environment( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(*keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(*keyring_provider); // Respect all requirements from the provided sources. let RequirementsSpecification { diff --git a/crates/uv/src/commands/project/remove.rs b/crates/uv/src/commands/project/remove.rs index 649e6c887..b3f12cea5 100644 --- a/crates/uv/src/commands/project/remove.rs +++ b/crates/uv/src/commands/project/remove.rs @@ -8,6 +8,7 @@ use owo_colors::OwoColorize; use tracing::{debug, warn}; use uv_cache::Cache; +use uv_client::NetworkSettings; use uv_configuration::{ Concurrency, DependencyGroups, DryRun, EditableMode, ExtrasSpecification, InstallOptions, Preview, @@ -35,7 +36,7 @@ use crate::commands::project::{ }; use crate::commands::{ExitStatus, diagnostics, project}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; /// Remove one or more packages from the project requirements. #[allow(clippy::fn_params_excessive_bools)] diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index 03fcad872..d46e61b2c 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -16,7 +16,7 @@ use url::Url; use uv_cache::Cache; use uv_cli::ExternalCommand; -use uv_client::BaseClientBuilder; +use uv_client::{BaseClientBuilder, NetworkSettings}; use uv_configuration::{ Concurrency, Constraints, DependencyGroups, DryRun, EditableMode, ExtrasSpecification, InstallOptions, Preview, @@ -70,7 +70,7 @@ use crate::commands::project::{ use crate::commands::reporters::PythonDownloadReporter; use crate::commands::{ExitStatus, diagnostics, project}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; /// Run a command. #[allow(clippy::fn_params_excessive_bools)] @@ -634,9 +634,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl // base environment for the project. let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); // Resolve the Python request and requirement for the workspace. let WorkspacePython { @@ -876,9 +874,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl let interpreter = { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); // (1) Explicit request from user let python_request = if let Some(request) = python.as_deref() { @@ -947,9 +943,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl } else { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); let spec = RequirementsSpecification::from_simple_sources(&requirements, &client_builder).await?; @@ -1623,9 +1617,7 @@ async fn resolve_gist_url( let client = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(network_settings) .build(); // Build the request with appropriate headers. @@ -1723,9 +1715,7 @@ impl RunCommand { let client = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(&network_settings) .build(); let response = client .for_host(&url) diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index 44d9dfe82..e2f13b705 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -10,7 +10,7 @@ use serde::Serialize; use tracing::warn; use uv_cache::Cache; use uv_cli::SyncFormat; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ Concurrency, Constraints, DependencyGroups, DependencyGroupsWithDefaults, DryRun, EditableMode, ExtrasSpecification, ExtrasSpecificationWithDefaults, HashCheckingMode, InstallOptions, @@ -49,9 +49,7 @@ use crate::commands::project::{ }; use crate::commands::{ExitStatus, diagnostics}; use crate::printer::Printer; -use crate::settings::{ - InstallerSettingsRef, NetworkSettings, ResolverInstallerSettings, ResolverSettings, -}; +use crate::settings::{InstallerSettingsRef, ResolverInstallerSettings, ResolverSettings}; /// Sync the project environment. #[allow(clippy::fn_params_excessive_bools)] @@ -643,10 +641,8 @@ pub(super) async fn do_sync( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings) + .keyring(keyring_provider); // Validate that the Python version is supported by the lockfile. if !target diff --git a/crates/uv/src/commands/project/tree.rs b/crates/uv/src/commands/project/tree.rs index 1f8f46a3d..5da74bbc5 100644 --- a/crates/uv/src/commands/project/tree.rs +++ b/crates/uv/src/commands/project/tree.rs @@ -6,7 +6,7 @@ use futures::StreamExt; use tokio::sync::Semaphore; use uv_cache::{Cache, Refresh}; use uv_cache_info::Timestamp; -use uv_client::RegistryClientBuilder; +use uv_client::{NetworkSettings, RegistryClientBuilder}; use uv_configuration::{Concurrency, DependencyGroups, Preview, TargetTriple}; use uv_distribution_types::IndexCapabilities; use uv_normalize::DefaultGroups; @@ -28,7 +28,7 @@ use crate::commands::project::{ use crate::commands::reporters::LatestVersionReporter; use crate::commands::{ExitStatus, diagnostics}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverSettings}; +use crate::settings::ResolverSettings; /// Run a command. #[allow(clippy::fn_params_excessive_bools)] @@ -218,9 +218,7 @@ pub(crate) async fn tree( cache.clone().with_refresh(Refresh::All(Timestamp::now())), ) .retries_from_env()? - .native_tls(network_settings.native_tls) - .connectivity(network_settings.connectivity) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(network_settings) .index_locations(index_locations) .keyring(*keyring_provider) .build(); diff --git a/crates/uv/src/commands/project/version.rs b/crates/uv/src/commands/project/version.rs index 566573594..5498da33c 100644 --- a/crates/uv/src/commands/project/version.rs +++ b/crates/uv/src/commands/project/version.rs @@ -9,6 +9,7 @@ use tracing::debug; use uv_cache::Cache; use uv_cli::version::VersionInfo; use uv_cli::{VersionBump, VersionFormat}; +use uv_client::NetworkSettings; use uv_configuration::{ Concurrency, DependencyGroups, DependencyGroupsWithDefaults, DryRun, EditableMode, ExtrasSpecification, InstallOptions, Preview, @@ -36,7 +37,7 @@ use crate::commands::project::{ }; use crate::commands::{ExitStatus, diagnostics, project}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; /// Display version information for uv itself (`uv self version`) pub(crate) fn self_version( diff --git a/crates/uv/src/commands/publish.rs b/crates/uv/src/commands/publish.rs index da61b7ca5..6b3638d83 100644 --- a/crates/uv/src/commands/publish.rs +++ b/crates/uv/src/commands/publish.rs @@ -9,7 +9,9 @@ use tokio::sync::Semaphore; use tracing::{debug, info, trace}; use uv_auth::Credentials; use uv_cache::Cache; -use uv_client::{AuthIntegration, BaseClient, BaseClientBuilder, RegistryClientBuilder}; +use uv_client::{ + AuthIntegration, BaseClient, BaseClientBuilder, NetworkSettings, RegistryClientBuilder, +}; use uv_configuration::{KeyringProviderType, TrustedPublishing}; use uv_distribution_types::{Index, IndexCapabilities, IndexLocations, IndexUrl}; use uv_publish::{ @@ -21,7 +23,6 @@ use uv_warnings::{warn_user_once, write_error_chain}; use crate::commands::reporters::PublishReporter; use crate::commands::{ExitStatus, human_readable_bytes}; use crate::printer::Printer; -use crate::settings::NetworkSettings; pub(crate) async fn publish( paths: Vec, @@ -59,8 +60,7 @@ pub(crate) async fn publish( let upload_client = BaseClientBuilder::new() .retries(0) .keyring(keyring_provider) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(network_settings) // Don't try cloning the request to make an unauthenticated request first. .auth_integration(AuthIntegration::OnlyAuthenticated) // Set a very high timeout for uploads, connections are often 10x slower on upload than @@ -95,9 +95,7 @@ pub(crate) async fn publish( ); let registry_client_builder = RegistryClientBuilder::new(cache.clone()) .retries_from_env()? - .native_tls(network_settings.native_tls) - .connectivity(network_settings.connectivity) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(network_settings) .index_locations(&index_locations) .keyring(keyring_provider); Some(CheckUrlClient { diff --git a/crates/uv/src/commands/python/find.rs b/crates/uv/src/commands/python/find.rs index 806e670a8..b0cf1d86e 100644 --- a/crates/uv/src/commands/python/find.rs +++ b/crates/uv/src/commands/python/find.rs @@ -3,6 +3,7 @@ use std::fmt::Write; use std::path::Path; use uv_cache::Cache; +use uv_client::NetworkSettings; use uv_configuration::{DependencyGroupsWithDefaults, Preview}; use uv_fs::Simplified; use uv_python::{ @@ -18,7 +19,6 @@ use crate::commands::{ project::{ScriptInterpreter, WorkspacePython, validate_project_requires_python}, }; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Find a Python interpreter. #[allow(clippy::fn_params_excessive_bools)] diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 40c98977e..4c4a8f34b 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -14,6 +14,7 @@ use owo_colors::{AnsiColors, OwoColorize}; use rustc_hash::{FxHashMap, FxHashSet}; use tracing::{debug, trace}; +use uv_client::NetworkSettings; use uv_configuration::{Preview, PreviewFeatures}; use uv_fs::Simplified; use uv_platform::{Arch, Libc}; @@ -36,7 +37,6 @@ use crate::commands::python::{ChangeEvent, ChangeEventKind}; use crate::commands::reporters::PythonDownloadReporter; use crate::commands::{ExitStatus, elapsed}; use crate::printer::Printer; -use crate::settings::NetworkSettings; #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct InstallRequest { @@ -393,9 +393,7 @@ pub(crate) async fn install( // Download and unpack the Python versions concurrently let client = uv_client::BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) + .network_settings(&network_settings) .build(); let reporter = PythonDownloadReporter::new(printer, downloads.len() as u64); let mut tasks = FuturesUnordered::new(); diff --git a/crates/uv/src/commands/python/pin.rs b/crates/uv/src/commands/python/pin.rs index 064cc780c..4e11f8bd7 100644 --- a/crates/uv/src/commands/python/pin.rs +++ b/crates/uv/src/commands/python/pin.rs @@ -22,7 +22,7 @@ use crate::commands::{ ExitStatus, project::find_requires_python, reporters::PythonDownloadReporter, }; use crate::printer::Printer; -use crate::settings::NetworkSettings; +use uv_client::NetworkSettings; /// Pin to a specific Python version. #[allow(clippy::fn_params_excessive_bools)] @@ -117,9 +117,7 @@ pub(crate) async fn pin( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); let reporter = PythonDownloadReporter::single(printer); let python = match PythonInstallation::find_or_download( diff --git a/crates/uv/src/commands/self_update.rs b/crates/uv/src/commands/self_update.rs index 4b4fd4830..247b4568a 100644 --- a/crates/uv/src/commands/self_update.rs +++ b/crates/uv/src/commands/self_update.rs @@ -5,12 +5,11 @@ use axoupdater::{AxoUpdater, AxoupdateError, UpdateRequest}; use owo_colors::OwoColorize; use tracing::debug; -use uv_client::WrappedReqwestError; +use uv_client::{NetworkSettings, WrappedReqwestError}; use uv_fs::Simplified; use crate::commands::ExitStatus; use crate::printer::Printer; -use crate::settings::NetworkSettings; /// Attempt to update the uv binary. pub(crate) async fn self_update( diff --git a/crates/uv/src/commands/tool/install.rs b/crates/uv/src/commands/tool/install.rs index b191d0e1e..753636125 100644 --- a/crates/uv/src/commands/tool/install.rs +++ b/crates/uv/src/commands/tool/install.rs @@ -38,7 +38,8 @@ use crate::commands::tool::common::{ use crate::commands::tool::{Target, ToolRequest}; use crate::commands::{diagnostics, reporters::PythonDownloadReporter}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings, ResolverSettings}; +use crate::settings::{ResolverInstallerSettings, ResolverSettings}; +use uv_client::NetworkSettings; /// Install a tool. #[allow(clippy::fn_params_excessive_bools)] @@ -67,9 +68,7 @@ pub(crate) async fn install( ) -> Result { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); let reporter = PythonDownloadReporter::single(printer); @@ -99,9 +98,7 @@ pub(crate) async fn install( let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); // Parse the input requirement. let request = ToolRequest::parse(&package, from.as_deref())?; diff --git a/crates/uv/src/commands/tool/run.rs b/crates/uv/src/commands/tool/run.rs index 64628e56a..e46d48fca 100644 --- a/crates/uv/src/commands/tool/run.rs +++ b/crates/uv/src/commands/tool/run.rs @@ -55,8 +55,8 @@ use crate::commands::tool::common::{matching_packages, refine_interpreter}; use crate::commands::tool::{Target, ToolRequest}; use crate::commands::{diagnostics, project::environment::CachedEnvironment}; use crate::printer::Printer; -use crate::settings::NetworkSettings; use crate::settings::ResolverInstallerSettings; +use uv_client::NetworkSettings; /// The user-facing command used to invoke a tool run. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -690,9 +690,7 @@ async fn get_or_create_environment( ) -> Result<(ToolRequirement, PythonEnvironment), ProjectError> { let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(network_settings); let reporter = PythonDownloadReporter::single(printer); diff --git a/crates/uv/src/commands/tool/upgrade.rs b/crates/uv/src/commands/tool/upgrade.rs index 4c62e15d6..dea221ea6 100644 --- a/crates/uv/src/commands/tool/upgrade.rs +++ b/crates/uv/src/commands/tool/upgrade.rs @@ -7,7 +7,7 @@ use std::str::FromStr; use tracing::{debug, trace}; use uv_cache::Cache; -use uv_client::BaseClientBuilder; +use uv_client::{BaseClientBuilder, NetworkSettings}; use uv_configuration::{Concurrency, Constraints, DryRun, Preview}; use uv_distribution_types::{ExtraBuildRequires, Requirement}; use uv_fs::CWD; @@ -33,7 +33,7 @@ use crate::commands::reporters::PythonDownloadReporter; use crate::commands::tool::common::remove_entrypoints; use crate::commands::{ExitStatus, conjunction, tool::common::finalize_tool_install}; use crate::printer::Printer; -use crate::settings::{NetworkSettings, ResolverInstallerSettings}; +use crate::settings::ResolverInstallerSettings; /// Upgrade a tool. pub(crate) async fn upgrade( @@ -83,9 +83,7 @@ pub(crate) async fn upgrade( let reporter = PythonDownloadReporter::single(printer); let client_builder = BaseClientBuilder::new() .retries_from_env()? - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + .network_settings(&network_settings); let python_request = python.as_deref().map(PythonRequest::parse); diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index 48b63182a..62cbb5a69 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -8,7 +8,7 @@ use owo_colors::OwoColorize; use thiserror::Error; use uv_cache::Cache; -use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; +use uv_client::{BaseClientBuilder, FlatIndexClient, NetworkSettings, RegistryClientBuilder}; use uv_configuration::{ BuildOptions, Concurrency, ConfigSettings, Constraints, DependencyGroups, IndexStrategy, KeyringProviderType, NoBinary, NoBuild, PackageConfigSettings, Preview, PreviewFeatures, @@ -37,7 +37,6 @@ use crate::commands::pip::operations::{Changelog, report_interpreter}; use crate::commands::project::{WorkspacePython, validate_project_requires_python}; use crate::commands::reporters::PythonDownloadReporter; use crate::printer::Printer; -use crate::settings::NetworkSettings; use super::project::default_dependency_groups; @@ -127,10 +126,7 @@ pub(crate) async fn 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() - .connectivity(network_settings.connectivity) - .native_tls(network_settings.native_tls) - .allow_insecure_host(network_settings.allow_insecure_host.clone()); + let client_builder = BaseClientBuilder::default().network_settings(network_settings); let reporter = PythonDownloadReporter::single(printer); @@ -232,7 +228,6 @@ pub(crate) async fn venv( .index_locations(index_locations) .index_strategy(index_strategy) .keyring(keyring_provider) - .allow_insecure_host(network_settings.allow_insecure_host.clone()) .markers(interpreter.markers()) .platform(interpreter.platform()) .build(); diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index e048f1c95..97fb46739 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -19,13 +19,13 @@ use uv_cli::{ ToolUpgradeArgs, options::{flag, resolver_installer_options, resolver_options}, }; -use uv_client::Connectivity; +use uv_client::{Connectivity, NetworkSettings}; use uv_configuration::{ BuildOptions, Concurrency, ConfigSettings, DependencyGroups, DryRun, EditableMode, ExportFormat, ExtrasSpecification, HashCheckingMode, IndexStrategy, InstallOptions, KeyringProviderType, NoBinary, NoBuild, PackageConfigSettings, Preview, ProjectBuildBackend, - Reinstall, RequiredVersion, SourceStrategy, TargetTriple, TrustedHost, TrustedPublishing, - Upgrade, VersionControlSystem, + Reinstall, RequiredVersion, SourceStrategy, TargetTriple, TrustedPublishing, Upgrade, + VersionControlSystem, }; use uv_distribution_types::{DependencyMetadata, Index, IndexLocations, IndexUrl, Requirement}; use uv_install_wheel::LinkMode; @@ -74,7 +74,7 @@ pub(crate) struct GlobalSettings { impl GlobalSettings { /// Resolve the [`GlobalSettings`] from the CLI and filesystem configuration. pub(crate) fn resolve(args: &GlobalArgs, workspace: Option<&FilesystemOptions>) -> Self { - let network_settings = NetworkSettings::resolve(args, workspace); + let network_settings = resolve_network_settings(args, workspace); let python_preference = resolve_python_preference(args, workspace); Self { required_version: workspace @@ -158,49 +158,42 @@ fn resolve_python_preference( } } -/// The resolved network settings to use for any invocation of the CLI. -#[derive(Debug, Clone)] -pub(crate) struct NetworkSettings { - pub(crate) connectivity: Connectivity, - pub(crate) native_tls: bool, - pub(crate) allow_insecure_host: Vec, -} - -impl NetworkSettings { - pub(crate) fn resolve(args: &GlobalArgs, workspace: Option<&FilesystemOptions>) -> Self { - let connectivity = if flag(args.offline, args.no_offline, "offline") - .combine(workspace.and_then(|workspace| workspace.globals.offline)) - .unwrap_or(false) - { - Connectivity::Offline - } else { - Connectivity::Online - }; - let native_tls = flag(args.native_tls, args.no_native_tls, "native-tls") - .combine(workspace.and_then(|workspace| workspace.globals.native_tls)) - .unwrap_or(false); - let allow_insecure_host = args - .allow_insecure_host - .as_ref() - .map(|allow_insecure_host| { - allow_insecure_host - .iter() - .filter_map(|value| value.clone().into_option()) - }) - .into_iter() - .flatten() - .chain( - workspace - .and_then(|workspace| workspace.globals.allow_insecure_host.clone()) - .into_iter() - .flatten(), - ) - .collect(); - Self { - connectivity, - native_tls, - allow_insecure_host, - } +pub(crate) fn resolve_network_settings( + args: &GlobalArgs, + workspace: Option<&FilesystemOptions>, +) -> NetworkSettings { + let connectivity = if flag(args.offline, args.no_offline, "offline") + .combine(workspace.and_then(|workspace| workspace.globals.offline)) + .unwrap_or(false) + { + Connectivity::Offline + } else { + Connectivity::Online + }; + let native_tls = flag(args.native_tls, args.no_native_tls, "native-tls") + .combine(workspace.and_then(|workspace| workspace.globals.native_tls)) + .unwrap_or(false); + let allow_insecure_host = args + .allow_insecure_host + .as_ref() + .map(|allow_insecure_host| { + allow_insecure_host + .iter() + .filter_map(|value| value.clone().into_option()) + }) + .into_iter() + .flatten() + .chain( + workspace + .and_then(|workspace| workspace.globals.allow_insecure_host.clone()) + .into_iter() + .flatten(), + ) + .collect(); + NetworkSettings { + connectivity, + native_tls, + allow_insecure_host, } } diff --git a/crates/uv/tests/it/common/mod.rs b/crates/uv/tests/it/common/mod.rs index d0982642d..4cdfe08ef 100644 --- a/crates/uv/tests/it/common/mod.rs +++ b/crates/uv/tests/it/common/mod.rs @@ -21,6 +21,7 @@ use regex::Regex; use tokio::io::AsyncWriteExt; use uv_cache::{Cache, CacheBucket}; +use uv_client::NetworkSettings; use uv_configuration::Preview; use uv_fs::Simplified; use uv_python::managed::ManagedPythonInstallations; @@ -1752,8 +1753,13 @@ pub async fn download_to_disk(url: &str, path: &Path) { .map(|h| uv_configuration::TrustedHost::from_str(h).unwrap()) .collect(); + let network_settings = NetworkSettings { + allow_insecure_host: trusted_hosts, + ..NetworkSettings::default() + }; + let client = uv_client::BaseClientBuilder::new() - .allow_insecure_host(trusted_hosts) + .network_settings(&network_settings) .build(); let url = url.parse().unwrap(); let response = client