From 5fc7fc49ce2be4a0eae05f7bebea271fbbfae856 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 3 Oct 2024 18:52:48 +0100 Subject: [PATCH] Respect project upper bounds when filtering wheels on requires-python --- crates/uv-resolver/src/requires_python.rs | 132 +++++++++++++++++++--- crates/uv/tests/lock.rs | 41 +------ 2 files changed, 117 insertions(+), 56 deletions(-) diff --git a/crates/uv-resolver/src/requires_python.rs b/crates/uv-resolver/src/requires_python.rs index fcd3a19f3170e..3ecf7c446ca61 100644 --- a/crates/uv-resolver/src/requires_python.rs +++ b/crates/uv-resolver/src/requires_python.rs @@ -361,22 +361,48 @@ impl RequiresPython { return false; } - // Remove (e.g.) `cp36-none-any` if the specifier is `==3.10.*`. - let Some(minor) = python_tag - .strip_prefix("cp3") - .or_else(|| python_tag.strip_prefix("pp3")) - else { - // We also return true for bounds such as `py36`, where the Python version - // is a lower bound (redundant with `requires-python`) + // Remove (e.g.) `py312-none-any` if the specifier is `==3.10.*`. However, + // `py37-none-any` would be fine, since the `3.7` represents a lower bound. + if let Some(minor) = python_tag.strip_prefix("py3") { + let Ok(minor) = minor.parse::() else { + return true; + }; + + // Ex) If the wheel bound is `3.12`, then it doesn't match `==3.10.*`. + let wheel_bound = UpperBound(Bound::Excluded(Version::new([3, minor + 1]))); + if wheel_bound > self.range.upper().major_minor() { + return false; + } + return true; }; - let Ok(minor) = minor.parse::() else { + + // Remove (e.g.) `cp36-none-any` or `cp312-none-any` if the specifier is + // `==3.10.*`, since these tags require an exact match. + if let Some(minor) = python_tag + .strip_prefix("cp3") + .or_else(|| python_tag.strip_prefix("pp3")) + { + let Ok(minor) = minor.parse::() else { + return true; + }; + + // Ex) If the wheel bound is `3.6`, then it doesn't match `>=3.10`. + let wheel_bound = LowerBound(Bound::Included(Version::new([3, minor]))); + if wheel_bound < self.range.lower().major_minor() { + return false; + } + + let wheel_bound = UpperBound(Bound::Excluded(Version::new([3, minor + 1]))); + if wheel_bound > self.range.upper().major_minor() { + return false; + } + return true; - }; + } - // Ex) If the wheel bound is `3.6`, then it doesn't match `>=3.10`. - let wheel_bound = LowerBound(Bound::Included(Version::new([3, minor]))); - wheel_bound >= self.bound_major_minor() + // Unknown tags are allowed. + true }) } else if abi_tag.starts_with("cp2") || abi_tag.starts_with("pypy2") { // Python 2 is never allowed. @@ -389,8 +415,19 @@ impl RequiresPython { return true; }; + // Ex) If the wheel bound is `3.6`, then it doesn't match `>=3.10`. let wheel_bound = LowerBound(Bound::Included(Version::new([3, minor]))); - wheel_bound >= self.bound_major_minor() + if wheel_bound < self.range.lower().major_minor() { + return false; + } + + // Ex) If the wheel bound is `3.12`, then it doesn't match `==3.10.*`. + let wheel_bound = UpperBound(Bound::Excluded(Version::new([3, minor + 1]))); + if wheel_bound > self.range.upper().major_minor() { + return false; + } + + true } else if let Some(minor_no_dot_abi) = abi_tag.strip_prefix("pypy3") { // Given `pypy39_pp73`, we just removed `pypy3`, now we remove `_pp73` ... let Some((minor_not_dot, _)) = minor_no_dot_abi.split_once('_') else { @@ -403,10 +440,21 @@ impl RequiresPython { return true; }; + // Ex) If the wheel bound is `3.6`, then it doesn't match `>=3.10`. let wheel_bound = LowerBound(Bound::Included(Version::new([3, minor]))); - wheel_bound >= self.bound_major_minor() + if wheel_bound < self.range.lower().major_minor() { + return false; + } + + // Ex) If the wheel bound is `3.12`, then it doesn't match `==3.10.*`. + let wheel_bound = UpperBound(Bound::Excluded(Version::new([3, minor + 1]))); + if wheel_bound > self.range.upper().major_minor() { + return false; + } + + true } else { - // Unknown python tag -> allowed. + // Unknown tags are allowed. true } }) @@ -519,6 +567,25 @@ impl SimplifiedMarkerTree { #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct LowerBound(Bound); +impl LowerBound { + /// Return the [`LowerBound`] truncated to the major and minor version. + fn major_minor(&self) -> Self { + match &self.0 { + // Ex) `>=3.10.1` -> `>=3.10` (and `>=3.10.0` is `>=3.10`) + Bound::Included(version) => Self(Bound::Included(Version::new( + version.release().iter().take(2), + ))), + // Ex) `>3.10.1` -> `>=3.10`. + // This is unintuitive, but `>3.10.1` does indicate that _some_ version of Python 3.10 + // is supported. + Bound::Excluded(version) => Self(Bound::Included(Version::new( + version.release().iter().take(2), + ))), + Bound::Unbounded => Self(Bound::Unbounded), + } + } +} + impl PartialOrd for LowerBound { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -615,6 +682,35 @@ impl From for Bound { #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct UpperBound(Bound); +impl UpperBound { + /// Return the [`UpperBound`] truncated to the major and minor version. + fn major_minor(&self) -> Self { + match &self.0 { + // Ex) `<=3.10.1` -> `<3.11` (but `<=3.10.0` is `<=3.10`) + Bound::Included(version) => { + let major = version.release().first().copied().unwrap_or(3); + let minor = version.release().get(1).copied().unwrap_or(0); + if version.release().get(2).is_some_and(|patch| *patch > 0) { + Self(Bound::Excluded(Version::new([major, minor + 1]))) + } else { + Self(Bound::Included(Version::new([major, minor]))) + } + } + // Ex) `<3.10.1` -> `<3.11` (but `<3.10.0` is `<3.10`) + Bound::Excluded(version) => { + let major = version.release().first().copied().unwrap_or(3); + let minor = version.release().get(1).copied().unwrap_or(0); + if version.release().get(2).is_some_and(|patch| *patch > 0) { + Self(Bound::Excluded(Version::new([major, minor + 1]))) + } else { + Self(Bound::Excluded(Version::new([major, minor]))) + } + } + Bound::Unbounded => Self(Bound::Unbounded), + } + } +} + impl PartialOrd for UpperBound { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -727,8 +823,9 @@ mod tests { "black-24.4.2-cp310-cp310-win_amd64.whl", "black-24.4.2-cp310-none-win_amd64.whl", "cbor2-5.6.4-py3-none-any.whl", - "dearpygui-1.11.1-cp312-cp312-win_amd64.whl", "solace_pubsubplus-1.8.0-py36-none-manylinux_2_12_x86_64.whl", + "torch-1.10.0-py310-none-macosx_10_9_x86_64.whl", + "torch-1.10.0-py37-none-macosx_10_9_x86_64.whl", "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", ]; for wheel_name in wheel_names { @@ -756,10 +853,13 @@ mod tests { let wheel_names = &[ "PySocks-1.7.1-py27-none-any.whl", "black-24.4.2-cp39-cp39-win_amd64.whl", + "dearpygui-1.11.1-cp312-cp312-win_amd64.whl", "psutil-6.0.0-cp27-none-win32.whl", "psutil-6.0.0-cp36-cp36m-win32.whl", "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", + "torch-1.10.0-cp311-none-macosx_10_9_x86_64.whl", "torch-1.10.0-cp36-none-macosx_10_9_x86_64.whl", + "torch-1.10.0-py311-none-macosx_10_9_x86_64.whl", ]; for wheel_name in wheel_names { assert!( diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index fe5090feb35f4..6c091ae8ea8a5 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -3474,30 +3474,6 @@ fn lock_requires_python_upper() -> Result<()> { { url = "https://files.pythonhosted.org/packages/4c/5b/fb37fe341344d9651f5c5f579639cd97d50a457dc53901aa8f7e9f28beb9/pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b", size = 2109044 }, { url = "https://files.pythonhosted.org/packages/70/1a/6f7278802dbc66716661618807ab0dfa4fc32b09d1235923bbbe8b3a5757/pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a", size = 1708265 }, { url = "https://files.pythonhosted.org/packages/35/7f/58758c42c61b0bdd585158586fecea295523d49933cb33664ea888162daf/pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2", size = 1901750 }, - { url = "https://files.pythonhosted.org/packages/6f/47/ef0d60ae23c41aced42921728650460dc831a0adf604bfa66b76028cb4d0/pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231", size = 1839225 }, - { url = "https://files.pythonhosted.org/packages/6a/23/430f2878c9cd977a61bb39f71751d9310ec55cee36b3d5bf1752c6341fd0/pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9", size = 1768604 }, - { url = "https://files.pythonhosted.org/packages/9e/2b/ec4e7225dee79e0dc80ccc3c35ab33cc2c4bbb8a1a7ecf060e5e453651ec/pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f", size = 1789767 }, - { url = "https://files.pythonhosted.org/packages/64/b0/38b24a1fa6d2f96af3148362e10737ec073768cd44d3ec21dca3be40a519/pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52", size = 1772061 }, - { url = "https://files.pythonhosted.org/packages/5e/da/bb73274c42cb60decfa61e9eb0c9029da78b3b9af0a9de0309dbc8ff87b6/pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237", size = 1974573 }, - { url = "https://files.pythonhosted.org/packages/c8/65/41693110fb3552556180460daffdb8bbeefb87fc026fd9aa4b849374015c/pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe", size = 2625596 }, - { url = "https://files.pythonhosted.org/packages/09/b3/a5a54b47cccd1ab661ed5775235c5e06924753c2d4817737c5667bfa19a8/pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e", size = 2099064 }, - { url = "https://files.pythonhosted.org/packages/52/fa/443a7a6ea54beaba45ff3a59f3d3e6e3004b7460bcfb0be77bcf98719d3b/pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24", size = 1900345 }, - { url = "https://files.pythonhosted.org/packages/8e/e6/9aca9ffae60f9cdf0183069de3e271889b628d0fb175913fcb3db5618fb1/pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1", size = 1968252 }, - { url = "https://files.pythonhosted.org/packages/46/5e/6c716810ea20a6419188992973a73c2fb4eb99cd382368d0637ddb6d3c99/pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd", size = 2119191 }, - { url = "https://files.pythonhosted.org/packages/06/fc/6123b00a9240fbb9ae0babad7a005d51103d9a5d39c957a986f5cdd0c271/pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688", size = 1717788 }, - { url = "https://files.pythonhosted.org/packages/d5/36/e61ad5a46607a469e2786f398cd671ebafcd9fb17f09a2359985c7228df5/pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d", size = 1898188 }, - { url = "https://files.pythonhosted.org/packages/49/75/40b0e98b658fdba02a693b3bacb4c875a28bba87796c7b13975976597d8c/pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686", size = 1838688 }, - { url = "https://files.pythonhosted.org/packages/75/02/d8ba2d4a266591a6a623c68b331b96523d4b62ab82a951794e3ed8907390/pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a", size = 1768409 }, - { url = "https://files.pythonhosted.org/packages/91/ae/25ecd9bc4ce4993e99a1a3c9ab111c082630c914260e129572fafed4ecc2/pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b", size = 1789317 }, - { url = "https://files.pythonhosted.org/packages/7a/80/72057580681cdbe55699c367963d9c661b569a1d39338b4f6239faf36cdc/pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19", size = 1771949 }, - { url = "https://files.pythonhosted.org/packages/a2/be/d9bbabc55b05019013180f141fcaf3b14dbe15ca7da550e95b60c321009a/pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac", size = 1974392 }, - { url = "https://files.pythonhosted.org/packages/79/2d/7bcd938c6afb0f40293283f5f09988b61fb0a4f1d180abe7c23a2f665f8e/pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703", size = 2625565 }, - { url = "https://files.pythonhosted.org/packages/ac/88/ca758e979457096008a4b16a064509028e3e092a1e85a5ed6c18ced8da88/pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c", size = 2098784 }, - { url = "https://files.pythonhosted.org/packages/eb/de/2fad6d63c3c42e472e985acb12ec45b7f56e42e6f4cd6dfbc5e87ee8678c/pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83", size = 1900198 }, - { url = "https://files.pythonhosted.org/packages/fe/50/077c7f35b6488dc369a6d22993af3a37901e198630f38ac43391ca730f5b/pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203", size = 1968005 }, - { url = "https://files.pythonhosted.org/packages/5d/1f/f378631574ead46d636b9a04a80ff878b9365d4b361b1905ef1667d4182a/pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0", size = 2118920 }, - { url = "https://files.pythonhosted.org/packages/7a/ea/e4943f17df7a3031d709481fe4363d4624ae875a6409aec34c28c9e6cf59/pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e", size = 1717397 }, - { url = "https://files.pythonhosted.org/packages/13/63/b95781763e8d84207025071c0cec16d921c0163c7a9033ae4b9a0e020dc7/pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20", size = 1898013 }, ] [[package]] @@ -3690,21 +3666,6 @@ fn lock_requires_python_wheels() -> Result<()> { { url = "https://files.pythonhosted.org/packages/db/1b/6a5b970e55dffc1a7d0bb54f57b184b2a2a2ad0b7bca16a97ca26d73c5b5/frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", size = 272292 }, { url = "https://files.pythonhosted.org/packages/1a/05/ebad68130e6b6eb9b287dacad08ea357c33849c74550c015b355b75cc714/frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", size = 44446 }, { url = "https://files.pythonhosted.org/packages/b3/21/c5aaffac47fd305d69df46cfbf118768cdf049a92ee6b0b5cb029d449dcf/frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", size = 50459 }, - { url = "https://files.pythonhosted.org/packages/b4/db/4cf37556a735bcdb2582f2c3fa286aefde2322f92d3141e087b8aeb27177/frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", size = 93937 }, - { url = "https://files.pythonhosted.org/packages/46/03/69eb64642ca8c05f30aa5931d6c55e50b43d0cd13256fdd01510a1f85221/frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", size = 53656 }, - { url = "https://files.pythonhosted.org/packages/3f/ab/c543c13824a615955f57e082c8a5ee122d2d5368e80084f2834e6f4feced/frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", size = 51868 }, - { url = "https://files.pythonhosted.org/packages/a9/b8/438cfd92be2a124da8259b13409224d9b19ef8f5a5b2507174fc7e7ea18f/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", size = 280652 }, - { url = "https://files.pythonhosted.org/packages/54/72/716a955521b97a25d48315c6c3653f981041ce7a17ff79f701298195bca3/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", size = 286739 }, - { url = "https://files.pythonhosted.org/packages/65/d8/934c08103637567084568e4d5b4219c1016c60b4d29353b1a5b3587827d6/frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", size = 289447 }, - { url = "https://files.pythonhosted.org/packages/70/bb/d3b98d83ec6ef88f9bd63d77104a305d68a146fd63a683569ea44c3085f6/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", size = 265466 }, - { url = "https://files.pythonhosted.org/packages/0b/f2/b8158a0f06faefec33f4dff6345a575c18095a44e52d4f10c678c137d0e0/frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", size = 281530 }, - { url = "https://files.pythonhosted.org/packages/ea/a2/20882c251e61be653764038ece62029bfb34bd5b842724fff32a5b7a2894/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", size = 281295 }, - { url = "https://files.pythonhosted.org/packages/4c/f9/8894c05dc927af2a09663bdf31914d4fb5501653f240a5bbaf1e88cab1d3/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", size = 268054 }, - { url = "https://files.pythonhosted.org/packages/37/ff/a613e58452b60166507d731812f3be253eb1229808e59980f0405d1eafbf/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", size = 286904 }, - { url = "https://files.pythonhosted.org/packages/cc/6e/0091d785187f4c2020d5245796d04213f2261ad097e0c1cf35c44317d517/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", size = 290754 }, - { url = "https://files.pythonhosted.org/packages/a5/c2/e42ad54bae8bcffee22d1e12a8ee6c7717f7d5b5019261a8c861854f4776/frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", size = 282602 }, - { url = "https://files.pythonhosted.org/packages/b6/61/56bad8cb94f0357c4bc134acc30822e90e203b5cb8ff82179947de90c17f/frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", size = 44063 }, - { url = "https://files.pythonhosted.org/packages/3e/dc/96647994a013bc72f3d453abab18340b7f5e222b7b7291e3697ca1fcfbd5/frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", size = 50452 }, { url = "https://files.pythonhosted.org/packages/83/10/466fe96dae1bff622021ee687f68e5524d6392b0a2f80d05001cd3a451ba/frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", size = 11552 }, ] @@ -3716,7 +3677,7 @@ fn lock_requires_python_wheels() -> Result<()> { { name = "frozenlist" }, ] - [package.metadata] + [package.metadata]` requires-dist = [{ name = "frozenlist" }] "### );