Skip to content

Commit e94a0f6

Browse files
committed
Add tests
1 parent 0e19f1a commit e94a0f6

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

crates/uv/tests/it/pip_compile.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
use std::env::current_dir;
44
use std::fs;
5+
use std::io::Cursor;
56
use std::path::PathBuf;
67

78
use anyhow::{bail, Context, Result};
89
use assert_fs::prelude::*;
10+
use flate2::write::GzEncoder;
11+
use fs_err::File;
912
use indoc::indoc;
1013
use url::Url;
1114

@@ -13858,3 +13861,70 @@ fn compile_lowest_extra_unpinned_warning() -> Result<()> {
1385813861

1385913862
Ok(())
1386013863
}
13864+
13865+
/// Test that we use the version in the source distribution filename for compiling, even if the
13866+
/// version is declared as dynamic.
13867+
///
13868+
/// `test_dynamic_version_sdist_wrong_version` checks that this version must be correct.
13869+
#[test]
13870+
fn dynamic_version_source_dist() -> Result<()> {
13871+
let context = TestContext::new("3.12");
13872+
13873+
// Write a source dist that has a version in its name, a dynamic version in pyproject.toml
13874+
// and check that we don't build it when compiling.
13875+
let pyproject_toml = r#"
13876+
[project]
13877+
name = "foo"
13878+
requires-python = ">=3.9"
13879+
dependencies = []
13880+
dynamic = ["version"]
13881+
"#;
13882+
13883+
let setup_py = "boom()";
13884+
13885+
let source_dist = context.temp_dir.child("foo-1.2.3.tar.gz");
13886+
// Flush the file after we're done.
13887+
{
13888+
let file = File::create(source_dist.path())?;
13889+
let enc = GzEncoder::new(file, flate2::Compression::default());
13890+
let mut tar = tar::Builder::new(enc);
13891+
13892+
for (path, contents) in [
13893+
("foo-1.2.3/pyproject.toml", pyproject_toml),
13894+
("foo-1.2.3/setup.py", setup_py),
13895+
] {
13896+
let mut header = tar::Header::new_gnu();
13897+
header.set_size(contents.len() as u64);
13898+
header.set_mode(0o644);
13899+
header.set_cksum();
13900+
tar.append_data(&mut header, path, Cursor::new(contents))?;
13901+
}
13902+
tar.finish()?;
13903+
}
13904+
13905+
let requirements_in = context.temp_dir.child("requirements.in");
13906+
requirements_in.write_str(indoc::indoc! {r"
13907+
foo
13908+
"})?;
13909+
13910+
uv_snapshot!(context.filters(), context
13911+
.pip_compile()
13912+
.arg(requirements_in.path())
13913+
.arg("--no-index")
13914+
.arg("--find-links")
13915+
.arg(context.temp_dir.path()), @r###"
13916+
success: true
13917+
exit_code: 0
13918+
----- stdout -----
13919+
# This file was autogenerated by uv via the following command:
13920+
# uv pip compile --cache-dir [CACHE_DIR] [TEMP_DIR]/requirements.in --no-index
13921+
foo==1.2.3
13922+
# via -r requirements.in
13923+
13924+
----- stderr -----
13925+
Resolved 1 package in [TIME]
13926+
"###
13927+
);
13928+
13929+
Ok(())
13930+
}

crates/uv/tests/it/pip_install.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
use std::io::{Cursor, Write};
12
use std::process::Command;
23

34
use anyhow::Result;
45
use assert_cmd::prelude::*;
56
use assert_fs::prelude::*;
7+
use flate2::write::GzEncoder;
68
use fs_err as fs;
9+
use fs_err::File;
710
use indoc::indoc;
811
use predicates::prelude::predicate;
912
use url::Url;
@@ -7455,3 +7458,61 @@ fn respect_no_installer_metadata_env_var() {
74557458
.join("INSTALLER");
74567459
assert!(!installer_file.exists());
74577460
}
7461+
7462+
/// Check that we error if a source dist lies about its built wheel version.
7463+
#[test]
7464+
fn test_dynamic_version_sdist_wrong_version() -> Result<()> {
7465+
let context = TestContext::new("3.12");
7466+
7467+
// Write a source dist that has a version in its name, a dynamic version in pyproject.toml,
7468+
// but reports the wrong version when built.
7469+
let pyproject_toml = r#"
7470+
[project]
7471+
name = "foo"
7472+
requires-python = ">=3.9"
7473+
dependencies = []
7474+
dynamic = ["version"]
7475+
"#;
7476+
7477+
let setup_py = indoc! {r#"
7478+
from setuptools import setup
7479+
7480+
setup(name="foo", version="10.11.12")
7481+
"#};
7482+
7483+
let source_dist = context.temp_dir.child("foo-1.2.3.tar.gz");
7484+
// Flush the file after we're done.
7485+
{
7486+
let file = File::create(source_dist.path())?;
7487+
let enc = GzEncoder::new(file, flate2::Compression::default());
7488+
let mut tar = tar::Builder::new(enc);
7489+
7490+
for (path, contents) in [
7491+
("foo-1.2.3/pyproject.toml", pyproject_toml),
7492+
("foo-1.2.3/setup.py", setup_py),
7493+
] {
7494+
let mut header = tar::Header::new_gnu();
7495+
header.set_size(contents.len() as u64);
7496+
header.set_mode(0o644);
7497+
header.set_cksum();
7498+
tar.append_data(&mut header, path, Cursor::new(contents))?;
7499+
}
7500+
tar.finish()?;
7501+
}
7502+
7503+
uv_snapshot!(context.filters(), context
7504+
.pip_install()
7505+
.arg(source_dist.path()), @r###"
7506+
success: false
7507+
exit_code: 1
7508+
----- stdout -----
7509+
7510+
----- stderr -----
7511+
Resolved 1 package in [TIME]
7512+
× Failed to build `foo @ file://[TEMP_DIR]/foo-1.2.3.tar.gz`
7513+
╰─▶ Package metadata version `10.11.12` does not match given version `1.2.3`
7514+
"###
7515+
);
7516+
7517+
Ok(())
7518+
}

0 commit comments

Comments
 (0)