Respect `UV_PYTHON_DOWNLOAD_MIRROR` in `uv python list`

This commit is contained in:
Zanie Blue 2025-12-10 09:34:49 -06:00
parent caac4814df
commit f41cb51574
5 changed files with 133 additions and 6 deletions

View File

@ -1458,7 +1458,7 @@ impl ManagedPythonDownload {
/// Return the [`Url`] to use when downloading the distribution. If a mirror is set via the /// Return the [`Url`] to use when downloading the distribution. If a mirror is set via the
/// appropriate environment variable, use it instead. /// appropriate environment variable, use it instead.
fn download_url( pub fn download_url(
&self, &self,
python_install_mirror: Option<&str>, python_install_mirror: Option<&str>,
pypy_install_mirror: Option<&str>, pypy_install_mirror: Option<&str>,

View File

@ -62,6 +62,8 @@ pub(crate) async fn list(
show_urls: bool, show_urls: bool,
output_format: PythonListFormat, output_format: PythonListFormat,
python_downloads_json_url: Option<String>, python_downloads_json_url: Option<String>,
python_install_mirror: Option<String>,
pypy_install_mirror: Option<String>,
python_preference: PythonPreference, python_preference: PythonPreference,
python_downloads: PythonDownloads, python_downloads: PythonDownloads,
client_builder: &BaseClientBuilder<'_>, client_builder: &BaseClientBuilder<'_>,
@ -121,7 +123,10 @@ pub(crate) async fn list(
output.insert(( output.insert((
download.key().clone(), download.key().clone(),
Kind::Download, Kind::Download,
Either::Right(download.url()), Either::Right(download.download_url(
python_install_mirror.as_deref(),
pypy_install_mirror.as_deref(),
)?),
)); ));
} }
} }

View File

@ -1585,6 +1585,8 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
args.show_urls, args.show_urls,
args.output_format, args.output_format,
args.python_downloads_json_url, args.python_downloads_json_url,
args.python_install_mirror,
args.pypy_install_mirror,
globals.python_preference, globals.python_preference,
globals.python_downloads, globals.python_downloads,
&client_builder.subcommand(vec!["python".to_owned(), "list".to_owned()]), &client_builder.subcommand(vec!["python".to_owned(), "list".to_owned()]),

View File

@ -995,6 +995,8 @@ pub(crate) struct PythonListSettings {
pub(crate) show_urls: bool, pub(crate) show_urls: bool,
pub(crate) output_format: PythonListFormat, pub(crate) output_format: PythonListFormat,
pub(crate) python_downloads_json_url: Option<String>, pub(crate) python_downloads_json_url: Option<String>,
pub(crate) python_install_mirror: Option<String>,
pub(crate) pypy_install_mirror: Option<String>,
} }
impl PythonListSettings { impl PythonListSettings {
@ -1018,15 +1020,38 @@ impl PythonListSettings {
} = args; } = args;
let options = filesystem.map(FilesystemOptions::into_options); let options = filesystem.map(FilesystemOptions::into_options);
let python_downloads_json_url_option = match options { let (
Some(options) => options.install_mirrors.python_downloads_json_url, python_downloads_json_url_option,
None => None, python_install_mirror_option,
pypy_install_mirror_option,
) = match &options {
Some(options) => (
options.install_mirrors.python_downloads_json_url.clone(),
options.install_mirrors.python_install_mirror.clone(),
options.install_mirrors.pypy_install_mirror.clone(),
),
None => (None, None, None),
}; };
let python_downloads_json_url = python_downloads_json_url_arg let python_downloads_json_url = python_downloads_json_url_arg
.or(environment.install_mirrors.python_downloads_json_url) .or(environment
.install_mirrors
.python_downloads_json_url
.clone())
.or(python_downloads_json_url_option); .or(python_downloads_json_url_option);
let python_install_mirror = environment
.install_mirrors
.python_install_mirror
.clone()
.or(python_install_mirror_option);
let pypy_install_mirror = environment
.install_mirrors
.pypy_install_mirror
.clone()
.or(pypy_install_mirror_option);
let kinds = if only_installed { let kinds = if only_installed {
PythonListKinds::Installed PythonListKinds::Installed
} else if only_downloads { } else if only_downloads {
@ -1044,6 +1069,8 @@ impl PythonListSettings {
show_urls, show_urls,
output_format, output_format,
python_downloads_json_url, python_downloads_json_url,
python_install_mirror,
pypy_install_mirror,
} }
} }
} }

View File

@ -591,3 +591,96 @@ async fn python_list_remote_python_downloads_json_url() -> Result<()> {
Ok(()) Ok(())
} }
#[test]
fn python_list_with_mirrors() {
let context: TestContext = TestContext::new_with_versions(&[])
.with_filtered_python_keys()
.with_collapsed_whitespace()
// Add filters to normalize file paths in URLs
.with_filter((
r"(https://mirror\.example\.com/).*".to_string(),
"$1[FILE-PATH]".to_string(),
))
.with_filter((
r"(https://python-mirror\.example\.com/).*".to_string(),
"$1[FILE-PATH]".to_string(),
))
.with_filter((
r"(https://pypy-mirror\.example\.com/).*".to_string(),
"$1[FILE-PATH]".to_string(),
))
.with_filter((
r"(https://github\.com/astral-sh/python-build-standalone/releases/download/).*"
.to_string(),
"$1[FILE-PATH]".to_string(),
))
.with_filter((
r"(https://downloads\.python\.org/pypy/).*".to_string(),
"$1[FILE-PATH]".to_string(),
))
.with_filter((
r"(https://github\.com/oracle/graalpython/releases/download/).*".to_string(),
"$1[FILE-PATH]".to_string(),
));
// Test with UV_PYTHON_INSTALL_MIRROR environment variable - verify mirror URL is used
uv_snapshot!(context.filters(), context.python_list()
.arg("cpython@3.10.19")
.arg("--show-urls")
.env(EnvVars::UV_PYTHON_INSTALL_MIRROR, "https://mirror.example.com")
.env_remove(EnvVars::UV_PYTHON_DOWNLOADS), @r"
success: true
exit_code: 0
----- stdout -----
cpython-3.10.19-[PLATFORM] https://mirror.example.com/[FILE-PATH]
----- stderr -----
");
// Test with UV_PYPY_INSTALL_MIRROR environment variable - verify PyPy mirror URL is used
uv_snapshot!(context.filters(), context.python_list()
.arg("pypy@3.10")
.arg("--show-urls")
.env(EnvVars::UV_PYPY_INSTALL_MIRROR, "https://pypy-mirror.example.com")
.env_remove(EnvVars::UV_PYTHON_DOWNLOADS), @r"
success: true
exit_code: 0
----- stdout -----
pypy-3.10.16-[PLATFORM] https://pypy-mirror.example.com/[FILE-PATH]
----- stderr -----
");
// Test with both mirror environment variables set
uv_snapshot!(context.filters(), context.python_list()
.arg("3.10")
.arg("--show-urls")
.env(EnvVars::UV_PYTHON_INSTALL_MIRROR, "https://python-mirror.example.com")
.env(EnvVars::UV_PYPY_INSTALL_MIRROR, "https://pypy-mirror.example.com")
.env_remove(EnvVars::UV_PYTHON_DOWNLOADS), @r"
success: true
exit_code: 0
----- stdout -----
cpython-3.10.19-[PLATFORM] https://python-mirror.example.com/[FILE-PATH]
pypy-3.10.16-[PLATFORM] https://pypy-mirror.example.com/[FILE-PATH]
graalpy-3.10.0-[PLATFORM] https://github.com/oracle/graalpython/releases/download/[FILE-PATH]
----- stderr -----
");
// Test without mirrors - verify default URLs are used
uv_snapshot!(context.filters(), context.python_list()
.arg("3.10")
.arg("--show-urls")
.env_remove(EnvVars::UV_PYTHON_DOWNLOADS), @r"
success: true
exit_code: 0
----- stdout -----
cpython-3.10.19-[PLATFORM] https://github.com/astral-sh/python-build-standalone/releases/download/[FILE-PATH]
pypy-3.10.16-[PLATFORM] https://downloads.python.org/pypy/[FILE-PATH]
graalpy-3.10.0-[PLATFORM] https://github.com/oracle/graalpython/releases/download/[FILE-PATH]
----- stderr -----
");
}