From 3bfc0bb97f38630993c3b4cd9188561dae04426c Mon Sep 17 00:00:00 2001 From: konstin Date: Thu, 27 Nov 2025 15:51:13 +0100 Subject: [PATCH] Update packse to 0.3.54 Add https://github.com/astral-sh/packse/pull/293 for https://github.com/astral-sh/uv/pull/16824#discussion_r2556176057 Beware of https://github.com/mitsuhiko/insta/issues/833 when working with packse for the time being (i.e., `cargo binstall cargo-insta@1.42.1 --force`) --- crates/uv/tests/it/common/mod.rs | 2 +- crates/uv/tests/it/lock_scenarios.rs | 169 +++++++++++++++++++- crates/uv/tests/it/pip_compile_scenarios.rs | 2 +- crates/uv/tests/it/pip_install_scenarios.rs | 2 +- scripts/scenarios/pylock.toml | 6 +- scripts/scenarios/pyproject.toml | 2 +- 6 files changed, 175 insertions(+), 8 deletions(-) diff --git a/crates/uv/tests/it/common/mod.rs b/crates/uv/tests/it/common/mod.rs index 1399b584d..30c3813ff 100644 --- a/crates/uv/tests/it/common/mod.rs +++ b/crates/uv/tests/it/common/mod.rs @@ -33,7 +33,7 @@ use uv_static::EnvVars; // Exclude any packages uploaded after this date. static EXCLUDE_NEWER: &str = "2024-03-25T00:00:00Z"; -pub const PACKSE_VERSION: &str = "0.3.53"; +pub const PACKSE_VERSION: &str = "0.3.54"; pub const DEFAULT_PYTHON_VERSION: &str = "3.12"; /// Using a find links url allows using `--index-url` instead of `--extra-index-url` in tests diff --git a/crates/uv/tests/it/lock_scenarios.rs b/crates/uv/tests/it/lock_scenarios.rs index 088fc18c3..aa96ad1bd 100644 --- a/crates/uv/tests/it/lock_scenarios.rs +++ b/crates/uv/tests/it/lock_scenarios.rs @@ -1,7 +1,7 @@ //! DO NOT EDIT //! //! Generated with `./scripts/sync_scenarios.sh` -//! Scenarios from +//! Scenarios from //! #![cfg(all(feature = "python", feature = "pypi"))] #![allow(clippy::needless_raw_string_hashes)] @@ -5347,6 +5347,173 @@ fn virtual_package_extra_priorities() -> Result<()> { Ok(()) } +/// A package is first used under a marker that is a subset of the required environments that it fulfills, and then under a marker that is a subset it doesn't fulfill. +/// +/// `a` has a wheel only supports Windows, and the required platforms are Linux and Windows. The first time we encounter `a`, it's used with a Windows-only marker, so it doesn't violate. Afterwards, we select `b`, and while it doesn't change the version for `a`, it requires it universally. Now the resolution needs to fail, as `a` is now missing the Linux wheel. +/// +/// See +/// +/// ```text +/// markers-change-after-selection +/// ├── environment +/// │ └── python3.12 +/// ├── root +/// │ ├── requires a; sys_platform == "win32" +/// │ │ └── satisfied by a-1.0.0 +/// │ └── requires b +/// │ └── satisfied by b-1.0.0 +/// ├── a +/// │ └── a-1.0.0 +/// └── b +/// └── b-1.0.0 +/// └── requires a; sys_platform == "linux" +/// └── satisfied by a-1.0.0 +/// ``` +#[test] +fn markers_change_after_selection() -> Result<()> { + let context = TestContext::new("3.12"); + + // In addition to the standard filters, swap out package names for shorter messages + let mut filters = context.filters(); + filters.push((r"markers-change-after-selection-", "package-")); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r###" + [project] + name = "project" + version = "0.1.0" + dependencies = [ + '''markers-change-after-selection-a; sys_platform == "win32"''', + '''markers-change-after-selection-b''', + ] + requires-python = ">=3.12" + [tool.uv] + required-environments = [ + '''sys_platform == "linux"''', + '''sys_platform == "win32"''', + ] + "###, + )?; + + let mut cmd = context.lock(); + cmd.env_remove(EnvVars::UV_EXCLUDE_NEWER); + cmd.arg("--index-url").arg(packse_index_url()); + uv_snapshot!(filters, cmd, @r" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies for split (markers: sys_platform == 'linux'): + ╰─▶ Because only package-a{sys_platform == 'win32'}==1.0.0 is available and package-a==1.0.0 has no Linux-compatible wheels, we can conclude that all versions of package-a{sys_platform == 'win32'} cannot be used. + And because your project depends on package-a{sys_platform == 'win32'}, we can conclude that your project's requirements are unsatisfiable. + " + ); + + Ok(()) +} + +/// While both Linux and Windows are required and `win-only` has only a Windows wheel, `win-only` is also used only on Windows. +/// +/// ```text +/// requires-python-subset +/// ├── environment +/// │ └── python3.12 +/// ├── root +/// │ └── requires win-only; sys_platform == "win32" +/// │ └── satisfied by win-only-1.0.0 +/// └── win-only +/// └── win-only-1.0.0 +/// ``` +#[test] +fn requires_python_subset() -> Result<()> { + let context = TestContext::new("3.12"); + + // In addition to the standard filters, swap out package names for shorter messages + let mut filters = context.filters(); + filters.push((r"requires-python-subset-", "package-")); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r###" + [project] + name = "project" + version = "0.1.0" + dependencies = [ + '''requires-python-subset-win-only; sys_platform == "win32"''', + ] + requires-python = ">=3.12" + [tool.uv] + required-environments = [ + '''sys_platform == "linux"''', + '''sys_platform == "win32"''', + ] + "###, + )?; + + let mut cmd = context.lock(); + cmd.env_remove(EnvVars::UV_EXCLUDE_NEWER); + cmd.arg("--index-url").arg(packse_index_url()); + uv_snapshot!(filters, cmd, @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + " + ); + + let lock = context.read("uv.lock"); + insta::with_settings!({ + filters => filters, + }, { + assert_snapshot!( + lock, @r#" + version = 1 + revision = 3 + requires-python = ">=3.12" + required-markers = [ + "sys_platform == 'linux'", + "sys_platform == 'win32'", + ] + + [[package]] + name = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "package-win-only", marker = "sys_platform == 'win32'" }, + ] + + [package.metadata] + requires-dist = [{ name = "package-win-only", marker = "sys_platform == 'win32'" }] + + [[package]] + name = "package-win-only" + version = "1.0.0" + source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } + wheels = [ + { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/requires_python_subset_win_only-1.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:91d59021b1c4aad7449e315ae1248c5c588a7e84cb7592671a41453012302711" }, + ] + "# + ); + }); + + // Assert the idempotence of `uv lock` when resolving from the lockfile (`--locked`). + context + .lock() + .arg("--locked") + .env_remove(EnvVars::UV_EXCLUDE_NEWER) + .arg("--index-url") + .arg(packse_index_url()) + .assert() + .success(); + + Ok(()) +} + /// When a dependency is only required on a specific platform (like x86_64), omit wheels that target other platforms (like aarch64). /// /// ```text diff --git a/crates/uv/tests/it/pip_compile_scenarios.rs b/crates/uv/tests/it/pip_compile_scenarios.rs index d1e2abc96..29f35ee34 100644 --- a/crates/uv/tests/it/pip_compile_scenarios.rs +++ b/crates/uv/tests/it/pip_compile_scenarios.rs @@ -1,7 +1,7 @@ //! DO NOT EDIT //! //! Generated with `./scripts/sync_scenarios.sh` -//! Scenarios from +//! Scenarios from //! #![cfg(all(feature = "python", feature = "pypi", unix))] diff --git a/crates/uv/tests/it/pip_install_scenarios.rs b/crates/uv/tests/it/pip_install_scenarios.rs index b2e43fa88..0209d19ab 100644 --- a/crates/uv/tests/it/pip_install_scenarios.rs +++ b/crates/uv/tests/it/pip_install_scenarios.rs @@ -1,7 +1,7 @@ //! DO NOT EDIT //! //! Generated with `./scripts/sync_scenarios.sh` -//! Scenarios from +//! Scenarios from //! #![cfg(all(feature = "python", feature = "pypi", unix))] diff --git a/scripts/scenarios/pylock.toml b/scripts/scenarios/pylock.toml index f55d1cc15..8fcee6fbf 100644 --- a/scripts/scenarios/pylock.toml +++ b/scripts/scenarios/pylock.toml @@ -66,9 +66,9 @@ wheels = [{ url = "https://files.pythonhosted.org/packages/20/12/38679034af33278 [[packages]] name = "packse" -version = "0.3.53" -sdist = { url = "https://files.pythonhosted.org/packages/52/58/373b6281bb741e875893dc351ac5f180c3fdce18a3b889f773725ff964b2/packse-0.3.53.tar.gz", upload-time = 2025-09-16T09:37:55Z, size = 5879063, hashes = { sha256 = "fcdbbb60f8ad4af94901891699a95ade4f15b9e769b4d8f443a2f3ef7aa74067" } } -wheels = [{ url = "https://files.pythonhosted.org/packages/fc/86/d5482bb2933fe47d282b1dae74cc9084b094f28229848ba8ea01a77fe0da/packse-0.3.53-py3-none-any.whl", upload-time = 2025-09-16T09:37:53Z, size = 34039, hashes = { sha256 = "78cf05f5e0b916f4070a66f04f3b371e2d4ac0c3917f38cb692a33fa6e9d764b" } }] +version = "0.3.54" +sdist = { url = "https://files.pythonhosted.org/packages/a3/e2/9ba11ffac2cb2719ace80731bec4c0c54b6b74c25f1675f45082e40dcd6f/packse-0.3.54.tar.gz", upload-time = 2025-11-27T14:41:23Z, size = 5879759, hashes = { sha256 = "1ef801475423f51724efaa20577ad708c29a89499001fae387b7ac2b5cfaf534" } } +wheels = [{ url = "https://files.pythonhosted.org/packages/5b/31/7d1e18a74e14a8d33aab5d24abdd19e47210d55846502380481384a33478/packse-0.3.54-py3-none-any.whl", upload-time = 2025-11-27T14:41:25Z, size = 34098, hashes = { sha256 = "bdb86af409a0c622f3a4374700b4bbb94fabc3d0e4d4d42b37e7aab3d863ff96" } }] [[packages]] name = "pathspec" diff --git a/scripts/scenarios/pyproject.toml b/scripts/scenarios/pyproject.toml index fd49a4345..03346b480 100644 --- a/scripts/scenarios/pyproject.toml +++ b/scripts/scenarios/pyproject.toml @@ -1,5 +1,5 @@ [dependency-groups] packse = [ "chevron-blue", - "packse>=0.3.53" + "packse>=0.3.54" ]