Skip to content

Commit 082065c

Browse files
committed
Exclude distributions from lock
1 parent a95f4cf commit 082065c

File tree

4 files changed

+182
-25
lines changed

4 files changed

+182
-25
lines changed

crates/uv-distribution-types/src/prioritized_distribution.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ impl PrioritizedDist {
371371
self.0.markers.or(implied_markers(&dist.filename));
372372
}
373373
}
374+
// Track the hashes.
375+
if !compatibility.is_excluded() {
376+
self.0.hashes.extend(hashes);
377+
}
374378
// Track the highest-priority wheel.
375379
if let Some((.., existing_compatibility)) = self.best_wheel() {
376380
if compatibility.is_more_compatible(existing_compatibility) {
@@ -379,7 +383,6 @@ impl PrioritizedDist {
379383
} else {
380384
self.0.best_wheel_index = Some(self.0.wheels.len());
381385
}
382-
self.0.hashes.extend(hashes);
383386
self.0.wheels.push((dist, compatibility));
384387
}
385388

@@ -394,6 +397,10 @@ impl PrioritizedDist {
394397
if compatibility.is_compatible() {
395398
self.0.markers = MarkerTree::TRUE;
396399
}
400+
// Track the hashes.
401+
if !compatibility.is_excluded() {
402+
self.0.hashes.extend(hashes);
403+
}
397404
// Track the highest-priority source.
398405
if let Some((.., existing_compatibility)) = &self.0.source {
399406
if compatibility.is_more_compatible(existing_compatibility) {
@@ -402,7 +409,6 @@ impl PrioritizedDist {
402409
} else {
403410
self.0.source = Some((dist, compatibility));
404411
}
405-
self.0.hashes.extend(hashes);
406412
}
407413

408414
/// Return the highest-priority distribution for the package version, if any.
@@ -501,6 +507,7 @@ impl PrioritizedDist {
501507
.0
502508
.wheels
503509
.iter()
510+
.filter(|(_, compatibility)| !compatibility.is_excluded())
504511
.map(|(wheel, _)| wheel.clone())
505512
.collect();
506513
let sdist = self.0.source.as_ref().map(|(sdist, _)| sdist.clone());
@@ -514,7 +521,12 @@ impl PrioritizedDist {
514521
/// If this prioritized dist has an sdist, then this creates a source
515522
/// distribution.
516523
pub fn source_dist(&self) -> Option<RegistrySourceDist> {
517-
let mut sdist = self.0.source.as_ref().map(|(sdist, _)| sdist.clone())?;
524+
let mut sdist = self
525+
.0
526+
.source
527+
.as_ref()
528+
.filter(|(_, compatibility)| !compatibility.is_excluded())
529+
.map(|(sdist, _)| sdist.clone())?;
518530
assert!(
519531
sdist.wheels.is_empty(),
520532
"source distribution should not have any wheels yet"
@@ -623,6 +635,11 @@ impl WheelCompatibility {
623635
matches!(self, Self::Compatible(_, _, _))
624636
}
625637

638+
/// Return `true` if the distribution is excluded.
639+
pub fn is_excluded(&self) -> bool {
640+
matches!(self, Self::Incompatible(IncompatibleWheel::ExcludeNewer(_)))
641+
}
642+
626643
/// Return `true` if the current compatibility is more compatible than another.
627644
///
628645
/// Compatible wheels are always higher more compatible than incompatible wheels.
@@ -650,6 +667,14 @@ impl SourceDistCompatibility {
650667
matches!(self, Self::Compatible(_))
651668
}
652669

670+
/// Return `true` if the distribution is excluded.
671+
pub fn is_excluded(&self) -> bool {
672+
matches!(
673+
self,
674+
Self::Incompatible(IncompatibleSource::ExcludeNewer(_))
675+
)
676+
}
677+
653678
/// Return the higher priority compatibility.
654679
///
655680
/// Compatible source distributions are always higher priority than incompatible source distributions.

crates/uv/tests/it/lock.rs

+90-2
Original file line numberDiff line numberDiff line change
@@ -26082,8 +26082,6 @@ fn lock_pytorch_local_preference() -> Result<()> {
2608226082
{ name = "torch", version = "2.6.0+cpu", source = { registry = "https://astral-sh.github.io/pytorch-mirror/whl/cpu" }, marker = "sys_platform != 'darwin'" },
2608326083
]
2608426084
wheels = [
26085-
{ url = "https://files.pythonhosted.org/packages/52/5b/76ca113a853b19c7b1da761f8a72cb6429b3bd0bf932537d8df4657f47c3/torchvision-0.21.0-1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:ffa2a16499508fe6798323e455f312c7c55f2a88901c9a7c0fb1efa86cf7e327", size = 2329878 },
26086-
{ url = "https://files.pythonhosted.org/packages/4e/fe/5e193353706dab96fe73ae100d5a633ff635ce310e0d92f3bc2958d075b1/torchvision-0.21.0-1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:7e9e9afa150e40cd2a8f0701c43cb82a8d724f512896455c0918b987f94b84a4", size = 2280711 },
2608726085
{ url = "https://files.pythonhosted.org/packages/6e/1b/28f527b22d5e8800184d0bc847f801ae92c7573a8c15979d92b7091c0751/torchvision-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:97a5814a93c793aaf0179cfc7f916024f4b63218929aee977b645633d074a49f", size = 1784140 },
2608826086
{ url = "https://files.pythonhosted.org/packages/36/63/0722e153fd27d64d5b0af45b5c8cb0e80b35a68cf0130303bc9a8bb095c7/torchvision-0.21.0-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:b578bcad8a4083b40d34f689b19ca9f7c63e511758d806510ea03c29ac568f7b", size = 7238673 },
2608926087
{ url = "https://files.pythonhosted.org/packages/bb/ea/03541ed901cdc30b934f897060d09bbf7a98466a08ad1680320f9ce0cbe0/torchvision-0.21.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5083a5b1fec2351bf5ea9900a741d54086db75baec4b1d21e39451e00977f1b1", size = 14701186 },
@@ -26455,3 +26453,93 @@ fn lock_invalid_fork_markers() -> Result<()> {
2645526453

2645626454
Ok(())
2645726455
}
26456+
26457+
#[test]
26458+
fn lock_omit_wheels_exclude_newer() -> Result<()> {
26459+
let context = TestContext::new("3.12").with_exclude_newer("2024-08-01T00:00:00Z");
26460+
26461+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
26462+
pyproject_toml.write_str(
26463+
r#"
26464+
[project]
26465+
name = "project"
26466+
version = "0.1.0"
26467+
requires-python = ">=3.12"
26468+
dependencies = ["pillow-avif-plugin"]
26469+
"#,
26470+
)?;
26471+
26472+
uv_snapshot!(context.filters(), context.lock(), @r"
26473+
success: true
26474+
exit_code: 0
26475+
----- stdout -----
26476+
26477+
----- stderr -----
26478+
Resolved 2 packages in [TIME]
26479+
");
26480+
26481+
let lock = context.read("uv.lock");
26482+
26483+
insta::with_settings!({
26484+
filters => context.filters(),
26485+
}, {
26486+
assert_snapshot!(
26487+
lock, @r#"
26488+
version = 1
26489+
revision = 1
26490+
requires-python = ">=3.12"
26491+
26492+
[options]
26493+
exclude-newer = "2024-08-01T00:00:00Z"
26494+
26495+
[[package]]
26496+
name = "pillow-avif-plugin"
26497+
version = "1.4.6"
26498+
source = { registry = "https://pypi.org/simple" }
26499+
sdist = { url = "https://files.pythonhosted.org/packages/2d/eb/9c097e058c9d5bb7cd39b32730397d645856a81360b4e49cafe16ec1f358/pillow-avif-plugin-1.4.6.tar.gz", hash = "sha256:855cf50d03f6fc16e1fd5e364b3cea0b79f4bf90d39ff2123969735d851e08ba", size = 19632 }
26500+
wheels = [
26501+
{ url = "https://files.pythonhosted.org/packages/b2/f7/460c854c3f4a9802aabd0a25b4814a7e5902c776a6501498a4078bf2a0d3/pillow_avif_plugin-1.4.6-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e2087daa49881421a5e703fcff80aa2cbcb5a455cf73114ed5f0ea2a697794c8", size = 7980980 },
26502+
{ url = "https://files.pythonhosted.org/packages/f5/11/2f0fa7d135f91a8e34d9040b18a899d185776a642f5773ca33d45b0996ba/pillow_avif_plugin-1.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5bacc0802516f054f98d9f218ada17b2e8a756e35cb71e7401bb8422848fe796", size = 5743257 },
26503+
{ url = "https://files.pythonhosted.org/packages/24/b6/5a2fda66a192c0a372bcd7968c5914ccc6dcd48cd57b2f6cccba4587e209/pillow_avif_plugin-1.4.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e74e53951228c3e6ff5141121bd2876e8aecdb27d5f12d01cc519258e0073d8b", size = 6431301 },
26504+
{ url = "https://files.pythonhosted.org/packages/ac/1d/2d6f816e15e56b053758fbd6d625fbd79b5cf22e775fce9967b83ede8c31/pillow_avif_plugin-1.4.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37e1314500cec3457210f4c8a7583afe35751f076efa8122faa0f205403d645", size = 7984138 },
26505+
{ url = "https://files.pythonhosted.org/packages/86/36/32e9576c512fb53096ee050a112a12c6054c4e9c6ce2ec9e7e6f4d9d5d11/pillow_avif_plugin-1.4.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d643db246d6c07994fbb98b5fa6c6ae8f9b19b4ed24566bc06942b7dad10ad47", size = 8123272 },
26506+
{ url = "https://files.pythonhosted.org/packages/f0/5f/0bb9ec1910a5ece813ac6324b1d0f148cf71a0e5297ab8fcfce1e48a4ebe/pillow_avif_plugin-1.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:f262547edeec00ad287c8845ac6c9d7d822ef4b00d1832175c4c8fd692e34eba", size = 10564587 },
26507+
]
26508+
26509+
[[package]]
26510+
name = "project"
26511+
version = "0.1.0"
26512+
source = { virtual = "." }
26513+
dependencies = [
26514+
{ name = "pillow-avif-plugin" },
26515+
]
26516+
26517+
[package.metadata]
26518+
requires-dist = [{ name = "pillow-avif-plugin" }]
26519+
"#
26520+
);
26521+
});
26522+
26523+
// Re-run with `--locked`.
26524+
uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r"
26525+
success: true
26526+
exit_code: 0
26527+
----- stdout -----
26528+
26529+
----- stderr -----
26530+
Resolved 2 packages in [TIME]
26531+
");
26532+
26533+
// Re-run with `--offline`. We shouldn't need a network connection to validate an
26534+
// already-correct lockfile with immutable metadata.
26535+
uv_snapshot!(context.filters(), context.lock().arg("--locked").arg("--offline").arg("--no-cache"), @r"
26536+
success: true
26537+
exit_code: 0
26538+
----- stdout -----
26539+
26540+
----- stderr -----
26541+
Resolved 2 packages in [TIME]
26542+
");
26543+
26544+
Ok(())
26545+
}

crates/uv/tests/it/pip_compile.rs

+64
Original file line numberDiff line numberDiff line change
@@ -16130,6 +16130,70 @@ fn respect_non_local_preference() -> Result<()> {
1613016130
Ok(())
1613116131
}
1613216132

16133+
#[test]
16134+
fn omit_wheels_exclude_newer() -> Result<()> {
16135+
let context = TestContext::new("3.12").with_exclude_newer("2024-08-01T00:00:00Z");
16136+
let requirements_in = context.temp_dir.child("requirements.in");
16137+
requirements_in.write_str("pillow-avif-plugin")?;
16138+
16139+
uv_snapshot!(context
16140+
.pip_compile()
16141+
.arg("requirements.in")
16142+
.arg("--universal")
16143+
.arg("--generate-hashes"), @r"
16144+
success: true
16145+
exit_code: 0
16146+
----- stdout -----
16147+
# This file was autogenerated by uv via the following command:
16148+
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal --generate-hashes
16149+
pillow-avif-plugin==1.4.6 \
16150+
--hash=sha256:0014a215e197c52520d3946f3704c8c0932a170cc5783f96d2385f55191dce29 \
16151+
--hash=sha256:07372b7740439cc26346d8e3995de1fd5c49a92ab307321b74b3e6305a7e0e49 \
16152+
--hash=sha256:09a7e4b00b18df55b9f34d4f031060ca46d8f5f5e0ba347dda600dcb5172e5f2 \
16153+
--hash=sha256:0e699ca8dcfee82732495e101401567184fed6ba10f17e7fb872c46415606ec7 \
16154+
--hash=sha256:2347399f2457e5efacec8fc9e446a5a90252b8723c6a47dc61e2353aa97e3e2e \
16155+
--hash=sha256:25d1dea0c496a49b17a336b271263ea76a4a0af19553565e95c4bb03281a4113 \
16156+
--hash=sha256:323804efe752cf4d15fdcf770749ba23d727f8ea94b95cfe42bec597f3b9bbbb \
16157+
--hash=sha256:334e1d39e8b3b4548db690df3735039378e96e1497fd8ba0e25a5e21561b7cf5 \
16158+
--hash=sha256:41a8c41b56a891adbcff30933009d475fdd649f2025d62ba59885975ed4379c0 \
16159+
--hash=sha256:450b34d19d88443e39b011e84b54433f7ccd6cf8774ed626e433ec3cc7d52924 \
16160+
--hash=sha256:56be2604b734caf23788922dbcc92d880d241d02b444c7a8367a65bb25b16aac \
16161+
--hash=sha256:584469ea7dedd8ca4f579917cf22f25e8ab980e1b98bbe212cbd7395f881cd42 \
16162+
--hash=sha256:5bacc0802516f054f98d9f218ada17b2e8a756e35cb71e7401bb8422848fe796 \
16163+
--hash=sha256:5c5e6575e0ca0cd292d459cf627a27a505f38a6edad6f35fd9c4bce4a2cccef3 \
16164+
--hash=sha256:5d3c1202e9e03b93ef5e385fcee917d73e23833618472e6416c0fc58b53ba8b8 \
16165+
--hash=sha256:60699d10679c8361690703b79abde4a2e7b8047540f0c58fd5da0ac672a15321 \
16166+
--hash=sha256:6556cbee2d755dc99a99a5a85c302393e58bcbbf675bc93fa9ab283904dadbfc \
16167+
--hash=sha256:6bc73ea62605c8725aba2422de1b546a5c4a6e5e73dcf66f9e22102249342d6b \
16168+
--hash=sha256:7d2e933e9b197e9a51c3fbfce389a70201fbce1b7c60172f790760217d7927f8 \
16169+
--hash=sha256:855cf50d03f6fc16e1fd5e364b3cea0b79f4bf90d39ff2123969735d851e08ba \
16170+
--hash=sha256:91537935612d8fb4b8f621a912ce0eb4e363fdf615d472b20a043a7a18efb461 \
16171+
--hash=sha256:963ce7b93340f235db5c7f16b46835c72681896052dcbf1652a01946e7b9103e \
16172+
--hash=sha256:a6f97ffc84cdce0926f86a2f4bee088e661f5f93bec9112adca281341f463479 \
16173+
--hash=sha256:b37e1314500cec3457210f4c8a7583afe35751f076efa8122faa0f205403d645 \
16174+
--hash=sha256:b4f08c341d8aed2d7762589fdd99c4d3e191d4976dab59516b522704a67a281d \
16175+
--hash=sha256:b7c2e4adcdf7341dc05f31f13d85b6c4eed0e08daafc836e7b3317df41074bab \
16176+
--hash=sha256:b95c477fc619a82a68800ff18599e2704aec6fcf9aa65898b02f0240feeb0af5 \
16177+
--hash=sha256:c1cd659136fca622a9324fa7efa56f711f2e576206754c284b80aa5504fb96e4 \
16178+
--hash=sha256:c8b9347a91acd183db302e198cf582127eb3de98ad185bf9aff773c99e415320 \
16179+
--hash=sha256:c96ee1d1b504a2efa80c9d6d3b71a9884c724dc34d6e67131a64678e09c7a81c \
16180+
--hash=sha256:ce89c26671cd0fcb7967e4be4098ae8775b93cc6376ecd523c815cb5a2146298 \
16181+
--hash=sha256:d643db246d6c07994fbb98b5fa6c6ae8f9b19b4ed24566bc06942b7dad10ad47 \
16182+
--hash=sha256:dec8a348e46266dd0bf20a6edd01b96b0a11042e8654d701444e4a5cebf7f44b \
16183+
--hash=sha256:df9a1e569543006abe0c534a3fa66ee1d72393644fd0d5bc74de57bfdb619573 \
16184+
--hash=sha256:e2087daa49881421a5e703fcff80aa2cbcb5a455cf73114ed5f0ea2a697794c8 \
16185+
--hash=sha256:e74e53951228c3e6ff5141121bd2876e8aecdb27d5f12d01cc519258e0073d8b \
16186+
--hash=sha256:f262547edeec00ad287c8845ac6c9d7d822ef4b00d1832175c4c8fd692e34eba \
16187+
--hash=sha256:fdd6ee615d948a2b68fd293f74a1a73d22e9d075f5d714b95a90ec2cb8da8de0
16188+
# via -r requirements.in
16189+
16190+
----- stderr -----
16191+
Resolved 1 package in [TIME]
16192+
");
16193+
16194+
Ok(())
16195+
}
16196+
1613316197
/// See: <https://github.com/astral-sh/uv/issues/12260>
1613416198
#[test]
1613516199
fn compile_quotes() -> Result<()> {

0 commit comments

Comments
 (0)