From 4e748363f80807551c3144ee1b8ccf8c04a83472 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Tue, 30 Jul 2024 08:27:39 -0400 Subject: [PATCH] uv-resolver: fix marker propagation This PR represents a different approach to marker propagation in an attempt to unblock #4640. In particular, instead of propagating markers when forks are created, we wait until resolution is complete to propagate all markers to all dependencies in each fork. This ends up being both more robust (we should never miss anything) and simpler to implement because it doesn't require mutating a `PubGrubPackage` (which was pretty annoying). I think the main downside here is that this can sometimes add markers where they aren't needed. This actually winds up making quite a few snapshot changes. I went through each of them. Some of them look like legitimate bug fixes. Some of them look like superfluous additions. And some of them look like they would be removed if we had perfect marker normalization. But I don't think any of the changes are _wrong_. --- .../uv-resolver/src/pubgrub/dependencies.rs | 5 -- crates/uv-resolver/src/pubgrub/package.rs | 72 ------------------- crates/uv-resolver/src/resolver/mod.rs | 49 ++++++++----- crates/uv/tests/branching_urls.rs | 24 +++---- crates/uv/tests/lock.rs | 18 ++--- crates/uv/tests/lock_scenarios.rs | 12 ++-- crates/uv/tests/pip_compile.rs | 38 +++++----- 7 files changed, 76 insertions(+), 142 deletions(-) diff --git a/crates/uv-resolver/src/pubgrub/dependencies.rs b/crates/uv-resolver/src/pubgrub/dependencies.rs index 3af4458bf0a0..620a16eb6404 100644 --- a/crates/uv-resolver/src/pubgrub/dependencies.rs +++ b/crates/uv-resolver/src/pubgrub/dependencies.rs @@ -5,7 +5,6 @@ use pubgrub::range::Range; use tracing::warn; use pep440_rs::{Version, VersionSpecifiers}; -use pep508_rs::MarkerTree; use pypi_types::{ ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl, Requirement, RequirementSource, VerbatimParsedUrl, @@ -30,10 +29,6 @@ pub(crate) struct PubGrubDependency { } impl PubGrubDependency { - pub(crate) fn and_markers(&mut self, marker: &MarkerTree) { - self.package.and_markers(marker); - } - pub(crate) fn from_requirement<'a>( requirement: &'a Requirement, source_name: Option<&'a PackageName>, diff --git a/crates/uv-resolver/src/pubgrub/package.rs b/crates/uv-resolver/src/pubgrub/package.rs index 82fe2eb3e330..7cb09629eecf 100644 --- a/crates/uv-resolver/src/pubgrub/package.rs +++ b/crates/uv-resolver/src/pubgrub/package.rs @@ -1,4 +1,3 @@ -use std::mem; use std::ops::Deref; use std::sync::Arc; @@ -121,77 +120,6 @@ impl PubGrubPackage { } } - /// Modifies this package in place such that it is associated with the - /// given markers by intersecting them any pre-existing markers. - /// - /// That is, this causes the package to only be applicable to marker - /// environments corresponding to the intersection of what it previously - /// matched and the given markers. - /// - /// This is useful when one needs to propagate markers from a fork to each - /// of its constituent dependencies. This is necessary because within a - /// fork, the resolver makes decisions based on the markers that created - /// that fork. While in many cases these decisions are universal, some may - /// not be! And so the markers from the fork must be propagated out to the - /// individual packages. - pub(crate) fn and_markers(&mut self, fork_marker: &MarkerTree) { - // We do a little dance here to pluck out as much existing - // information from this package as we can to avoid allocs. - // It is possible that the `Arc::make_mut` will do a deep - // clone here, thereby defeating our efforts, but I think it - // is likely that in most cases it will not. This is because - // this routine should be called almost immediately after a - // `PubGrubPackage` is created and _before_ it is passed to - // PubGrub itself. - match Arc::make_mut(&mut self.0) { - PubGrubPackageInner::Root(_) | PubGrubPackageInner::Python(_) => {} - // In this case, we may or may not already have a marker. - // If we don't, then this implies we will, and thus we may - // need to switch `Package` to some other representation. - PubGrubPackageInner::Package { - ref mut name, - ref mut extra, - ref dev, - ref mut marker, - } => { - // This case *should* never happen, I believe, because - // a `Package` with a non-None `dev` can only happen as - // a result of a `Dev` package, which we should have - // processed already by the time we get this package. - if dev.is_some() { - return; - } - - let mut and = fork_marker.clone(); - if let Some(marker) = marker.take() { - and.and(marker); - } - *self = PubGrubPackage::from_package(mem::take(name), extra.take(), Some(and)); - } - // These cases are easy, because we can just modify the marker - // in place. - PubGrubPackageInner::Extra { ref mut marker, .. } => { - let mut and = fork_marker.clone(); - if let Some(marker) = marker.take() { - and.and(marker); - } - *marker = Some(and); - } - PubGrubPackageInner::Dev { ref mut marker, .. } => { - let mut and = fork_marker.clone(); - if let Some(marker) = marker.take() { - and.and(marker); - } - *marker = Some(and); - } - PubGrubPackageInner::Marker { ref mut marker, .. } => { - let mut and = fork_marker.clone(); - and.and(mem::replace(marker, MarkerTree::And(vec![]))); - *marker = and; - } - } - } - /// Returns the name of this PubGrub package, if it has one. pub(crate) fn name(&self) -> Option<&PackageName> { match &**self { diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index f7096128a066..f286240f69a4 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -2301,7 +2301,36 @@ impl ForkState { to_url: to_url.cloned(), to_extra: dependency_extra.clone(), to_dev: dependency_dev.clone(), - marker: None, + // This propagates markers from the fork to + // packages without any markers. These might wind + // up be duplicative (and are even further merged + // via disjunction when a ResolutionGraph is + // constructed), but normalization should simplify + // most such cases. + // + // In a previous implementation of marker + // propagation, markers were propagated at the + // time a fork was created. But this was crucially + // missing a key detail: the specific version of + // a package outside of a fork can be determined + // by the forks of its dependencies, even when + // that package is not part of a fork at the time + // the forks were created. In that case, it was + // possible for two versions of the same package + // to be unconditionally included in a resolution, + // which must never be. + // + // See https://github.com/astral-sh/uv/pull/5583 + // for an example of where this occurs with + // `Sphinx`. + // + // Here, instead, we do the marker propagation + // after resolution has completed. This relies + // on the fact that the markers aren't otherwise + // needed during resolution (which I believe is + // true), but is a more robust approach that should + // capture all cases. + marker: self.markers.fork_markers().cloned(), }; edges.insert(edge); } @@ -2736,9 +2765,6 @@ impl Dependencies { forks = new_forks; diverging_packages.push(name.clone()); } - for fork in &mut forks { - fork.propagate_markers(); - } ForkedDependencies::Forked { forks, diverging_packages, @@ -2833,21 +2859,6 @@ impl Fork { .map_or(true, |pkg_marker| !is_disjoint(pkg_marker, &self.markers)) }); } - - /// This attaches the marker in this fork to each of its dependencies. - /// - /// In effect, this "propagates" the markers to each individual dependency - /// that was spawned as the result of a fork. While in many cases the - /// markers will be combined when multiple forks choose the same version of - /// a dependency, in some cases, the version chosen can be specific to a - /// particular set of marker environments. In this case, the dependencies - /// will be platform specific and thus require marker expressions to appear - /// in the lock file. - fn propagate_markers(&mut self) { - for dependency in &mut self.dependencies { - dependency.and_markers(&self.markers); - } - } } /// Intermediate state that represents a *possible* grouping of forks diff --git a/crates/uv/tests/branching_urls.rs b/crates/uv/tests/branching_urls.rs index d321f6ea0c23..665b66aab4e4 100644 --- a/crates/uv/tests/branching_urls.rs +++ b/crates/uv/tests/branching_urls.rs @@ -232,8 +232,8 @@ fn root_package_splits_transitive_too() -> Result<()> { "python_version < '3.12'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "python_version < '3.12'" }, + { name = "sniffio", marker = "python_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770 } wheels = [ @@ -248,8 +248,8 @@ fn root_package_splits_transitive_too() -> Result<()> { "python_version >= '3.12'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "python_version >= '3.12'" }, + { name = "sniffio", marker = "python_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } wheels = [ @@ -270,7 +270,7 @@ fn root_package_splits_transitive_too() -> Result<()> { version = "0.1.0" source = { directory = "../b1" } dependencies = [ - { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" } }, + { name = "iniconfig", version = "1.1.1", source = { url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" }, marker = "python_version < '3.12'" }, ] [[distribution]] @@ -278,7 +278,7 @@ fn root_package_splits_transitive_too() -> Result<()> { version = "0.1.0" source = { directory = "../b2" } dependencies = [ - { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" } }, + { name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "python_version >= '3.12'" }, ] [[distribution]] @@ -407,8 +407,8 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { "python_version < '3.12'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "python_version < '3.12'" }, + { name = "sniffio", marker = "python_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770 } wheels = [ @@ -423,8 +423,8 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { "python_version >= '3.12'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "python_version >= '3.12'" }, + { name = "sniffio", marker = "python_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } wheels = [ @@ -436,7 +436,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { version = "0.1.0" source = { directory = "b1" } dependencies = [ - { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" } }, + { name = "iniconfig", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '3.12'" }, ] [[distribution]] @@ -444,7 +444,7 @@ fn root_package_splits_other_dependencies_too() -> Result<()> { version = "0.1.0" source = { directory = "b2" } dependencies = [ - { name = "iniconfig", version = "2.0.0", source = { registry = "https://pypi.org/simple" } }, + { name = "iniconfig", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version >= '3.12'" }, ] [[distribution]] diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 0bd5d2b0cf33..c027274b3500 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -2921,9 +2921,9 @@ fn lock_python_version_marker_complement() -> Result<()> { version = "0.1.0" source = { editable = "." } dependencies = [ - { name = "attrs", marker = "(python_full_version <= '3.10' and python_version == '3.10') or (python_full_version <= '3.10' and python_version < '3.10') or (python_full_version <= '3.10' and python_version > '3.10') or (python_full_version > '3.10' and python_version == '3.10') or (python_full_version > '3.10' and python_version < '3.10') or (python_full_version > '3.10' and python_version > '3.10')" }, - { name = "iniconfig", marker = "(python_full_version <= '3.10' and python_version == '3.10') or (python_full_version <= '3.10' and python_version < '3.10') or (python_full_version <= '3.10' and python_version > '3.10') or (python_full_version > '3.10' and python_version == '3.10') or (python_full_version > '3.10' and python_version < '3.10') or (python_full_version > '3.10' and python_version > '3.10')" }, - { name = "typing-extensions", marker = "(python_full_version <= '3.10' and python_version == '3.10') or (python_full_version <= '3.10' and python_version < '3.10') or (python_full_version <= '3.10' and python_version < '3.10' and python_version > '3.10') or (python_full_version <= '3.10' and python_version > '3.10') or (python_full_version > '3.10' and python_version == '3.10') or (python_full_version > '3.10' and python_version < '3.10') or (python_full_version > '3.10' and python_version < '3.10' and python_version > '3.10') or (python_full_version > '3.10' and python_version > '3.10')" }, + { name = "attrs" }, + { name = "iniconfig" }, + { name = "typing-extensions", marker = "python_full_version <= '3.10' or python_full_version > '3.10'" }, ] [[distribution]] @@ -4063,8 +4063,8 @@ fn lock_same_version_multiple_urls() -> Result<()> { "sys_platform != 'darwin'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "sys_platform != 'darwin'" }, + { name = "sniffio", marker = "sys_platform != 'darwin'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/99/0d/65165f99e5f4f3b4c43a5ed9db0fb7aa655f5a58f290727a30528a87eb45/anyio-3.0.0.tar.gz", hash = "sha256:b553598332c050af19f7d41f73a7790142f5bc3d5eb8bd82f5e515ec22019bd9", size = 116952 } wheels = [ @@ -4079,8 +4079,8 @@ fn lock_same_version_multiple_urls() -> Result<()> { "sys_platform == 'darwin'", ] dependencies = [ - { name = "idna" }, - { name = "sniffio" }, + { name = "idna", marker = "sys_platform == 'darwin'" }, + { name = "sniffio", marker = "sys_platform == 'darwin'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737 } wheels = [ @@ -4095,7 +4095,7 @@ fn lock_same_version_multiple_urls() -> Result<()> { "sys_platform == 'darwin'", ] dependencies = [ - { name = "anyio", version = "3.7.0", source = { registry = "https://pypi.org/simple" } }, + { name = "anyio", version = "3.7.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, ] [[distribution]] @@ -4106,7 +4106,7 @@ fn lock_same_version_multiple_urls() -> Result<()> { "sys_platform != 'darwin'", ] dependencies = [ - { name = "anyio", version = "3.0.0", source = { registry = "https://pypi.org/simple" } }, + { name = "anyio", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'darwin'" }, ] [[distribution]] diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index 35f458228f71..d4c6739759c2 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -570,7 +570,7 @@ fn fork_filter_sibling_dependencies() -> Result<()> { version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-d", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } }, + { name = "package-d", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_filter_sibling_dependencies_b-1.0.0.tar.gz#sha256=af3f861d6df9a2bbad55bae02acf17384ea2efa1abbf19206ac56cb021814613", hash = "sha256:af3f861d6df9a2bbad55bae02acf17384ea2efa1abbf19206ac56cb021814613" } wheels = [ @@ -582,7 +582,7 @@ fn fork_filter_sibling_dependencies() -> Result<()> { version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-d", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } }, + { name = "package-d", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'darwin'" }, ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_filter_sibling_dependencies_c-1.0.0.tar.gz#sha256=c03742ca6e81c2a5d7d8cb72d1214bf03b2925e63858a19097f17d3e1a750192", hash = "sha256:c03742ca6e81c2a5d7d8cb72d1214bf03b2925e63858a19097f17d3e1a750192" } wheels = [ @@ -1636,7 +1636,7 @@ fn fork_marker_inherit_transitive() -> Result<()> { "sys_platform == 'darwin'", ] dependencies = [ - { name = "package-b" }, + { name = "package-b", marker = "sys_platform == 'darwin'" }, ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_marker_inherit_transitive_a-1.0.0.tar.gz#sha256=8bcab85231487b9350471da0c4c22dc3d69dfe4a1198d16b5f81b0235d7112ce", hash = "sha256:8bcab85231487b9350471da0c4c22dc3d69dfe4a1198d16b5f81b0235d7112ce" } wheels = [ @@ -1660,7 +1660,7 @@ fn fork_marker_inherit_transitive() -> Result<()> { version = "1.0.0" source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } dependencies = [ - { name = "package-c" }, + { name = "package-c", marker = "sys_platform == 'darwin'" }, ] sdist = { url = "https://astral-sh.github.io/packse/PACKSE_VERSION/files/fork_marker_inherit_transitive_b-1.0.0.tar.gz#sha256=03b4b0e323c36bd4a1e51a65e1489715da231d44d26e12b54544e3bf9a9f6129", hash = "sha256:03b4b0e323c36bd4a1e51a65e1489715da231d44d26e12b54544e3bf9a9f6129" } wheels = [ @@ -2748,8 +2748,8 @@ fn preferences_dependent_forking() -> Result<()> { dependencies = [ { name = "package-bar" }, { name = "package-cleaver" }, - { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } }, - { name = "package-foo", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" } }, + { name = "package-foo", version = "1.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform == 'linux'" }, + { name = "package-foo", version = "2.0.0", source = { registry = "https://astral-sh.github.io/packse/PACKSE_VERSION/simple-html/" }, marker = "sys_platform != 'linux'" }, ] "### ); diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index ba901d067e53..847e1e2f393d 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -6612,7 +6612,7 @@ fn universal_conflicting() -> Result<()> { # 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 ; (sys_platform == 'darwin' or sys_platform == 'win32') and ((implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')) # via cffi sniffio==1.3.1 ; sys_platform == 'darwin' or sys_platform == 'win32' # via trio @@ -6922,11 +6922,11 @@ fn universal_transitive_disjoint_locals() -> Result<()> { # via torchvision sympy==1.12 # via torch - torch==2.0.0+cpu + torch==2.0.0+cpu ; platform_machine != 'x86_64' # via # -r requirements.in # torchvision - torch==2.0.0+cu118 + torch==2.0.0+cu118 ; platform_machine == 'x86_64' # via # -r requirements.in # torchvision @@ -7145,11 +7145,11 @@ fn universal_disjoint_local_requirement() -> Result<()> { # via torch sympy==1.12 # via torch - torch==2.0.0+cpu + torch==2.0.0+cpu ; platform_machine != 'x86_64' # via # -r requirements.in # example - torch==2.0.0+cu118 + torch==2.0.0+cu118 ; platform_machine == 'x86_64' # via # -r requirements.in # example @@ -7204,7 +7204,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { ----- stdout ----- # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal - cmake==3.28.4 ; platform_machine == 'x86_64' and platform_system == 'Linux' + cmake==3.28.4 ; python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' # via triton . # via -r requirements.in @@ -7214,7 +7214,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { # triton jinja2==3.1.3 # via torch - lit==18.1.2 ; platform_machine == 'x86_64' and platform_system == 'Linux' + lit==18.1.2 ; python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' # via triton markupsafe==2.1.5 # via jinja2 @@ -7228,12 +7228,12 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> { # via # -r requirements.in # example - torch==2.0.0+cu118 + torch==2.0.0+cu118 ; python_version <= '3.12' # via # -r requirements.in # example # triton - triton==2.0.0 ; platform_machine == 'x86_64' and platform_system == 'Linux' + triton==2.0.0 ; python_version <= '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux' # via torch typing-extensions==4.10.0 # via torch @@ -7357,7 +7357,7 @@ fn universal_nested_overlapping_local_requirement() -> Result<()> { # uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal cmake==3.28.4 ; platform_machine == 'x86_64' and platform_system == 'Linux' # via triton - . ; (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') + . ; os_name == 'Linux' # via -r requirements.in filelock==3.13.1 # via @@ -7444,7 +7444,7 @@ fn universal_nested_disjoint_local_requirement() -> Result<()> { # via triton . ; os_name == 'Linux' # via -r requirements.in - filelock==3.13.1 + filelock==3.13.1 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine == 'x86_64' and platform_system == 'Linux') or (os_name == 'Linux' and platform_machine != 'x86_64') # via # torch # triton @@ -7452,17 +7452,17 @@ fn universal_nested_disjoint_local_requirement() -> Result<()> { # via torch intel-openmp==2021.4.0 ; os_name != 'Linux' and platform_system == 'Windows' # via mkl - jinja2==3.1.3 + jinja2==3.1.3 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via torch lit==18.1.2 ; os_name == 'Linux' and platform_machine == 'x86_64' and platform_system == 'Linux' # via triton - markupsafe==2.1.5 + markupsafe==2.1.5 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via jinja2 mkl==2021.4.0 ; os_name != 'Linux' and platform_system == 'Windows' # via torch - mpmath==1.3.0 + mpmath==1.3.0 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via sympy - networkx==3.2.1 + networkx==3.2.1 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via torch nvidia-cublas-cu12==12.1.3.1 ; os_name != 'Linux' and platform_machine == 'x86_64' and platform_system == 'Linux' # via @@ -7495,7 +7495,7 @@ fn universal_nested_disjoint_local_requirement() -> Result<()> { # nvidia-cusparse-cu12 nvidia-nvtx-cu12==12.1.105 ; os_name != 'Linux' and platform_machine == 'x86_64' and platform_system == 'Linux' # via torch - sympy==1.12 + sympy==1.12 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via torch tbb==2021.11.0 ; os_name != 'Linux' and platform_system == 'Windows' # via mkl @@ -7512,7 +7512,7 @@ fn universal_nested_disjoint_local_requirement() -> Result<()> { # via -r requirements.in triton==2.0.0 ; os_name == 'Linux' and platform_machine == 'x86_64' and platform_system == 'Linux' # via torch - typing-extensions==4.10.0 + typing-extensions==4.10.0 ; os_name != 'Linux' or (os_name == 'Linux' and platform_machine == 'x86_64') or (os_name == 'Linux' and platform_machine != 'x86_64') # via torch ----- stderr ----- @@ -7726,11 +7726,11 @@ fn universal_disjoint_prerelease_requirement() -> Result<()> { ----- stdout ----- # This file was autogenerated by uv via the following command: # uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal - cffi==1.15.0 + cffi==1.15.0 ; os_name != 'Linux' # via # -r requirements.in # example - cffi==1.17.0rc1 + cffi==1.17.0rc1 ; os_name == 'Linux' # via # -r requirements.in # example