Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/uv-python/src/downloads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,7 @@ impl ManagedPythonDownload {

/// Return the [`Url`] to use when downloading the distribution. If a mirror is set via the
/// appropriate environment variable, use it instead.
fn download_url(
pub fn download_url(
&self,
python_install_mirror: Option<&str>,
pypy_install_mirror: Option<&str>,
Expand Down
7 changes: 6 additions & 1 deletion crates/uv/src/commands/python/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub(crate) async fn list(
show_urls: bool,
output_format: PythonListFormat,
python_downloads_json_url: Option<String>,
python_install_mirror: Option<String>,
pypy_install_mirror: Option<String>,
python_preference: PythonPreference,
python_downloads: PythonDownloads,
cache: &Cache,
Expand Down Expand Up @@ -117,7 +119,10 @@ pub(crate) async fn list(
output.insert((
download.key().clone(),
Kind::Download,
Either::Right(download.url()),
Either::Right(download.download_url(
python_install_mirror.as_deref(),
pypy_install_mirror.as_deref(),
)?),
));
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,8 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
args.show_urls,
args.output_format,
args.python_downloads_json_url,
args.python_install_mirror,
args.pypy_install_mirror,
globals.python_preference,
globals.python_downloads,
&cache,
Expand Down
35 changes: 31 additions & 4 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,8 @@ pub(crate) struct PythonListSettings {
pub(crate) show_urls: bool,
pub(crate) output_format: PythonListFormat,
pub(crate) python_downloads_json_url: Option<String>,
pub(crate) python_install_mirror: Option<String>,
pub(crate) pypy_install_mirror: Option<String>,
}

impl PythonListSettings {
Expand All @@ -1008,15 +1010,38 @@ impl PythonListSettings {
} = args;

let options = filesystem.map(FilesystemOptions::into_options);
let python_downloads_json_url_option = match options {
Some(options) => options.install_mirrors.python_downloads_json_url,
None => None,
let (
python_downloads_json_url_option,
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
.or(environment.install_mirrors.python_downloads_json_url)
.or(environment
.install_mirrors
.python_downloads_json_url
.clone())
.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 {
PythonListKinds::Installed
} else if only_downloads {
Expand All @@ -1034,6 +1059,8 @@ impl PythonListSettings {
show_urls,
output_format,
python_downloads_json_url,
python_install_mirror,
pypy_install_mirror,
}
}
}
Expand Down
93 changes: 93 additions & 0 deletions crates/uv/tests/it/python_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,3 +479,96 @@ fn python_list_downloads_installed() {
----- stderr -----
");
}

#[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("[email protected]")
.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("[email protected]")
.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 -----
");
}
Loading