Conditionalize more tests that require PyPI (#13699)

<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
Use the existing `pypi` feature to conditionalize a number of tests that
attempt to access https://pypi.org and/or
https://files.pythonhosted.org. See
https://github.com/astral-sh/uv/issues/8970#issuecomment-2466794088.

There is no reason to believe that these are *all* of the tests that
need to be conditionalized on the `pypi` feature, but this should be a
solid step in the right direction.

## Test Plan

<!-- How was it tested? -->

This allows me to build and run the integration tests in [Fedora’s `uv`
package](https://src.fedoraproject.org/rpms/uv) without having to
manually skip tests that try to access PyPI. I confirmed that this
appears to accomplish that goal.

Otherwise, this should be tested by building and running the tests as
usual. As mentioned in
https://github.com/astral-sh/uv/issues/8970#issuecomment-2516181501, a
more complete solution would include CI tests that confirm these
features are working as intended. I’m not in a position to offer that.
This commit is contained in:
Ben Beasley 2025-06-02 03:57:03 -04:00 committed by GitHub
parent 1e890b5ac7
commit 73829f3bf4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 75 additions and 2 deletions

View file

@ -14,6 +14,7 @@ use crate::common::{TestContext, make_project, uv_snapshot};
/// ]
/// ```
#[test]
#[cfg(feature = "pypi")]
fn branching_urls_disjoint() -> Result<()> {
let context = TestContext::new("3.12");
@ -47,6 +48,7 @@ fn branching_urls_disjoint() -> Result<()> {
/// ]
/// ```
#[test]
#[cfg(feature = "pypi")]
fn branching_urls_overlapping() -> Result<()> {
let context = TestContext::new("3.12");
@ -83,6 +85,7 @@ fn branching_urls_overlapping() -> Result<()> {
/// a -> b -> b2 -> https://../iniconfig-2.0.0-py3-none-any.whl
/// ```
#[test]
#[cfg(feature = "pypi")]
fn root_package_splits_but_transitive_conflict() -> Result<()> {
let context = TestContext::new("3.12");
@ -151,6 +154,7 @@ fn root_package_splits_but_transitive_conflict() -> Result<()> {
/// a -> b -> b2 ; python_version >= '3.12' -> https://../iniconfig-2.0.0-py3-none-any.whl
/// ```
#[test]
#[cfg(feature = "pypi")]
fn root_package_splits_transitive_too() -> Result<()> {
let context = TestContext::new("3.12");
@ -356,6 +360,7 @@ fn root_package_splits_transitive_too() -> Result<()> {
/// a -> b2 ; python_version >= '3.12' -> iniconfig==2.0.0
/// ```
#[test]
#[cfg(feature = "pypi")]
fn root_package_splits_other_dependencies_too() -> Result<()> {
let context = TestContext::new("3.12");
@ -539,6 +544,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> {
/// ]
/// ```
#[test]
#[cfg(feature = "pypi")]
fn branching_between_registry_and_direct_url() -> Result<()> {
let context = TestContext::new("3.12");
@ -624,7 +630,7 @@ fn branching_between_registry_and_direct_url() -> Result<()> {
/// ]
/// ```
#[test]
#[cfg(feature = "git")]
#[cfg(all(feature = "git", feature = "pypi"))]
fn branching_urls_of_different_sources_disjoint() -> Result<()> {
let context = TestContext::new("3.12");
@ -708,7 +714,7 @@ fn branching_urls_of_different_sources_disjoint() -> Result<()> {
/// ]
/// ```
#[test]
#[cfg(feature = "git")]
#[cfg(all(feature = "git", feature = "pypi"))]
fn branching_urls_of_different_sources_conflict() -> Result<()> {
let context = TestContext::new("3.12");

View file

@ -24,6 +24,7 @@ const BUILT_BY_UV_TEST_SCRIPT: &str = indoc! {r#"
///
/// We can't test end-to-end here including the PEP 517 bridge code since we don't have a uv wheel.
#[test]
#[cfg(feature = "pypi")]
fn built_by_uv_direct_wheel() -> Result<()> {
let context = TestContext::new("3.12");
let built_by_uv = Path::new("../../scripts/packages/built-by-uv");
@ -83,6 +84,7 @@ fn built_by_uv_direct_wheel() -> Result<()> {
/// We can't test end-to-end here including the PEP 517 bridge code since we don't have a uv wheel,
/// so we call the build backend directly.
#[test]
#[cfg(feature = "pypi")]
fn built_by_uv_direct() -> Result<()> {
let context = TestContext::new("3.12");
let built_by_uv = Path::new("../../scripts/packages/built-by-uv");
@ -160,6 +162,7 @@ fn built_by_uv_direct() -> Result<()> {
/// We can't test end-to-end here including the PEP 517 bridge code since we don't have a uv wheel,
/// so we call the build backend directly.
#[test]
#[cfg(feature = "pypi")]
fn built_by_uv_editable() -> Result<()> {
let context = TestContext::new("3.12");
let built_by_uv = Path::new("../../scripts/packages/built-by-uv");

View file

@ -41,6 +41,7 @@ mod lock_scenarios;
mod version;
#[cfg(all(feature = "python", feature = "pypi"))]
mod pip_check;
#[cfg(all(feature = "python", feature = "pypi"))]

View file

@ -56,6 +56,7 @@ fn list_empty_json() {
}
#[test]
#[cfg(feature = "pypi")]
fn list_single_no_editable() -> Result<()> {
let context = TestContext::new("3.12");
@ -96,6 +97,7 @@ fn list_single_no_editable() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn list_outdated_columns() -> Result<()> {
let context = TestContext::new("3.12");
@ -136,6 +138,7 @@ fn list_outdated_columns() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn list_outdated_json() -> Result<()> {
let context = TestContext::new("3.12");
@ -232,6 +235,7 @@ fn list_outdated_git() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn list_outdated_index() -> Result<()> {
let context = TestContext::new("3.12");
@ -275,6 +279,7 @@ fn list_outdated_index() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn list_editable() {
let context = TestContext::new("3.12");
@ -320,6 +325,7 @@ fn list_editable() {
}
#[test]
#[cfg(feature = "pypi")]
fn list_editable_only() {
let context = TestContext::new("3.12");
@ -394,6 +400,7 @@ fn list_editable_only() {
}
#[test]
#[cfg(feature = "pypi")]
fn list_exclude() {
let context = TestContext::new("3.12");
@ -475,6 +482,7 @@ fn list_exclude() {
}
#[test]
#[cfg(feature = "pypi")]
#[cfg(not(windows))]
fn list_format_json() {
let context = TestContext::new("3.12");
@ -541,6 +549,7 @@ fn list_format_json() {
}
#[test]
#[cfg(feature = "pypi")]
fn list_format_freeze() {
let context = TestContext::new("3.12");
@ -706,6 +715,7 @@ Version: 0.1-bulbasaur
}
#[test]
#[cfg(feature = "pypi")]
fn list_ignores_quiet_flag_format_freeze() {
let context = TestContext::new("3.12");

View file

@ -26,6 +26,7 @@ fn show_empty() {
}
#[test]
#[cfg(feature = "pypi")]
fn show_requires_multiple() -> Result<()> {
let context = TestContext::new("3.12");
@ -75,6 +76,7 @@ fn show_requires_multiple() -> Result<()> {
/// Asserts that the Python version marker in the metadata is correctly evaluated.
/// `click` v8.1.7 requires `importlib-metadata`, but only when `python_version < "3.8"`.
#[test]
#[cfg(feature = "pypi")]
fn show_python_version_marker() -> Result<()> {
let context = TestContext::new("3.12");
@ -124,6 +126,7 @@ fn show_python_version_marker() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_found_single_package() -> Result<()> {
let context = TestContext::new("3.12");
@ -168,6 +171,7 @@ fn show_found_single_package() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_found_multiple_packages() -> Result<()> {
let context = TestContext::new("3.12");
@ -224,6 +228,7 @@ fn show_found_multiple_packages() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_found_one_out_of_three() -> Result<()> {
let context = TestContext::new("3.12");
@ -276,6 +281,7 @@ fn show_found_one_out_of_three() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_found_one_out_of_two_quiet() -> Result<()> {
let context = TestContext::new("3.12");
@ -323,6 +329,7 @@ fn show_found_one_out_of_two_quiet() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_empty_quiet() -> Result<()> {
let context = TestContext::new("3.12");
@ -369,6 +376,7 @@ fn show_empty_quiet() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_editable() -> Result<()> {
let context = TestContext::new("3.12");
@ -405,6 +413,7 @@ fn show_editable() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_required_by_multiple() -> Result<()> {
let context = TestContext::new("3.12");
@ -460,6 +469,7 @@ fn show_required_by_multiple() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn show_files() {
let context = TestContext::new("3.12");

View file

@ -26,6 +26,7 @@ fn no_package() {
}
#[test]
#[cfg(feature = "pypi")]
fn prune_last_in_the_subgroup() {
let context = TestContext::new("3.12");
@ -69,6 +70,7 @@ fn prune_last_in_the_subgroup() {
}
#[test]
#[cfg(feature = "pypi")]
fn single_package() {
let context = TestContext::new("3.12");
@ -114,6 +116,7 @@ fn single_package() {
}
#[test]
#[cfg(feature = "pypi")]
fn nested_dependencies() {
let context = TestContext::new("3.12");
@ -163,6 +166,7 @@ fn nested_dependencies() {
/// Identical test as `invert` since `--reverse` is simply an alias for `--invert`.
#[test]
#[cfg(feature = "pypi")]
fn reverse() {
let context = TestContext::new("3.12");
@ -214,6 +218,7 @@ fn reverse() {
}
#[test]
#[cfg(feature = "pypi")]
fn invert() {
let context = TestContext::new("3.12");
@ -265,6 +270,7 @@ fn invert() {
}
#[test]
#[cfg(feature = "pypi")]
fn depth() {
let context = TestContext::new("3.12");
@ -364,6 +370,7 @@ fn depth() {
}
#[test]
#[cfg(feature = "pypi")]
fn prune() {
let context = TestContext::new("3.12");
@ -468,6 +475,7 @@ fn prune() {
/// Ensure `pip tree` behaves correctly after a package has been removed.
#[test]
#[cfg(feature = "pypi")]
fn removed_dependency() {
let context = TestContext::new("3.12");
@ -523,6 +531,7 @@ fn removed_dependency() {
}
#[test]
#[cfg(feature = "pypi")]
fn multiple_packages() {
let context = TestContext::new("3.12");
@ -577,6 +586,7 @@ fn multiple_packages() {
/// Show the installed tree in the presence of a cycle.
#[test]
#[cfg(feature = "pypi")]
fn cycle() {
let context = TestContext::new("3.12");
@ -644,6 +654,7 @@ fn cycle() {
/// Both `pendulum` and `boto3` depend on `python-dateutil`.
#[test]
#[cfg(feature = "pypi")]
fn multiple_packages_shared_descendant() {
let context = TestContext::new("3.12");
@ -697,6 +708,7 @@ fn multiple_packages_shared_descendant() {
/// Test the interaction between `--no-dedupe` and `--invert`.
#[test]
#[cfg(feature = "pypi")]
fn no_dedupe_and_invert() {
let context = TestContext::new("3.12");
@ -749,6 +761,7 @@ fn no_dedupe_and_invert() {
}
#[test]
#[cfg(feature = "pypi")]
fn no_dedupe() {
let context = TestContext::new("3.12");
@ -843,6 +856,7 @@ fn with_editable() {
}
#[test]
#[cfg(feature = "pypi")]
fn package_flag() {
let context = TestContext::new("3.12");
@ -910,6 +924,7 @@ fn package_flag() {
}
#[test]
#[cfg(feature = "pypi")]
fn show_version_specifiers_simple() {
let context = TestContext::new("3.12");
@ -953,6 +968,7 @@ fn show_version_specifiers_simple() {
}
#[test]
#[cfg(feature = "pypi")]
fn show_version_specifiers_with_invert() {
let context = TestContext::new("3.12");
@ -1008,6 +1024,7 @@ fn show_version_specifiers_with_invert() {
}
#[test]
#[cfg(feature = "pypi")]
fn show_version_specifiers_with_package() {
let context = TestContext::new("3.12");
@ -1055,6 +1072,7 @@ fn show_version_specifiers_with_package() {
}
#[test]
#[cfg(feature = "pypi")]
fn print_output_even_with_quite_flag() {
let context = TestContext::new("3.12");
@ -1094,6 +1112,7 @@ fn print_output_even_with_quite_flag() {
}
#[test]
#[cfg(feature = "pypi")]
fn outdated() {
let context = TestContext::new("3.12");

View file

@ -100,6 +100,7 @@ fn invalid_requirements_txt_requirement() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn uninstall() -> Result<()> {
let context = TestContext::new("3.12");
@ -142,6 +143,7 @@ fn uninstall() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn missing_record() -> Result<()> {
let context = TestContext::new("3.12");
@ -180,6 +182,7 @@ fn missing_record() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn uninstall_editable_by_name() -> Result<()> {
let context = TestContext::new("3.12");
@ -228,6 +231,7 @@ fn uninstall_editable_by_name() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn uninstall_by_path() -> Result<()> {
let context = TestContext::new("3.12");
@ -276,6 +280,7 @@ fn uninstall_by_path() -> Result<()> {
}
#[test]
#[cfg(feature = "pypi")]
fn uninstall_duplicate_by_path() -> Result<()> {
let context = TestContext::new("3.12");
@ -326,6 +331,7 @@ fn uninstall_duplicate_by_path() -> Result<()> {
/// Uninstall a duplicate package in a virtual environment.
#[test]
#[cfg(feature = "pypi")]
fn uninstall_duplicate() -> Result<()> {
use uv_fs::copy_dir_all;

View file

@ -579,6 +579,7 @@ fn create_venv_explicit_request_takes_priority_over_python_version_file() {
}
#[test]
#[cfg(feature = "pypi")]
fn seed() {
let context = TestContext::new_with_versions(&["3.12"]);
uv_snapshot!(context.filters(), context.venv()
@ -602,6 +603,7 @@ fn seed() {
}
#[test]
#[cfg(feature = "pypi")]
fn seed_older_python_version() {
let context = TestContext::new_with_versions(&["3.11"]);
uv_snapshot!(context.filters(), context.venv()

View file

@ -1368,6 +1368,7 @@ fn version_get_workspace() -> Result<()> {
///
/// Also check that --locked/--frozen/--no-sync do what they say
#[test]
#[cfg(feature = "pypi")]
fn version_set_workspace() -> Result<()> {
let context = TestContext::new("3.12");
@ -1709,6 +1710,7 @@ fn version_set_workspace() -> Result<()> {
/// It would be nice to have a case where we still get a package dependency, but
/// this still demonstrates the non-trivial "hazard" of a version change.
#[test]
#[cfg(feature = "pypi")]
fn version_set_evil_constraints() -> Result<()> {
let context = TestContext::new("3.12");

View file

@ -24,6 +24,7 @@ fn workspaces_dir() -> PathBuf {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_in_examples_bird_feeder() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -67,6 +68,7 @@ fn test_albatross_in_examples_bird_feeder() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_in_examples() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -107,6 +109,7 @@ fn test_albatross_in_examples() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_just_project() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -147,6 +150,7 @@ fn test_albatross_just_project() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_project_in_excluded() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -222,6 +226,7 @@ fn test_albatross_project_in_excluded() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_root_workspace() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -265,6 +270,7 @@ fn test_albatross_root_workspace() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_root_workspace_bird_feeder() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -310,6 +316,7 @@ fn test_albatross_root_workspace_bird_feeder() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_root_workspace_albatross() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -355,6 +362,7 @@ fn test_albatross_root_workspace_albatross() {
}
#[test]
#[cfg(feature = "pypi")]
fn test_albatross_virtual_workspace() {
let context = TestContext::new("3.12");
let workspace = context.temp_dir.child("workspace");
@ -402,6 +410,7 @@ fn test_albatross_virtual_workspace() {
/// Check that `uv run --package` works in a virtual workspace.
#[test]
#[cfg(feature = "pypi")]
fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
let context = TestContext::new("3.12");
let work_dir = context.temp_dir.join("albatross-virtual-workspace");
@ -471,6 +480,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
/// Check that `uv run` works from a virtual workspace root, which should sync all packages in the
/// workspace.
#[test]
#[cfg(feature = "pypi")]
fn test_uv_run_virtual_workspace_root() -> Result<()> {
let context = TestContext::new("3.12");
let work_dir = context.temp_dir.join("albatross-virtual-workspace");
@ -511,6 +521,7 @@ fn test_uv_run_virtual_workspace_root() -> Result<()> {
/// Check that `uv run --package` works in a root workspace.
#[test]
#[cfg(feature = "pypi")]
fn test_uv_run_with_package_root_workspace() -> Result<()> {
let context = TestContext::new("3.12");
let work_dir = context.temp_dir.join("albatross-root-workspace");
@ -573,6 +584,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
/// Check that `uv run --isolated` creates isolated virtual environments.
#[test]
#[cfg(feature = "pypi")]
fn test_uv_run_isolate() -> Result<()> {
let context = TestContext::new("3.12");
let work_dir = context.temp_dir.join("albatross-root-workspace");
@ -694,6 +706,7 @@ fn workspace_lock_idempotence(workspace: &str, subdirectories: &[&str]) -> Resul
/// Check that the resolution is the same no matter where in the workspace we are.
#[test]
#[cfg(feature = "pypi")]
fn workspace_lock_idempotence_root_workspace() -> Result<()> {
workspace_lock_idempotence(
"albatross-root-workspace",
@ -705,6 +718,7 @@ fn workspace_lock_idempotence_root_workspace() -> Result<()> {
/// Check that the resolution is the same no matter where in the workspace we are, and that locking
/// works even if there is no root project.
#[test]
#[cfg(feature = "pypi")]
fn workspace_lock_idempotence_virtual_workspace() -> Result<()> {
workspace_lock_idempotence(
"albatross-virtual-workspace",