Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/uv-platform-tags/src/platform_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ impl PlatformTag {
}

impl PlatformTag {
/// Returns `true` if the platform is "any" (i.e., not specific to a platform).
pub fn is_any(&self) -> bool {
matches!(self, Self::Any)
}

/// Returns `true` if the platform is manylinux-only.
pub fn is_manylinux(&self) -> bool {
matches!(
Expand Down
119 changes: 116 additions & 3 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,51 @@ static X86_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
.unwrap();
UniversalMarker::new(pep508, ConflictMarker::TRUE)
});
static LINUX_ARM_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *LINUX_MARKERS;
marker.and(*ARM_MARKERS);
marker
});
static LINUX_X86_64_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *LINUX_MARKERS;
marker.and(*X86_64_MARKERS);
marker
});
static LINUX_X86_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *LINUX_MARKERS;
marker.and(*X86_MARKERS);
marker
});
static WINDOWS_ARM_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *WINDOWS_MARKERS;
marker.and(*ARM_MARKERS);
marker
});
static WINDOWS_X86_64_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *WINDOWS_MARKERS;
marker.and(*X86_64_MARKERS);
marker
});
static WINDOWS_X86_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *WINDOWS_MARKERS;
marker.and(*X86_MARKERS);
marker
});
static MAC_ARM_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *MAC_MARKERS;
marker.and(*ARM_MARKERS);
marker
});
static MAC_X86_64_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *MAC_MARKERS;
marker.and(*X86_64_MARKERS);
marker
});
static MAC_X86_MARKERS: LazyLock<UniversalMarker> = LazyLock::new(|| {
let mut marker = *MAC_MARKERS;
marker.and(*X86_MARKERS);
marker
});

#[derive(Clone, Debug, serde::Deserialize)]
#[serde(try_from = "LockWire")]
Expand Down Expand Up @@ -336,14 +381,61 @@ impl Lock {
// a single disjointness check with the intersection is sufficient, so we have one
// constant per platform.
let platform_tags = wheel.filename.platform_tags();

if platform_tags.iter().all(PlatformTag::is_any) {
return true;
}

if platform_tags.iter().all(PlatformTag::is_linux) {
if graph.graph[node_index].marker().is_disjoint(*LINUX_MARKERS) {
if platform_tags.iter().all(PlatformTag::is_arm) {
if graph.graph[node_index]
.marker()
.is_disjoint(*LINUX_ARM_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86_64) {
if graph.graph[node_index]
.marker()
.is_disjoint(*LINUX_X86_64_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86) {
if graph.graph[node_index]
.marker()
.is_disjoint(*LINUX_X86_MARKERS)
{
return false;
}
} else if graph.graph[node_index].marker().is_disjoint(*LINUX_MARKERS) {
return false;
}
}

if platform_tags.iter().all(PlatformTag::is_windows) {
if graph.graph[node_index]
if platform_tags.iter().all(PlatformTag::is_arm) {
if graph.graph[node_index]
.marker()
.is_disjoint(*WINDOWS_ARM_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86_64) {
if graph.graph[node_index]
.marker()
.is_disjoint(*WINDOWS_X86_64_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86) {
if graph.graph[node_index]
.marker()
.is_disjoint(*WINDOWS_X86_MARKERS)
{
return false;
}
} else if graph.graph[node_index]
.marker()
.is_disjoint(*WINDOWS_MARKERS)
{
Expand All @@ -352,7 +444,28 @@ impl Lock {
}

if platform_tags.iter().all(PlatformTag::is_macos) {
if graph.graph[node_index].marker().is_disjoint(*MAC_MARKERS) {
if platform_tags.iter().all(PlatformTag::is_arm) {
if graph.graph[node_index]
.marker()
.is_disjoint(*MAC_ARM_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86_64) {
if graph.graph[node_index]
.marker()
.is_disjoint(*MAC_X86_64_MARKERS)
{
return false;
}
} else if platform_tags.iter().all(PlatformTag::is_x86) {
if graph.graph[node_index]
.marker()
.is_disjoint(*MAC_X86_MARKERS)
{
return false;
}
} else if graph.graph[node_index].marker().is_disjoint(*MAC_MARKERS) {
return false;
}
}
Expand Down
103 changes: 103 additions & 0 deletions crates/uv/tests/it/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30040,3 +30040,106 @@ fn lock_circular_path_dependency_explicit_index() -> Result<()> {

Ok(())
}

#[test]
fn lock_required_intersection() -> Result<()> {
let context = TestContext::new("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"numpy",
]

[tool.uv]
environments = [
"(sys_platform=='linux' and platform_machine=='x86_64')",
"(platform_machine=='arm64' and sys_platform=='darwin')"
]
"#,
)?;

uv_snapshot!(context.filters(), context.lock(), @r"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
");

let lock = context.read("uv.lock");

insta::with_settings!({
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r#"
version = 1
revision = 3
requires-python = ">=3.12"
resolution-markers = [
"platform_machine == 'x86_64' and sys_platform == 'linux'",
"platform_machine == 'arm64' and sys_platform == 'darwin'",
]
supported-markers = [
"platform_machine == 'x86_64' and sys_platform == 'linux'",
"platform_machine == 'arm64' and sys_platform == 'darwin'",
]

[options]
exclude-newer = "2024-03-25T00:00:00Z"

[[package]]
name = "numpy"
version = "1.26.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129, upload-time = "2024-02-06T00:26:44.495Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", size = 13685868, upload-time = "2024-02-05T23:55:56.28Z" },
{ url = "https://files.pythonhosted.org/packages/0f/50/de23fde84e45f5c4fda2488c759b69990fd4512387a8632860f3ac9cd225/numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed", size = 17950613, upload-time = "2024-02-05T23:56:56.054Z" },
{ url = "https://files.pythonhosted.org/packages/76/8c/2ba3902e1a0fc1c74962ea9bb33a534bb05984ad7ff9515bf8d07527cadd/numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0", size = 17786643, upload-time = "2024-02-05T23:57:56.585Z" },
]

[[package]]
name = "project"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "numpy", marker = "(platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
]

[package.metadata]
requires-dist = [{ name = "numpy" }]
"#
);
});

// 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]
");

// Re-run with `--offline`. We shouldn't need a network connection to validate an
// already-correct lockfile with immutable metadata.
uv_snapshot!(context.filters(), context.lock().arg("--locked").arg("--offline").arg("--no-cache"), @r###"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
"###);

Ok(())
}
Loading