Skip to content

Commit

Permalink
Add disjoint
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Nov 28, 2024
1 parent 6ed78a7 commit b2415d6
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 31 deletions.
4 changes: 3 additions & 1 deletion crates/uv-pep508/src/marker/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,9 @@ impl MarkerTree {
/// false negatives, i.e. it may not be able to detect that two markers are disjoint for
/// complex expressions.
pub fn is_disjoint(&self, other: &MarkerTree) -> bool {
INTERNER.lock().is_disjoint(self.0, other.0)
let mutex = &*MUTUAL_EXCLUSIONS;
let node = INTERNER.lock().and(self.0, other.0);
node.is_false() || INTERNER.lock().is_disjoint(node, mutex.0)
}

/// Returns the contents of this marker tree, if it contains at least one expression.
Expand Down
1 change: 0 additions & 1 deletion crates/uv-resolver/src/resolution/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ impl ResolverOutput {
// Insert each node only once.
continue;
}

Self::add_edge(&mut graph, &mut inverse, root_index, edge, marker.clone());
}
}
Expand Down
17 changes: 11 additions & 6 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
let mut marker = constraint.marker.clone();
marker.and(requirement.marker.clone());

if marker.is_false() {
trace!("skipping {constraint} because of disjoint markers: {}", marker.try_to_string().unwrap());
return None;
}

Cow::Owned(Requirement {
name: constraint.name.clone(),
extras: constraint.extras.clone(),
Expand All @@ -1734,17 +1739,17 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
let mut marker = constraint.marker.clone();
marker.and(requirement.marker.clone());

// Additionally, if the requirement is `requests ; sys_platform == 'darwin'`
// and the constraint is `requests ; python_version == '3.6'`, the
// constraint should only apply when _both_ markers are true.
if marker.is_false() {
trace!("skipping {constraint} because of Requires-Python: {requires_python}");
trace!("skipping {constraint} because of disjoint markers: {}", marker.try_to_string().unwrap());
return None;
}

// Additionally, if the requirement is `requests ; sys_platform == 'darwin'`
// and the constraint is `requests ; python_version == '3.6'`, the
// constraint should only apply when _both_ markers are true.
if python_marker.is_disjoint(&marker) {
trace!(
"skipping constraint {requirement} because of Requires-Python: {requires_python}",
requires_python = python_requirement.target(),
"skipping constraint {requirement} because of Requires-Python: {requires_python}"
);
return None;
}
Expand Down
164 changes: 163 additions & 1 deletion crates/uv/tests/it/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,169 @@ fn dependency_conflicting_markers() -> Result<()> {
"#,
)?;

context.lock().assert().success();
uv_snapshot!(context.filters(), context.lock(), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 11 packages in [TIME]
"###);

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

insta::with_settings!(
{
filters => context.filters(),
},
{
insta::assert_snapshot!(
lock, @r###"
version = 1
requires-python = ">=3.12"
resolution-markers = [
"sys_platform == 'darwin'",
"sys_platform == 'win32'",
"sys_platform != 'darwin' and sys_platform != 'win32'",
]
[options]
exclude-newer = "2024-03-25T00:00:00Z"
[[package]]
name = "async-generator"
version = "1.10"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ce/b6/6fa6b3b598a03cba5e80f829e0dadbb49d7645f523d209b2fb7ea0bbb02a/async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144", size = 29870 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/71/52/39d20e03abd0ac9159c162ec24b93fbcaa111e8400308f2465432495ca2b/async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b", size = 18857 },
]
[[package]]
name = "attrs"
version = "23.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/fc/f800d51204003fa8ae392c4e8278f256206e7a919b708eef054f5f4b650d/attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", size = 780820 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1", size = 60752 },
]
[[package]]
name = "cffi"
version = "1.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/ce/95b0bae7968c65473e1298efb042e10cafc7bafc14d9e4f154008241c91d/cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", size = 512873 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c9/6e/751437067affe7ac0944b1ad4856ec11650da77f0dd8f305fae1117ef7bb/cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", size = 173564 },
{ url = "https://files.pythonhosted.org/packages/e9/63/e285470a4880a4f36edabe4810057bd4b562c6ddcc165eacf9c3c7210b40/cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", size = 181956 },
]
[[package]]
name = "idna"
version = "3.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 },
]
[[package]]
name = "outcome"
version = "1.3.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs", marker = "sys_platform == 'darwin' or sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692 },
]
[[package]]
name = "project"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "trio", version = "0.10.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'win32'" },
{ name = "trio", version = "0.25.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" },
]
[package.metadata]
requires-dist = [
{ name = "trio", marker = "sys_platform == 'darwin'", specifier = "==0.25.0" },
{ name = "trio", marker = "sys_platform == 'win32'", specifier = "==0.10.0" },
]
[[package]]
name = "pycparser"
version = "2.21"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", size = 170877 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", size = 118697 },
]
[[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 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
[[package]]
name = "sortedcontainers"
version = "2.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
]
[[package]]
name = "trio"
version = "0.10.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"sys_platform == 'win32'",
]
dependencies = [
{ name = "async-generator", marker = "sys_platform == 'win32'" },
{ name = "attrs", marker = "sys_platform == 'win32'" },
{ name = "cffi", marker = "os_name == 'nt' and sys_platform == 'win32'" },
{ name = "idna", marker = "sys_platform == 'win32'" },
{ name = "outcome", marker = "sys_platform == 'win32'" },
{ name = "sniffio", marker = "sys_platform == 'win32'" },
{ name = "sortedcontainers", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e6/20/37be7b5f47db6a9fbf905b5de5386e5b7193c45d07becb750db6f03cd117/trio-0.10.0.tar.gz", hash = "sha256:d323cc15f6406d15954af91e5e34af2001cc24163fdde29e3f88a227a1b53ab0", size = 402511 }
[[package]]
name = "trio"
version = "0.25.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"sys_platform == 'darwin'",
]
dependencies = [
{ name = "attrs", marker = "sys_platform == 'darwin'" },
{ name = "idna", marker = "sys_platform == 'darwin'" },
{ name = "outcome", marker = "sys_platform == 'darwin'" },
{ name = "sniffio", marker = "sys_platform == 'darwin'" },
{ name = "sortedcontainers", marker = "sys_platform == 'darwin'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b4/51/4f5ae37ec58768b9c30e5bc5b89431a7baf3fa9d0dda98983af6ef55eb47/trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e", size = 551863 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/17/c9/f86f89f14d52f9f2f652ce24cb2f60141a51d087db1563f3fba94ba07346/trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81", size = 467161 },
]
"###
);
}
);

uv_snapshot!(context.filters(), context.export(), @r###"
success: true
Expand Down
32 changes: 10 additions & 22 deletions crates/uv/tests/it/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7218,13 +7218,13 @@ fn universal_conflicting() -> Result<()> {
# via
# outcome
# trio
cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')
cffi==1.16.0 ; os_name == 'nt' and sys_platform == 'win32'
# via trio
idna==3.6 ; sys_platform == 'darwin' or sys_platform == 'win32'
# via trio
outcome==1.3.0.post0 ; sys_platform == 'darwin' or sys_platform == 'win32'
# via trio
pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')
pycparser==2.21 ; os_name == 'nt' and sys_platform == 'win32'
# via cffi
sniffio==1.3.1 ; sys_platform == 'darwin' or sys_platform == 'win32'
# via trio
Expand Down Expand Up @@ -8951,8 +8951,6 @@ fn universal_disjoint_extra() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
# via click
flask==3.0.2 ; sys_platform == 'linux'
# via -r requirements.in
itsdangerous==2.1.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
Expand All @@ -8969,7 +8967,7 @@ fn universal_disjoint_extra() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down Expand Up @@ -9000,8 +8998,6 @@ fn universal_disjoint_extra_no_strip() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
# via click
flask==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via -r requirements.in
flask[async]==3.0.2 ; sys_platform == 'linux'
Expand All @@ -9022,7 +9018,7 @@ fn universal_disjoint_extra_no_strip() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down Expand Up @@ -9050,7 +9046,7 @@ fn universal_overlap_extra_base() -> Result<()> {
# via flask
click==8.1.7
# via flask
colorama==0.4.6 ; platform_system == 'Windows'
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform != 'darwin'
# via click
flask==3.0.2
# via -r requirements.in
Expand Down Expand Up @@ -9097,7 +9093,7 @@ fn universal_overlap_extra_base_no_strip() -> Result<()> {
# via flask
click==8.1.7
# via flask
colorama==0.4.6 ; platform_system == 'Windows'
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform != 'darwin'
# via click
flask==3.0.2
# via -r requirements.in
Expand Down Expand Up @@ -9147,8 +9143,6 @@ fn universal_overlap_extras() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
# via click
flask==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via -r requirements.in
itsdangerous==2.1.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
Expand All @@ -9165,7 +9159,7 @@ fn universal_overlap_extras() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down Expand Up @@ -9196,8 +9190,6 @@ fn universal_overlap_extras_no_strip() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
# via click
flask[async]==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via -r requirements.in
flask[dotenv]==3.0.2 ; sys_platform == 'darwin'
Expand All @@ -9216,7 +9208,7 @@ fn universal_overlap_extras_no_strip() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down Expand Up @@ -9246,8 +9238,6 @@ fn universal_identical_extras() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin'
# via flask
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform == 'darwin'
# via click
flask==3.0.2 ; sys_platform == 'darwin'
# via -r requirements.in
itsdangerous==2.1.2 ; sys_platform == 'darwin'
Expand All @@ -9264,7 +9254,7 @@ fn universal_identical_extras() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down Expand Up @@ -9295,8 +9285,6 @@ fn universal_identical_extras_no_strip() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin'
# via flask
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform == 'darwin'
# via click
flask[async, dotenv]==3.0.2 ; sys_platform == 'darwin'
# via -r requirements.in
itsdangerous==2.1.2 ; sys_platform == 'darwin'
Expand All @@ -9313,7 +9301,7 @@ fn universal_identical_extras_no_strip() -> Result<()> {
# via flask
----- stderr -----
Resolved 10 packages in [TIME]
Resolved 9 packages in [TIME]
"###
);

Expand Down

0 comments on commit b2415d6

Please sign in to comment.