mirror of https://github.com/astral-sh/uv
Cache Python downloads by default
i.e., without requiring opt-in vi `UV_PYTHON_CACHE_DIR`
This commit is contained in:
parent
caac4814df
commit
6d69bda50b
|
|
@ -21,6 +21,7 @@ use tokio_util::either::Either;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use uv_cache::{Cache, CacheBucket};
|
||||||
use uv_client::{BaseClient, WrappedReqwestError, is_transient_network_error};
|
use uv_client::{BaseClient, WrappedReqwestError, is_transient_network_error};
|
||||||
use uv_distribution_filename::{ExtensionError, SourceDistExtension};
|
use uv_distribution_filename::{ExtensionError, SourceDistExtension};
|
||||||
use uv_extract::hash::Hasher;
|
use uv_extract::hash::Hasher;
|
||||||
|
|
@ -1099,13 +1100,14 @@ impl ManagedPythonDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download and extract a Python distribution, retrying on failure.
|
/// Download and extract a Python distribution, retrying on failure.
|
||||||
#[instrument(skip(client, installation_dir, scratch_dir, reporter), fields(download = % self.key()))]
|
#[instrument(skip(client, installation_dir, scratch_dir, cache, reporter), fields(download = % self.key()))]
|
||||||
pub async fn fetch_with_retry(
|
pub async fn fetch_with_retry(
|
||||||
&self,
|
&self,
|
||||||
client: &BaseClient,
|
client: &BaseClient,
|
||||||
retry_policy: &ExponentialBackoff,
|
retry_policy: &ExponentialBackoff,
|
||||||
installation_dir: &Path,
|
installation_dir: &Path,
|
||||||
scratch_dir: &Path,
|
scratch_dir: &Path,
|
||||||
|
cache: &Cache,
|
||||||
reinstall: bool,
|
reinstall: bool,
|
||||||
python_install_mirror: Option<&str>,
|
python_install_mirror: Option<&str>,
|
||||||
pypy_install_mirror: Option<&str>,
|
pypy_install_mirror: Option<&str>,
|
||||||
|
|
@ -1120,6 +1122,7 @@ impl ManagedPythonDownload {
|
||||||
client,
|
client,
|
||||||
installation_dir,
|
installation_dir,
|
||||||
scratch_dir,
|
scratch_dir,
|
||||||
|
cache,
|
||||||
reinstall,
|
reinstall,
|
||||||
python_install_mirror,
|
python_install_mirror,
|
||||||
pypy_install_mirror,
|
pypy_install_mirror,
|
||||||
|
|
@ -1167,12 +1170,13 @@ impl ManagedPythonDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download and extract a Python distribution.
|
/// Download and extract a Python distribution.
|
||||||
#[instrument(skip(client, installation_dir, scratch_dir, reporter), fields(download = % self.key()))]
|
#[instrument(skip(client, installation_dir, scratch_dir, cache, reporter), fields(download = % self.key()))]
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
&self,
|
&self,
|
||||||
client: &BaseClient,
|
client: &BaseClient,
|
||||||
installation_dir: &Path,
|
installation_dir: &Path,
|
||||||
scratch_dir: &Path,
|
scratch_dir: &Path,
|
||||||
|
cache: &Cache,
|
||||||
reinstall: bool,
|
reinstall: bool,
|
||||||
python_install_mirror: Option<&str>,
|
python_install_mirror: Option<&str>,
|
||||||
pypy_install_mirror: Option<&str>,
|
pypy_install_mirror: Option<&str>,
|
||||||
|
|
@ -1205,10 +1209,13 @@ impl ManagedPythonDownload {
|
||||||
|
|
||||||
let temp_dir = tempfile::tempdir_in(scratch_dir).map_err(Error::DownloadDirError)?;
|
let temp_dir = tempfile::tempdir_in(scratch_dir).map_err(Error::DownloadDirError)?;
|
||||||
|
|
||||||
if let Some(python_builds_dir) =
|
// Use the cache directory from the environment variable if set, otherwise use the default
|
||||||
env::var_os(EnvVars::UV_PYTHON_CACHE_DIR).filter(|s| !s.is_empty())
|
// cache bucket.
|
||||||
{
|
let python_builds_dir = env::var_os(EnvVars::UV_PYTHON_CACHE_DIR)
|
||||||
let python_builds_dir = PathBuf::from(python_builds_dir);
|
.filter(|s| !s.is_empty())
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.unwrap_or_else(|| cache.bucket(CacheBucket::Python));
|
||||||
|
|
||||||
fs_err::create_dir_all(&python_builds_dir)?;
|
fs_err::create_dir_all(&python_builds_dir)?;
|
||||||
let hash_prefix = match self.sha256.as_deref() {
|
let hash_prefix = match self.sha256.as_deref() {
|
||||||
Some(sha) => {
|
Some(sha) => {
|
||||||
|
|
@ -1272,26 +1279,6 @@ impl ManagedPythonDownload {
|
||||||
Direction::Extract,
|
Direction::Extract,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
|
||||||
// Avoid overlong log lines
|
|
||||||
debug!("Downloading {url}");
|
|
||||||
debug!(
|
|
||||||
"Extracting {filename} to temporary location: {}",
|
|
||||||
temp_dir.path().simplified_display()
|
|
||||||
);
|
|
||||||
|
|
||||||
let (reader, size) = read_url(&url, client).await?;
|
|
||||||
self.extract_reader(
|
|
||||||
reader,
|
|
||||||
temp_dir.path(),
|
|
||||||
&filename,
|
|
||||||
ext,
|
|
||||||
size,
|
|
||||||
reporter,
|
|
||||||
Direction::Download,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the top-level directory.
|
// Extract the top-level directory.
|
||||||
let mut extracted = match uv_extract::strip_component(temp_dir.path()) {
|
let mut extracted = match uv_extract::strip_component(temp_dir.path()) {
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,7 @@ impl PythonInstallation {
|
||||||
retry_policy,
|
retry_policy,
|
||||||
installations_dir,
|
installations_dir,
|
||||||
&scratch_dir,
|
&scratch_dir,
|
||||||
|
cache,
|
||||||
false,
|
false,
|
||||||
python_install_mirror,
|
python_install_mirror,
|
||||||
pypy_install_mirror,
|
pypy_install_mirror,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use owo_colors::{AnsiColors, OwoColorize};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
|
use uv_cache::Cache;
|
||||||
use uv_client::BaseClientBuilder;
|
use uv_client::BaseClientBuilder;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_platform::{Arch, Libc};
|
use uv_platform::{Arch, Libc};
|
||||||
|
|
@ -188,6 +189,7 @@ pub(crate) async fn install(
|
||||||
pypy_install_mirror: Option<String>,
|
pypy_install_mirror: Option<String>,
|
||||||
python_downloads_json_url: Option<String>,
|
python_downloads_json_url: Option<String>,
|
||||||
client_builder: BaseClientBuilder<'_>,
|
client_builder: BaseClientBuilder<'_>,
|
||||||
|
cache: &Cache,
|
||||||
default: bool,
|
default: bool,
|
||||||
python_downloads: PythonDownloads,
|
python_downloads: PythonDownloads,
|
||||||
no_config: bool,
|
no_config: bool,
|
||||||
|
|
@ -470,6 +472,7 @@ pub(crate) async fn install(
|
||||||
&retry_policy,
|
&retry_policy,
|
||||||
installations_dir,
|
installations_dir,
|
||||||
&scratch_dir,
|
&scratch_dir,
|
||||||
|
cache,
|
||||||
reinstall,
|
reinstall,
|
||||||
python_install_mirror.as_deref(),
|
python_install_mirror.as_deref(),
|
||||||
pypy_install_mirror.as_deref(),
|
pypy_install_mirror.as_deref(),
|
||||||
|
|
|
||||||
|
|
@ -1601,6 +1601,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
let args = settings::PythonInstallSettings::resolve(args, filesystem, environment);
|
let args = settings::PythonInstallSettings::resolve(args, filesystem, environment);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
|
||||||
|
let cache = cache.init().await?;
|
||||||
commands::python_install(
|
commands::python_install(
|
||||||
&project_dir,
|
&project_dir,
|
||||||
args.install_dir,
|
args.install_dir,
|
||||||
|
|
@ -1614,6 +1615,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
args.pypy_install_mirror,
|
args.pypy_install_mirror,
|
||||||
args.python_downloads_json_url,
|
args.python_downloads_json_url,
|
||||||
client_builder.subcommand(vec!["python".to_owned(), "install".to_owned()]),
|
client_builder.subcommand(vec!["python".to_owned(), "install".to_owned()]),
|
||||||
|
&cache,
|
||||||
args.default,
|
args.default,
|
||||||
globals.python_downloads,
|
globals.python_downloads,
|
||||||
cli.top_level.no_config,
|
cli.top_level.no_config,
|
||||||
|
|
@ -1630,6 +1632,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
let upgrade = commands::PythonUpgrade::Enabled(commands::PythonUpgradeSource::Upgrade);
|
let upgrade = commands::PythonUpgrade::Enabled(commands::PythonUpgradeSource::Upgrade);
|
||||||
|
|
||||||
|
let cache = cache.init().await?;
|
||||||
commands::python_install(
|
commands::python_install(
|
||||||
&project_dir,
|
&project_dir,
|
||||||
args.install_dir,
|
args.install_dir,
|
||||||
|
|
@ -1643,6 +1646,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
args.pypy_install_mirror,
|
args.pypy_install_mirror,
|
||||||
args.python_downloads_json_url,
|
args.python_downloads_json_url,
|
||||||
client_builder.subcommand(vec!["python".to_owned(), "upgrade".to_owned()]),
|
client_builder.subcommand(vec!["python".to_owned(), "upgrade".to_owned()]),
|
||||||
|
&cache,
|
||||||
args.default,
|
args.default,
|
||||||
globals.python_downloads,
|
globals.python_downloads,
|
||||||
cli.top_level.no_config,
|
cli.top_level.no_config,
|
||||||
|
|
|
||||||
|
|
@ -2712,10 +2712,10 @@ fn python_install_no_cache() {
|
||||||
- cpython-3.14.2-[PLATFORM] (python3.14)
|
- cpython-3.14.2-[PLATFORM] (python3.14)
|
||||||
");
|
");
|
||||||
|
|
||||||
// 3.12 isn't cached, so it can't be installed
|
// 3.12 isn't cached, so it can't be installed offline
|
||||||
let mut filters = context.filters();
|
let mut filters = context.filters();
|
||||||
filters.push((
|
filters.push((
|
||||||
"cpython-3.12.*.tar.gz",
|
r"cpython-3\.12\.\d+(%2B|\+)\d+-[a-z0-9_-]+\.tar\.gz",
|
||||||
"cpython-3.12.[PATCH]-[DATE]-[PLATFORM].tar.gz",
|
"cpython-3.12.[PATCH]-[DATE]-[PLATFORM].tar.gz",
|
||||||
));
|
));
|
||||||
filters.push((r"releases/download/\d{8}/", "releases/download/[DATE]/"));
|
filters.push((r"releases/download/\d{8}/", "releases/download/[DATE]/"));
|
||||||
|
|
@ -2729,8 +2729,7 @@ fn python_install_no_cache() {
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: Failed to install cpython-3.12.12-[PLATFORM]
|
error: Failed to install cpython-3.12.12-[PLATFORM]
|
||||||
Caused by: Failed to download https://github.com/astral-sh/python-build-standalone/releases/download/[DATE]/cpython-3.12.[PATCH]-[DATE]-[PLATFORM].tar.gz
|
Caused by: An offline Python installation was requested, but cpython-3.12.12-[PLATFORM] (from https://github.com/astral-sh/python-build-standalone/releases/download/[DATE]/cpython-3.12.[PATCH]-[DATE]-[PLATFORM].tar.gz) is missing in [CACHE_DIR]/python-v0
|
||||||
Caused by: Network connectivity is disabled, but the requested data wasn't found in the cache for: `https://github.com/astral-sh/python-build-standalone/releases/download/[DATE]/cpython-3.12.[PATCH]-[DATE]-[PLATFORM].tar.gz`
|
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue