mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Add test coverage for build tag prioritization (#9680)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
## Summary See: https://github.com/astral-sh/uv/pull/3781 and https://github.com/astral-sh/uv/pull/9677.
This commit is contained in:
parent
b5022efef9
commit
3aaa9594be
10 changed files with 205 additions and 18 deletions
|
@ -34,10 +34,18 @@ pub enum FindLinksDirectoryError {
|
|||
VerbatimUrl(#[from] uv_pep508::VerbatimUrlError),
|
||||
}
|
||||
|
||||
/// An entry in a `--find-links` index.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FlatIndexEntry {
|
||||
pub filename: DistFilename,
|
||||
pub file: File,
|
||||
pub index: IndexUrl,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct FlatIndexEntries {
|
||||
/// The list of `--find-links` entries.
|
||||
pub entries: Vec<(DistFilename, File, IndexUrl)>,
|
||||
pub entries: Vec<FlatIndexEntry>,
|
||||
/// Whether any `--find-links` entries could not be resolved due to a lack of network
|
||||
/// connectivity.
|
||||
pub offline: bool,
|
||||
|
@ -45,7 +53,7 @@ pub struct FlatIndexEntries {
|
|||
|
||||
impl FlatIndexEntries {
|
||||
/// Create a [`FlatIndexEntries`] from a list of `--find-links` entries.
|
||||
fn from_entries(entries: Vec<(DistFilename, File, IndexUrl)>) -> Self {
|
||||
fn from_entries(entries: Vec<FlatIndexEntry>) -> Self {
|
||||
Self {
|
||||
entries,
|
||||
offline: false,
|
||||
|
@ -130,6 +138,9 @@ impl<'a> FlatIndexClient<'a> {
|
|||
while let Some(entries) = fetches.next().await.transpose()? {
|
||||
results.extend(entries);
|
||||
}
|
||||
results
|
||||
.entries
|
||||
.sort_by(|a, b| a.filename.cmp(&b.filename).then(a.index.cmp(&b.index)));
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
|
@ -211,11 +222,11 @@ impl<'a> FlatIndexClient<'a> {
|
|||
.expect("archived version always deserializes")
|
||||
})
|
||||
.filter_map(|file| {
|
||||
Some((
|
||||
DistFilename::try_from_normalized_filename(&file.filename)?,
|
||||
Some(FlatIndexEntry {
|
||||
filename: DistFilename::try_from_normalized_filename(&file.filename)?,
|
||||
file,
|
||||
flat_index.clone(),
|
||||
))
|
||||
index: flat_index.clone(),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(FlatIndexEntries::from_entries(files))
|
||||
|
@ -283,7 +294,11 @@ impl<'a> FlatIndexClient<'a> {
|
|||
);
|
||||
continue;
|
||||
};
|
||||
dists.push((filename, file, flat_index.clone()));
|
||||
dists.push(FlatIndexEntry {
|
||||
filename,
|
||||
file,
|
||||
index: flat_index.clone(),
|
||||
});
|
||||
}
|
||||
Ok(FlatIndexEntries::from_entries(dists))
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ mod extension;
|
|||
mod source_dist;
|
||||
mod wheel;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum DistFilename {
|
||||
SourceDistFilename(SourceDistFilename),
|
||||
WheelFilename(WheelFilename),
|
||||
|
|
|
@ -14,6 +14,8 @@ use uv_pep440::{Version, VersionParseError};
|
|||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
rkyv::Archive,
|
||||
|
|
|
@ -11,7 +11,18 @@ use uv_platform_tags::{TagCompatibility, Tags};
|
|||
|
||||
use crate::{BuildTag, BuildTagError};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Hash,
|
||||
rkyv::Archive,
|
||||
rkyv::Deserialize,
|
||||
rkyv::Serialize,
|
||||
)]
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct WheelFilename {
|
||||
pub name: PackageName,
|
||||
|
|
|
@ -40,16 +40,16 @@ impl FlatIndex {
|
|||
) -> Self {
|
||||
// Collect compatible distributions.
|
||||
let mut index = FxHashMap::default();
|
||||
for (filename, file, url) in entries.entries {
|
||||
let distributions = index.entry(filename.name().clone()).or_default();
|
||||
for entry in entries.entries {
|
||||
let distributions = index.entry(entry.filename.name().clone()).or_default();
|
||||
Self::add_file(
|
||||
distributions,
|
||||
file,
|
||||
filename,
|
||||
entry.file,
|
||||
entry.filename,
|
||||
tags,
|
||||
hasher,
|
||||
build_options,
|
||||
url,
|
||||
entry.index,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use predicates::prelude::predicate;
|
|||
use url::Url;
|
||||
|
||||
use crate::common::{
|
||||
self, build_vendor_links_url, decode_token, get_bin, uv_snapshot, venv_bin_path, TestContext,
|
||||
self, build_vendor_links_url, decode_token, get_bin, uv_snapshot, venv_bin_path,
|
||||
venv_to_interpreter, TestContext,
|
||||
};
|
||||
use uv_fs::Simplified;
|
||||
use uv_static::EnvVars;
|
||||
|
@ -7516,3 +7517,40 @@ fn test_dynamic_version_sdist_wrong_version() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Install a package with multiple wheels at the same version, differing only in the build tag. We
|
||||
/// should choose the wheel with the highest build tag.
|
||||
#[test]
|
||||
fn build_tag() {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("build-tag")
|
||||
.arg("--find-links")
|
||||
.arg(context.workspace_root.join("scripts/links/")), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ build-tag==1.0.0
|
||||
"###
|
||||
);
|
||||
|
||||
// Ensure that we choose the highest build tag (5).
|
||||
uv_snapshot!(Command::new(venv_to_interpreter(&context.venv))
|
||||
.arg("-B")
|
||||
.arg("-c")
|
||||
.arg("import build_tag; build_tag.main()")
|
||||
.current_dir(&context.temp_dir), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
5
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use assert_cmd::prelude::*;
|
||||
use assert_fs::{fixture::ChildPath, prelude::*};
|
||||
use indoc::indoc;
|
||||
use indoc::{formatdoc, indoc};
|
||||
use insta::assert_snapshot;
|
||||
|
||||
use crate::common::{download_to_disk, uv_snapshot, venv_bin_path, TestContext};
|
||||
use predicates::prelude::predicate;
|
||||
use tempfile::tempdir_in;
|
||||
|
||||
use crate::common::{download_to_disk, uv_snapshot, venv_bin_path, TestContext};
|
||||
use uv_fs::Simplified;
|
||||
use uv_static::EnvVars;
|
||||
|
||||
#[test]
|
||||
|
@ -5589,3 +5589,124 @@ fn sync_git_path_dependency() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sync a package with multiple wheels at the same version, differing only in the build tag. We
|
||||
/// should choose the wheel with the highest build tag.
|
||||
#[test]
|
||||
fn sync_build_tag() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
// Populate the `--find-links` entries.
|
||||
fs_err::create_dir_all(context.temp_dir.join("links"))?;
|
||||
|
||||
for entry in fs_err::read_dir(context.workspace_root.join("scripts/links"))? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path
|
||||
.file_name()
|
||||
.and_then(|file_name| file_name.to_str())
|
||||
.is_some_and(|file_name| file_name.starts_with("build_tag-"))
|
||||
{
|
||||
let dest = context
|
||||
.temp_dir
|
||||
.join("links")
|
||||
.join(path.file_name().unwrap());
|
||||
fs_err::copy(&path, &dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child("pyproject.toml")
|
||||
.write_str(&formatdoc! { r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["build-tag"]
|
||||
|
||||
[tool.uv]
|
||||
find-links = ["{}"]
|
||||
"#,
|
||||
context.temp_dir.join("links/").portable_display(),
|
||||
})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
"###);
|
||||
|
||||
let lock = fs_err::read_to_string(context.temp_dir.child("uv.lock")).unwrap();
|
||||
|
||||
insta::with_settings!({
|
||||
filters => context.filters(),
|
||||
}, {
|
||||
assert_snapshot!(
|
||||
lock, @r###"
|
||||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[options]
|
||||
exclude-newer = "2024-03-25T00:00:00Z"
|
||||
|
||||
[[package]]
|
||||
name = "build-tag"
|
||||
version = "1.0.0"
|
||||
source = { registry = "links" }
|
||||
wheels = [
|
||||
{ path = "build_tag-1.0.0-1-py2.py3-none-any.whl" },
|
||||
{ path = "build_tag-1.0.0-3-py2.py3-none-any.whl" },
|
||||
{ path = "build_tag-1.0.0-5-py2.py3-none-any.whl" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "build-tag" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "build-tag" }]
|
||||
"###
|
||||
);
|
||||
});
|
||||
|
||||
// Re-run with `--locked`.
|
||||
uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
"###);
|
||||
|
||||
// Install from the lockfile.
|
||||
uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Installed 1 package in [TIME]
|
||||
+ build-tag==1.0.0
|
||||
"###);
|
||||
|
||||
// Ensure that we choose the highest build tag (5).
|
||||
uv_snapshot!(context.filters(), context.run().arg("--no-sync").arg("python").arg("-c").arg("import build_tag; build_tag.main()"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
5
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
BIN
scripts/links/build_tag-1.0.0-1-py2.py3-none-any.whl
Normal file
BIN
scripts/links/build_tag-1.0.0-1-py2.py3-none-any.whl
Normal file
Binary file not shown.
BIN
scripts/links/build_tag-1.0.0-3-py2.py3-none-any.whl
Normal file
BIN
scripts/links/build_tag-1.0.0-3-py2.py3-none-any.whl
Normal file
Binary file not shown.
BIN
scripts/links/build_tag-1.0.0-5-py2.py3-none-any.whl
Normal file
BIN
scripts/links/build_tag-1.0.0-5-py2.py3-none-any.whl
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue