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