Use Packse server in check command tests

This commit is contained in:
Zsolt Dollenstein
2026-06-18 17:10:36 +01:00
parent 3d7e2f9450
commit d6cfd81416
+110 -112
View File
@@ -1,11 +1,11 @@
use anyhow::Result;
#[cfg(feature = "test-pypi")]
use assert_cmd::assert::OutputAssertExt;
use assert_fs::prelude::*;
use indoc::indoc;
use insta::assert_snapshot;
use uv_static::EnvVars;
use uv_test::packse::PackseServer;
use uv_test::{diff_snapshot, uv_snapshot};
#[test]
@@ -41,6 +41,7 @@ fn check_project() -> Result<()> {
#[test]
fn check_no_sync_creates_lock_without_sync() -> Result<()> {
let server = PackseServer::new("local/local-simple.toml");
let context = uv_test::test_context!("3.12");
context
@@ -51,7 +52,7 @@ fn check_no_sync_creates_lock_without_sync() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
dependencies = ["a==1.2.3"]
"#})?;
context.temp_dir.child("main.py").write_str(indoc! {r"
x: int = 1
@@ -62,8 +63,9 @@ fn check_no_sync_creates_lock_without_sync() -> Result<()> {
context
.check()
.arg("--no-sync")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.arg("--ty-version")
.arg("0.0.17"),
@"
@@ -85,16 +87,13 @@ fn check_no_sync_creates_lock_without_sync() -> Result<()> {
revision = 3
requires-python = ">=3.12"
[options]
exclude-newer = "2026-02-15T00:00:00Z"
[[package]]
name = "iniconfig"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload-time = "2023-01-07T11:08:11.254Z" }
name = "a"
version = "1.2.3+foo"
source = { registry = "http://[LOCALHOST]/simple/" }
sdist = { url = "http://[LOCALHOST]/files/a-1.2.3+foo.tar.gz", hash = "sha256:d8c42806a0bf7b47451778ed2a909a2f9d22fe3a4bac673934fc8fb2537a886a", upload-time = "2024-03-24T00:00:00Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload-time = "2023-01-07T11:08:09.864Z" },
{ url = "http://[LOCALHOST]/files/a-1.2.3+foo-py3-none-any.whl", hash = "sha256:2fd8eec176cad72b6c4372682485914aff65d215fb8cd71c85e9ed4511fa8bbe", upload-time = "2024-03-24T00:00:00Z" },
]
[[package]]
@@ -102,14 +101,14 @@ fn check_no_sync_creates_lock_without_sync() -> Result<()> {
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "iniconfig" },
{ name = "a" },
]
[package.metadata]
requires-dist = [{ name = "iniconfig", specifier = "==2.0.0" }]
requires-dist = [{ name = "a", specifier = "==1.2.3" }]
"#);
});
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
Ok(())
}
@@ -145,8 +144,6 @@ fn check_no_sync_uses_compatible_lock_interpreter() -> Result<()> {
.arg("--no-sync")
.arg("--python")
.arg("3.11")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--ty-version")
.arg("0.0.17"),
@"
@@ -172,6 +169,7 @@ fn check_no_sync_uses_compatible_lock_interpreter() -> Result<()> {
#[test]
fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
let server = PackseServer::new("local/local-simple.toml");
let context = uv_test::test_context!("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
@@ -180,12 +178,13 @@ fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]
dependencies = ["a==1.2.3+bar"]
"#})?;
context
.lock()
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.assert()
.success();
let stale_lock = context.read("uv.lock");
@@ -195,7 +194,7 @@ fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
dependencies = ["a==1.2.3+foo"]
"#})?;
context.temp_dir.child("main.py").write_str(indoc! {r"
x: int = 1
@@ -206,8 +205,9 @@ fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
context
.check()
.arg("--no-sync")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.arg("--ty-version")
.arg("0.0.17"),
@"
@@ -229,38 +229,21 @@ fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
assert_snapshot!(diff, @r#"
--- old
+++ new
@@ -1,48 +1,26 @@
@@ -1,23 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.12"
[options]
exclude-newer = "2026-02-15T00:00:00Z"
[[package]]
-name = "anyio"
-version = "3.7.0"
+name = "iniconfig"
+version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "idna" },
- { name = "sniffio" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737, upload-time = "2023-05-27T11:12:46.688Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload-time = "2023-01-07T11:08:11.254Z" }
name = "a"
-version = "1.2.3+bar"
+version = "1.2.3+foo"
source = { registry = "http://[LOCALHOST]/simple/" }
-sdist = { url = "http://[LOCALHOST]/files/a-1.2.3+bar.tar.gz", hash = "sha256:b96640078f7011764f0e428c0481c726149e4ae3190d29f9f5f7c2372e11f074", upload-time = "2024-03-24T00:00:00Z" }
+sdist = { url = "http://[LOCALHOST]/files/a-1.2.3+foo.tar.gz", hash = "sha256:d8c42806a0bf7b47451778ed2a909a2f9d22fe3a4bac673934fc8fb2537a886a", upload-time = "2024-03-24T00:00:00Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0", size = 80873, upload-time = "2023-05-27T11:12:44.474Z" },
-]
-
-[[package]]
-name = "idna"
-version = "3.11"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload-time = "2023-01-07T11:08:09.864Z" },
- { url = "http://[LOCALHOST]/files/a-1.2.3+bar-py3-none-any.whl", hash = "sha256:dc4f0c4f8461a32a72175670fa502b7bfb6c0e0ab542e8e26895caf77fc4b17d", upload-time = "2024-03-24T00:00:00Z" },
+ { url = "http://[LOCALHOST]/files/a-1.2.3+foo-py3-none-any.whl", hash = "sha256:2fd8eec176cad72b6c4372682485914aff65d215fb8cd71c85e9ed4511fa8bbe", upload-time = "2024-03-24T00:00:00Z" },
]
[[package]]
@@ -268,31 +251,22 @@ fn check_no_sync_updates_stale_lock_without_sync() -> Result<()> {
version = "0.1.0"
source = { virtual = "." }
dependencies = [
- { name = "anyio" },
+ { name = "iniconfig" },
{ name = "a" },
]
[package.metadata]
-requires-dist = [{ name = "anyio", specifier = "==3.7.0" }]
-
-[[package]]
-name = "sniffio"
-version = "1.3.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
-]
+requires-dist = [{ name = "iniconfig", specifier = "==2.0.0" }]
-requires-dist = [{ name = "a", specifier = "==1.2.3+bar" }]
+requires-dist = [{ name = "a", specifier = "==1.2.3+foo" }]
"#);
});
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
Ok(())
}
#[test]
fn check_no_sync_locked_rejects_stale_lock_without_update() -> Result<()> {
let server = PackseServer::new("local/local-simple.toml");
let context = uv_test::test_context!("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
@@ -301,12 +275,13 @@ fn check_no_sync_locked_rejects_stale_lock_without_update() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]
dependencies = ["a==1.2.3+bar"]
"#})?;
context
.lock()
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.assert()
.success();
let stale_lock = context.read("uv.lock");
@@ -316,7 +291,7 @@ fn check_no_sync_locked_rejects_stale_lock_without_update() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
dependencies = ["a==1.2.3+foo"]
"#})?;
uv_snapshot!(
@@ -325,8 +300,9 @@ fn check_no_sync_locked_rejects_stale_lock_without_update() -> Result<()> {
.check()
.arg("--no-sync")
.arg("--locked")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z"),
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER),
@"
success: false
exit_code: 2
@@ -339,7 +315,7 @@ fn check_no_sync_locked_rejects_stale_lock_without_update() -> Result<()> {
);
assert_eq!(stale_lock, context.read("uv.lock"));
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
Ok(())
}
@@ -380,6 +356,7 @@ fn check_no_sync_locked_requires_existing_lock() -> Result<()> {
#[test]
fn check_no_sync_frozen_uses_existing_lock_without_update() -> Result<()> {
let server = PackseServer::new("local/local-simple.toml");
let context = uv_test::test_context!("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
@@ -388,12 +365,13 @@ fn check_no_sync_frozen_uses_existing_lock_without_update() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]
dependencies = ["a==1.2.3+bar"]
"#})?;
context
.lock()
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.assert()
.success();
let stale_lock = context.read("uv.lock");
@@ -403,7 +381,7 @@ fn check_no_sync_frozen_uses_existing_lock_without_update() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
dependencies = ["a==1.2.3+foo"]
"#})?;
context.temp_dir.child("main.py").write_str(indoc! {r"
x: int = 1
@@ -415,8 +393,9 @@ fn check_no_sync_frozen_uses_existing_lock_without_update() -> Result<()> {
.check()
.arg("--no-sync")
.arg("--frozen")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.arg("--ty-version")
.arg("0.0.17"),
@"
@@ -431,7 +410,7 @@ fn check_no_sync_frozen_uses_existing_lock_without_update() -> Result<()> {
);
assert_eq!(stale_lock, context.read("uv.lock"));
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
Ok(())
}
@@ -472,6 +451,7 @@ fn check_no_sync_frozen_requires_existing_lock() -> Result<()> {
#[test]
fn check_no_sync_isolated_does_not_write_lock_or_sync() -> Result<()> {
let server = PackseServer::new("local/local-simple.toml");
let context = uv_test::test_context!("3.12");
context
@@ -482,7 +462,7 @@ fn check_no_sync_isolated_does_not_write_lock_or_sync() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig==2.0.0"]
dependencies = ["a==1.2.3"]
"#})?;
context.temp_dir.child("main.py").write_str(indoc! {r"
x: int = 1
@@ -494,8 +474,9 @@ fn check_no_sync_isolated_does_not_write_lock_or_sync() -> Result<()> {
.check()
.arg("--no-sync")
.arg("--isolated")
.arg("--exclude-newer")
.arg("2026-02-15T00:00:00Z")
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.arg("--ty-version")
.arg("0.0.17"),
@"
@@ -510,7 +491,7 @@ fn check_no_sync_isolated_does_not_write_lock_or_sync() -> Result<()> {
);
assert!(!context.temp_dir.child("uv.lock").exists());
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
Ok(())
}
@@ -947,8 +928,8 @@ fn check_type_error() -> Result<()> {
}
#[test]
#[cfg(feature = "test-pypi")]
fn check_with_declared_dependency() -> Result<()> {
let server = PackseServer::new("extras/extra-does-not-exist-backtrack.toml");
let context = uv_test::test_context!("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
@@ -957,19 +938,25 @@ fn check_with_declared_dependency() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig"]
dependencies = ["a==3.0.0"]
[project.optional-dependencies]
test = ["typing-extensions"]
test = ["b==1.0.0"]
"#})?;
let main_py = context.temp_dir.child("main.py");
main_py.write_str(indoc! {r"
import iniconfig
import a
"})?;
// ty should resolve the import via the synced virtual environment.
uv_snapshot!(context.filters(), context.check(), @"
uv_snapshot!(
context.filters(),
context
.check()
.arg("--index")
.arg(server.index_url()),
@"
success: true
exit_code: 0
----- stdout -----
@@ -978,26 +965,22 @@ fn check_with_declared_dependency() -> Result<()> {
----- stderr -----
warning: `uv check` is experimental and may change without warning. Pass `--preview-features check-command` to disable this warning.
Installed 1 package in [TIME]
");
"
);
context
.assert_command(
"from importlib.metadata import distribution; assert distribution('iniconfig').read_text('INSTALLER') == 'uv'",
"from importlib.metadata import distribution; assert distribution('a').read_text('INSTALLER') == 'uv'",
)
.success();
assert!(
!context
.site_packages()
.join("typing_extensions.py")
.exists()
);
assert!(!context.site_packages().join("b").exists());
Ok(())
}
#[test]
#[cfg(feature = "test-pypi")]
fn check_isolated() -> Result<()> {
let server = PackseServer::new("extras/extra-does-not-exist-backtrack.toml");
let context = uv_test::test_context!("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
@@ -1006,18 +989,25 @@ fn check_isolated() -> Result<()> {
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig"]
dependencies = ["a==3.0.0"]
"#})?;
let main_py = context.temp_dir.child("main.py");
main_py.write_str(indoc! {r"
import iniconfig
import a
"})?;
let environment_sentinel = context.venv.child("sentinel");
environment_sentinel.write_str("present")?;
uv_snapshot!(context.filters(), context.check().arg("--isolated"), @"
uv_snapshot!(
context.filters(),
context
.check()
.arg("--isolated")
.arg("--index")
.arg(server.index_url()),
@"
success: true
exit_code: 0
----- stdout -----
@@ -1026,36 +1016,44 @@ fn check_isolated() -> Result<()> {
----- stderr -----
warning: `uv check` is experimental and may change without warning. Pass `--preview-features check-command` to disable this warning.
Installed 1 package in [TIME]
");
"
);
assert!(!context.temp_dir.child("uv.lock").exists());
assert!(!context.site_packages().join("iniconfig").exists());
assert!(!context.site_packages().join("a").exists());
assert!(environment_sentinel.exists());
// An existing lockfile should not be updated.
context.lock().assert().success();
context
.lock()
.arg("--index")
.arg(server.index_url())
.env_remove(EnvVars::UV_EXCLUDE_NEWER)
.assert()
.success();
let existing_lock = context.read("uv.lock");
pyproject_toml.write_str(indoc! {r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["iniconfig", "typing-extensions"]
dependencies = ["a==3.0.0", "b==1.0.0"]
"#})?;
main_py.write_str(indoc! {r"
import iniconfig
import typing_extensions
import a
import b
"})?;
context.check().arg("--isolated").assert().success();
context
.check()
.arg("--isolated")
.arg("--index")
.arg(server.index_url())
.assert()
.success();
assert_eq!(existing_lock, context.read("uv.lock"));
assert!(!context.site_packages().join("iniconfig").exists());
assert!(
!context
.site_packages()
.join("typing_extensions.py")
.exists()
);
assert!(!context.site_packages().join("a").exists());
assert!(!context.site_packages().join("b").exists());
assert!(environment_sentinel.exists());
Ok(())