mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35: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),
|
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)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct FlatIndexEntries {
|
pub struct FlatIndexEntries {
|
||||||
/// The list of `--find-links` entries.
|
/// 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
|
/// Whether any `--find-links` entries could not be resolved due to a lack of network
|
||||||
/// connectivity.
|
/// connectivity.
|
||||||
pub offline: bool,
|
pub offline: bool,
|
||||||
|
@ -45,7 +53,7 @@ pub struct FlatIndexEntries {
|
||||||
|
|
||||||
impl FlatIndexEntries {
|
impl FlatIndexEntries {
|
||||||
/// Create a [`FlatIndexEntries`] from a list of `--find-links` entries.
|
/// 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 {
|
Self {
|
||||||
entries,
|
entries,
|
||||||
offline: false,
|
offline: false,
|
||||||
|
@ -130,6 +138,9 @@ impl<'a> FlatIndexClient<'a> {
|
||||||
while let Some(entries) = fetches.next().await.transpose()? {
|
while let Some(entries) = fetches.next().await.transpose()? {
|
||||||
results.extend(entries);
|
results.extend(entries);
|
||||||
}
|
}
|
||||||
|
results
|
||||||
|
.entries
|
||||||
|
.sort_by(|a, b| a.filename.cmp(&b.filename).then(a.index.cmp(&b.index)));
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,11 +222,11 @@ impl<'a> FlatIndexClient<'a> {
|
||||||
.expect("archived version always deserializes")
|
.expect("archived version always deserializes")
|
||||||
})
|
})
|
||||||
.filter_map(|file| {
|
.filter_map(|file| {
|
||||||
Some((
|
Some(FlatIndexEntry {
|
||||||
DistFilename::try_from_normalized_filename(&file.filename)?,
|
filename: DistFilename::try_from_normalized_filename(&file.filename)?,
|
||||||
file,
|
file,
|
||||||
flat_index.clone(),
|
index: flat_index.clone(),
|
||||||
))
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(FlatIndexEntries::from_entries(files))
|
Ok(FlatIndexEntries::from_entries(files))
|
||||||
|
@ -283,7 +294,11 @@ impl<'a> FlatIndexClient<'a> {
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
dists.push((filename, file, flat_index.clone()));
|
dists.push(FlatIndexEntry {
|
||||||
|
filename,
|
||||||
|
file,
|
||||||
|
index: flat_index.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(FlatIndexEntries::from_entries(dists))
|
Ok(FlatIndexEntries::from_entries(dists))
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ mod extension;
|
||||||
mod source_dist;
|
mod source_dist;
|
||||||
mod wheel;
|
mod wheel;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum DistFilename {
|
pub enum DistFilename {
|
||||||
SourceDistFilename(SourceDistFilename),
|
SourceDistFilename(SourceDistFilename),
|
||||||
WheelFilename(WheelFilename),
|
WheelFilename(WheelFilename),
|
||||||
|
|
|
@ -14,6 +14,8 @@ use uv_pep440::{Version, VersionParseError};
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
Eq,
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
Serialize,
|
Serialize,
|
||||||
Deserialize,
|
Deserialize,
|
||||||
rkyv::Archive,
|
rkyv::Archive,
|
||||||
|
|
|
@ -11,7 +11,18 @@ use uv_platform_tags::{TagCompatibility, Tags};
|
||||||
|
|
||||||
use crate::{BuildTag, BuildTagError};
|
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))]
|
#[rkyv(derive(Debug))]
|
||||||
pub struct WheelFilename {
|
pub struct WheelFilename {
|
||||||
pub name: PackageName,
|
pub name: PackageName,
|
||||||
|
|
|
@ -40,16 +40,16 @@ impl FlatIndex {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Collect compatible distributions.
|
// Collect compatible distributions.
|
||||||
let mut index = FxHashMap::default();
|
let mut index = FxHashMap::default();
|
||||||
for (filename, file, url) in entries.entries {
|
for entry in entries.entries {
|
||||||
let distributions = index.entry(filename.name().clone()).or_default();
|
let distributions = index.entry(entry.filename.name().clone()).or_default();
|
||||||
Self::add_file(
|
Self::add_file(
|
||||||
distributions,
|
distributions,
|
||||||
file,
|
entry.file,
|
||||||
filename,
|
entry.filename,
|
||||||
tags,
|
tags,
|
||||||
hasher,
|
hasher,
|
||||||
build_options,
|
build_options,
|
||||||
url,
|
entry.index,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@ use predicates::prelude::predicate;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::common::{
|
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_fs::Simplified;
|
||||||
use uv_static::EnvVars;
|
use uv_static::EnvVars;
|
||||||
|
@ -7516,3 +7517,40 @@ fn test_dynamic_version_sdist_wrong_version() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
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 anyhow::Result;
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::prelude::*;
|
||||||
use assert_fs::{fixture::ChildPath, prelude::*};
|
use assert_fs::{fixture::ChildPath, prelude::*};
|
||||||
use indoc::indoc;
|
use indoc::{formatdoc, indoc};
|
||||||
use insta::assert_snapshot;
|
use insta::assert_snapshot;
|
||||||
|
|
||||||
|
use crate::common::{download_to_disk, uv_snapshot, venv_bin_path, TestContext};
|
||||||
use predicates::prelude::predicate;
|
use predicates::prelude::predicate;
|
||||||
use tempfile::tempdir_in;
|
use tempfile::tempdir_in;
|
||||||
|
use uv_fs::Simplified;
|
||||||
use crate::common::{download_to_disk, uv_snapshot, venv_bin_path, TestContext};
|
|
||||||
use uv_static::EnvVars;
|
use uv_static::EnvVars;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -5589,3 +5589,124 @@ fn sync_git_path_dependency() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
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