diff --git a/crates/uv/tests/it/common/mod.rs b/crates/uv/tests/it/common/mod.rs index 13e1b20c6d6f7..4fa0c43f525aa 100644 --- a/crates/uv/tests/it/common/mod.rs +++ b/crates/uv/tests/it/common/mod.rs @@ -205,10 +205,10 @@ impl TestContext { self.filters .push(("python.exe".to_string(), "python".to_string())); } else { - self.filters - .push((r"python\d".to_string(), "python".to_string())); self.filters .push((r"python\d.\d\d".to_string(), "python".to_string())); + self.filters + .push((r"python\d".to_string(), "python".to_string())); } self } @@ -224,6 +224,25 @@ impl TestContext { self } + /// Add extra standard filtering for Python installation `bin/` directories, which are not + /// present on Windows but are on Unix. See [`TestContext::with_filtered_virtualenv_bin`] for + /// the virtual environment equivalent. + #[must_use] + pub fn with_filtered_python_install_bin(mut self) -> Self { + if cfg!(unix) { + self.filters.push(( + r"[\\/]bin/python".to_string(), + "/[INSTALL-BIN]/python".to_string(), + )); + } else { + self.filters.push(( + r"[\\/]python".to_string(), + "/[INSTALL-BIN]/python".to_string(), + )); + } + self + } + /// Add extra filtering for ` -> ` symlink display for Python versions in the test /// context, e.g., for use in `uv python list`. #[must_use] diff --git a/crates/uv/tests/it/python_list.rs b/crates/uv/tests/it/python_list.rs index 65766786153ce..6206cfca2e0fc 100644 --- a/crates/uv/tests/it/python_list.rs +++ b/crates/uv/tests/it/python_list.rs @@ -352,3 +352,123 @@ fn python_list_duplicate_path_entries() { "); } } + +#[test] +fn python_list_downloads() { + let context: TestContext = TestContext::new_with_versions(&[]).with_filtered_python_keys(); + + // We do not test showing all interpreters — as it differs per platform + // Instead, we choose a Python version where our available distributions are stable + + // Test the default display, which requires reverting the test context disabling Python downloads + uv_snapshot!(context.filters(), context.python_list().arg("3.10").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.10.17-[PLATFORM] + pypy-3.10.16-[PLATFORM] + + ----- stderr ----- + "); + + // Show patch versions + uv_snapshot!(context.filters(), context.python_list().arg("3.10").arg("--all-versions").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.10.17-[PLATFORM] + cpython-3.10.16-[PLATFORM] + cpython-3.10.15-[PLATFORM] + cpython-3.10.14-[PLATFORM] + cpython-3.10.13-[PLATFORM] + cpython-3.10.12-[PLATFORM] + cpython-3.10.11-[PLATFORM] + cpython-3.10.9-[PLATFORM] + cpython-3.10.8-[PLATFORM] + cpython-3.10.7-[PLATFORM] + cpython-3.10.6-[PLATFORM] + cpython-3.10.5-[PLATFORM] + cpython-3.10.4-[PLATFORM] + cpython-3.10.3-[PLATFORM] + cpython-3.10.2-[PLATFORM] + cpython-3.10.0-[PLATFORM] + pypy-3.10.16-[PLATFORM] + pypy-3.10.14-[PLATFORM] + pypy-3.10.13-[PLATFORM] + pypy-3.10.12-[PLATFORM] + + ----- stderr ----- + "); +} + +#[test] +#[cfg(feature = "python-managed")] +fn python_list_downloads_installed() { + use assert_cmd::assert::OutputAssertExt; + + let context: TestContext = TestContext::new_with_versions(&[]) + .with_filtered_python_keys() + .with_filtered_python_names() + .with_filtered_python_install_bin() + .with_managed_python_dirs(); + + // We do not test showing all interpreters — as it differs per platform + // Instead, we choose a Python version where our available distributions are stable + + // First, the download is shown as available + uv_snapshot!(context.filters(), context.python_list().arg("3.10").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.10.17-[PLATFORM] + pypy-3.10.16-[PLATFORM] + + ----- stderr ----- + "); + + // TODO(zanieb): It'd be nice to test `--show-urls` here too but we need special filtering for + // the URL + + // But not if `--only-installed` is used + uv_snapshot!(context.filters(), context.python_list().arg("3.10").arg("--only-installed").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + "); + + // Install a Python version + context.python_install().arg("3.10").assert().success(); + + // Then, it should be listed as installed instead of available + uv_snapshot!(context.filters(), context.python_list().arg("3.10").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.10.17-[PLATFORM] managed/cpython-3.10.17-[PLATFORM]/[INSTALL-BIN]/python + pypy-3.10.16-[PLATFORM] + + ----- stderr ----- + "); + + // But, the display should be reverted if `--only-downloads` is used + uv_snapshot!(context.filters(), context.python_list().arg("3.10").arg("--only-downloads").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.10.17-[PLATFORM] + pypy-3.10.16-[PLATFORM] + + ----- stderr ----- + "); + + // And should not be shown if `--no-managed-python` is used + uv_snapshot!(context.filters(), context.python_list().arg("3.10").arg("--no-managed-python").env_remove("UV_PYTHON_DOWNLOADS"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + "); +}