mirror of https://github.com/astral-sh/uv
Add lazy base client construction
This commit is contained in:
parent
d91f64ea9a
commit
91fc60f938
|
|
@ -4360,6 +4360,7 @@ dependencies = [
|
|||
"hyper 0.14.28",
|
||||
"insta",
|
||||
"install-wheel-rs",
|
||||
"itertools 0.12.1",
|
||||
"pep440_rs",
|
||||
"pep508_rs",
|
||||
"platform-tags",
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ use pep508_rs::{
|
|||
};
|
||||
#[cfg(feature = "http")]
|
||||
use uv_client::BaseClient;
|
||||
use uv_client::BaseClientBuilder;
|
||||
use uv_client::{BaseClientBuilder, LazyBaseClientBuilder};
|
||||
use uv_fs::{normalize_url_path, Simplified};
|
||||
use uv_normalize::ExtraName;
|
||||
use uv_warnings::warn_user;
|
||||
|
|
@ -334,7 +334,7 @@ impl RequirementsTxt {
|
|||
pub async fn parse(
|
||||
requirements_txt: impl AsRef<Path>,
|
||||
working_dir: impl AsRef<Path>,
|
||||
client_builder: BaseClientBuilder,
|
||||
client_builder: &mut LazyBaseClientBuilder,
|
||||
) -> Result<Self, RequirementsTxtFileError> {
|
||||
let requirements_txt = requirements_txt.as_ref();
|
||||
let working_dir = working_dir.as_ref();
|
||||
|
|
@ -355,17 +355,17 @@ impl RequirementsTxt {
|
|||
#[cfg(feature = "http")]
|
||||
{
|
||||
// Avoid constructing a client if network is disabled already
|
||||
if client_builder.is_offline() {
|
||||
return Err(RequirementsTxtFileError {
|
||||
file: requirements_txt.to_path_buf(),
|
||||
error: RequirementsTxtParserError::IO(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("Network connectivity is disabled, but a remote requirements file was requested: {}", requirements_txt.display()),
|
||||
)),
|
||||
});
|
||||
}
|
||||
// if client_builder.is_offline() {
|
||||
// return Err(RequirementsTxtFileError {
|
||||
// file: requirements_txt.to_path_buf(),
|
||||
// error: RequirementsTxtParserError::IO(io::Error::new(
|
||||
// io::ErrorKind::InvalidInput,
|
||||
// format!("Network connectivity is disabled, but a remote requirements file was requested: {}", requirements_txt.display()),
|
||||
// )),
|
||||
// });
|
||||
// }
|
||||
|
||||
let client = client_builder.clone().build();
|
||||
let client = client_builder.build();
|
||||
read_url_to_string(&requirements_txt, client).await
|
||||
}
|
||||
} else {
|
||||
|
|
@ -406,7 +406,7 @@ impl RequirementsTxt {
|
|||
content: &str,
|
||||
working_dir: &Path,
|
||||
requirements_dir: &Path,
|
||||
client_builder: BaseClientBuilder,
|
||||
client_builder: &mut LazyBaseClientBuilder,
|
||||
) -> Result<Self, RequirementsTxtParserError> {
|
||||
let mut s = Scanner::new(content);
|
||||
|
||||
|
|
@ -425,8 +425,7 @@ impl RequirementsTxt {
|
|||
} else {
|
||||
requirements_dir.join(filename.as_ref())
|
||||
};
|
||||
let sub_requirements =
|
||||
Self::parse(&sub_file, working_dir, client_builder.clone())
|
||||
let sub_requirements = Self::parse(&sub_file, working_dir, client_builder)
|
||||
.await
|
||||
.map_err(|err| RequirementsTxtParserError::Subfile {
|
||||
source: Box::new(err),
|
||||
|
|
@ -464,8 +463,7 @@ impl RequirementsTxt {
|
|||
} else {
|
||||
requirements_dir.join(filename.as_ref())
|
||||
};
|
||||
let sub_constraints =
|
||||
Self::parse(&sub_file, working_dir, client_builder.clone())
|
||||
let sub_constraints = Self::parse(&sub_file, working_dir, client_builder)
|
||||
.await
|
||||
.map_err(|err| RequirementsTxtParserError::Subfile {
|
||||
source: Box::new(err),
|
||||
|
|
@ -835,7 +833,7 @@ fn parse_value<'a, T>(
|
|||
#[cfg(feature = "http")]
|
||||
async fn read_url_to_string(
|
||||
path: impl AsRef<Path>,
|
||||
client: BaseClient,
|
||||
client: &BaseClient,
|
||||
) -> Result<String, RequirementsTxtParserError> {
|
||||
// pip would URL-encode the non-UTF-8 bytes of the string; we just don't support them.
|
||||
let path_utf8 =
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ fs-err = { workspace = true, features = ["tokio"] }
|
|||
futures = { workspace = true }
|
||||
html-escape = { workspace = true }
|
||||
http = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
reqwest-middleware = { workspace = true }
|
||||
reqwest-retry = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
use itertools::Either;
|
||||
use reqwest::{Client, ClientBuilder};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use reqwest_retry::policies::ExponentialBackoff;
|
||||
use reqwest_retry::RetryTransientMiddleware;
|
||||
use std::env;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
use tracing::debug;
|
||||
use uv_auth::{AuthMiddleware, KeyringProvider};
|
||||
use uv_fs::Simplified;
|
||||
|
|
@ -78,6 +81,10 @@ impl BaseClientBuilder {
|
|||
matches!(self.connectivity, Connectivity::Offline)
|
||||
}
|
||||
|
||||
pub fn to_lazy_builder(self) -> LazyBaseClientBuilder {
|
||||
LazyBaseClientBuilder::new(self)
|
||||
}
|
||||
|
||||
pub fn build(self) -> BaseClient {
|
||||
// Create user agent.
|
||||
let user_agent_string = format!("uv/{}", version());
|
||||
|
|
@ -185,3 +192,27 @@ impl BaseClient {
|
|||
self.connectivity
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LazyBaseClientBuilder {
|
||||
builder: Option<BaseClientBuilder>,
|
||||
client: Option<BaseClient>,
|
||||
}
|
||||
|
||||
impl LazyBaseClientBuilder {
|
||||
fn new(builder: BaseClientBuilder) -> Self {
|
||||
Self {
|
||||
builder: Some(builder),
|
||||
client: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(&mut self) -> &BaseClient {
|
||||
if let Some(ref client) = self.client {
|
||||
client
|
||||
} else {
|
||||
let builder = self.builder.take().unwrap();
|
||||
let client = self.client.insert(builder.build());
|
||||
client
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
pub use base_client::{BaseClient, BaseClientBuilder};
|
||||
pub use base_client::{BaseClient, BaseClientBuilder, LazyBaseClientBuilder};
|
||||
pub use cached_client::{CacheControl, CachedClient, CachedClientError, DataWithCachePolicy};
|
||||
pub use error::{BetterReqwestError, Error, ErrorKind};
|
||||
pub use flat_index::{FlatDistributions, FlatIndex, FlatIndexClient, FlatIndexError};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use tracing::{instrument, Level};
|
|||
use distribution_types::{FlatIndexLocation, IndexUrl};
|
||||
use pep508_rs::Requirement;
|
||||
use requirements_txt::{EditableRequirement, FindLink, RequirementsTxt};
|
||||
use uv_client::{BaseClientBuilder, Connectivity};
|
||||
use uv_client::{BaseClient, BaseClientBuilder, Connectivity, LazyBaseClientBuilder};
|
||||
use uv_fs::Simplified;
|
||||
use uv_normalize::{ExtraName, PackageName};
|
||||
use uv_warnings::warn_user;
|
||||
|
|
@ -142,7 +142,7 @@ impl RequirementsSpecification {
|
|||
pub(crate) async fn from_source(
|
||||
source: &RequirementsSource,
|
||||
extras: &ExtrasSpecification<'_>,
|
||||
client_builder: BaseClientBuilder,
|
||||
client_builder: &mut LazyBaseClientBuilder,
|
||||
) -> Result<Self> {
|
||||
Ok(match source {
|
||||
RequirementsSource::Package(name) => {
|
||||
|
|
@ -284,12 +284,13 @@ impl RequirementsSpecification {
|
|||
client_builder: BaseClientBuilder,
|
||||
) -> Result<Self> {
|
||||
let mut spec = Self::default();
|
||||
let mut client_builder = client_builder.to_lazy_builder();
|
||||
|
||||
// Read all requirements, and keep track of all requirements _and_ constraints.
|
||||
// A `requirements.txt` can contain a `-c constraints.txt` directive within it, so reading
|
||||
// a requirements file can also add constraints.
|
||||
for source in requirements {
|
||||
let source = Self::from_source(source, extras, client_builder.clone()).await?;
|
||||
let source = Self::from_source(source, extras, &mut client_builder).await?;
|
||||
spec.requirements.extend(source.requirements);
|
||||
spec.constraints.extend(source.constraints);
|
||||
spec.overrides.extend(source.overrides);
|
||||
|
|
@ -316,7 +317,7 @@ impl RequirementsSpecification {
|
|||
|
||||
// Read all constraints, treating _everything_ as a constraint.
|
||||
for source in constraints {
|
||||
let source = Self::from_source(source, extras, client_builder.clone()).await?;
|
||||
let source = Self::from_source(source, extras, &mut client_builder).await?;
|
||||
spec.constraints.extend(source.requirements);
|
||||
spec.constraints.extend(source.constraints);
|
||||
spec.constraints.extend(source.overrides);
|
||||
|
|
@ -336,7 +337,7 @@ impl RequirementsSpecification {
|
|||
|
||||
// Read all overrides, treating both requirements _and_ constraints as overrides.
|
||||
for source in overrides {
|
||||
let source = Self::from_source(source, extras, client_builder.clone()).await?;
|
||||
let source = Self::from_source(source, extras, &mut client_builder).await?;
|
||||
spec.overrides.extend(source.requirements);
|
||||
spec.overrides.extend(source.constraints);
|
||||
spec.overrides.extend(source.overrides);
|
||||
|
|
@ -458,7 +459,9 @@ pub(crate) async fn read_lockfile(
|
|||
let requirements_txt = RequirementsTxt::parse(
|
||||
output_file,
|
||||
std::env::current_dir()?,
|
||||
BaseClientBuilder::new().connectivity(Connectivity::Offline),
|
||||
&mut BaseClientBuilder::new()
|
||||
.connectivity(Connectivity::Offline)
|
||||
.to_lazy_builder(),
|
||||
)
|
||||
.await?;
|
||||
let requirements = requirements_txt
|
||||
|
|
|
|||
Loading…
Reference in New Issue