Add an HTTP cache (and --no-cache argument) (#14)

Closes https://github.com/astral-sh/puffin/issues/3.
This commit is contained in:
Charlie Marsh 2023-10-05 19:14:05 -04:00 committed by GitHub
parent 1063d8c150
commit 2d6266b167
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 31 additions and 23 deletions

View file

@ -10,5 +10,3 @@ documentation = "https://astral.sh"
repository = "https://github.com/astral-sh/puffin"
authors = ["Astral Software Inc. <hey@astral.sh>"]
license = "MIT OR Apache-2.0"
[workspace.dependencies]

View file

@ -23,3 +23,4 @@ pep440_rs = { version = "0.3.12" }
tracing = { version = "0.1.37" }
tracing-tree = { version = "0.2.5" }
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
directories = "5.0.1"

View file

@ -29,7 +29,7 @@ enum Response {
Version(Metadata21, Requirement),
}
pub(crate) async fn install(src: &Path) -> Result<ExitStatus> {
pub(crate) async fn install(src: &Path, cache: Option<&Path>) -> Result<ExitStatus> {
// Read the `requirements.txt` from disk.
let requirements_txt = std::fs::read_to_string(src)?;
@ -44,8 +44,13 @@ pub(crate) async fn install(src: &Path) -> Result<ExitStatus> {
);
// Instantiate a client.
let pypi_client = PypiClientBuilder::default().build();
let proxy_client = PypiClientBuilder::default().build();
let pypi_client = {
let mut pypi_client = PypiClientBuilder::default();
if let Some(cache) = cache {
pypi_client = pypi_client.cache(cache);
}
pypi_client.build()
};
// A channel to fetch package metadata (e.g., given `flask`, fetch all versions) and version
// metadata (e.g., given `flask==1.0.0`, fetch the metadata for that version).
@ -60,7 +65,7 @@ pub(crate) async fn install(src: &Path) -> Result<ExitStatus> {
.map_ok(move |metadata| Response::Package(metadata, requirement)),
),
Request::Version(requirement, file) => Either::Right(
proxy_client
pypi_client
.file(file)
.map_ok(move |metadata| Response::Version(metadata, requirement)),
),

View file

@ -3,6 +3,7 @@ use std::process::ExitCode;
use clap::{Args, Parser, Subcommand};
use colored::Colorize;
use directories::ProjectDirs;
use crate::commands::ExitStatus;
@ -27,6 +28,10 @@ enum Commands {
struct InstallArgs {
/// Path to the `requirements.text` file to install.
src: PathBuf,
/// Avoid reading from or writing to the cache.
#[arg(long)]
no_cache: bool,
}
#[async_std::main]
@ -35,8 +40,18 @@ async fn main() -> ExitCode {
let _ = logging::setup_logging();
let dirs = ProjectDirs::from("", "", "puffin");
let result = match &cli.command {
Commands::Install(install) => commands::install(&install.src).await,
Commands::Install(install) => {
commands::install(
&install.src,
dirs.as_ref()
.map(directories::ProjectDirs::cache_dir)
.filter(|_| !install.no_cache),
)
.await
}
};
match result {

View file

@ -16,8 +16,6 @@ impl PypiClient {
&self,
package_name: impl AsRef<str>,
) -> Result<SimpleJson, PypiClientError> {
let start = std::time::Instant::now();
// Format the URL for PyPI.
let mut url = self.registry.join("simple")?;
url.path_segments_mut()
@ -34,12 +32,8 @@ impl PypiClient {
// Fetch from the registry.
let text = self.simple_impl(&package_name, &url).await?;
let payload = serde_json::from_str(&text)
.map_err(move |e| PypiClientError::from_json_err(e, String::new()));
trace!("fetched metadata for {} in {:?}", url, start.elapsed());
payload
serde_json::from_str(&text)
.map_err(move |e| PypiClientError::from_json_err(e, String::new()))
}
async fn simple_impl(
@ -69,8 +63,6 @@ impl PypiClient {
}
pub async fn file(&self, file: File) -> Result<Metadata21, PypiClientError> {
let start = std::time::Instant::now();
// Send to the proxy.
let url = self.proxy.join(
file.url
@ -82,11 +74,7 @@ impl PypiClient {
// Fetch from the registry.
let text = self.file_impl(&file.filename, &url).await?;
let payload = Metadata21::parse(text.as_bytes()).map_err(std::convert::Into::into);
trace!("fetched file {} in {:?}", url, start.elapsed());
payload
Metadata21::parse(text.as_bytes()).map_err(std::convert::Into::into)
}
async fn file_impl(

View file

@ -16,7 +16,8 @@ serde = { version = "1.0.188" }
thiserror = { version = "1.0.49" }
[dev-dependencies]
criterion = "0.5.1"
criterion = { version = "0.5.1" }
insta = { version = "1.33.0" }
[[bench]]
name = "parser"