From ea3741eedc1e6c46239d7e01c6eaf5965c60bcb8 Mon Sep 17 00:00:00 2001 From: John Sirois Date: Tue, 7 Oct 2025 16:27:43 -0700 Subject: [PATCH 1/2] Fix generated WHEEL Tag metadata to be spec compliant. Fixes #2761 --- Changelog.md | 4 ++++ src/module_writer.rs | 46 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index a9e62278d..678c6fdbf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +* Fix generated WHEEL Tag metadata to be spec compliant. + ## [1.9.6] * Fix regressions to interpreter platform detection on Windows from 1.9.5 diff --git a/src/module_writer.rs b/src/module_writer.rs index 6fb407154..3adce005d 100644 --- a/src/module_writer.rs +++ b/src/module_writer.rs @@ -591,6 +591,13 @@ impl FileTracker { } } +fn expand_compressed_tag(tag: &str) -> impl Iterator + use<'_> { + tag.split('-') + .map(|component| component.split('.')) + .multi_cartesian_product() + .map(|components| components.join("-")) +} + fn wheel_file(tags: &[String]) -> Result { let mut wheel_file = format!( "Wheel-Version: 1.0 @@ -601,8 +608,20 @@ Root-Is-Purelib: false version = env!("CARGO_PKG_VERSION"), ); + // N.B.: Tags should be in expanded form in this metadata (See: + // https://packaging.python.org/en/latest/specifications/binary-distribution-format/#file-contents + // items 7 and 11); so we do that expansion here if needed. + // + // It might make sense to reify a Tag struct in the code base and then, when a compressed tag + // set needs to be rendered, render a single string at that time. As things stand though, this + // is the only place in the codebase that needs reified tags (compressed tag sets expanded); so + // we do the expansion here. + // + // See: https://github.com/PyO3/maturin/issues/2761 for tag in tags { - writeln!(wheel_file, "Tag: {tag}")?; + for expanded_tag in expand_compressed_tag(tag) { + writeln!(wheel_file, "Tag: {expanded_tag}")?; + } } Ok(wheel_file) @@ -1636,4 +1655,29 @@ mod tests { Ok(()) } + + #[test] + fn wheel_file_compressed_tags() -> Result<(), Box> { + let expected = format!( + "Wheel-Version: 1.0 +Generator: {name} ({version}) +Root-Is-Purelib: false +Tag: py2-none-any +Tag: py3-none-any +Tag: pre-expanded-tag +Tag: cp37-abi3-manylinux_2_17_x86_64 +Tag: cp37-abi3-manylinux2014_x86_64 +", + name = env!("CARGO_PKG_NAME"), + version = env!("CARGO_PKG_VERSION"), + ); + let actual = wheel_file(&[ + "py2.py3-none-any".to_string(), + "pre-expanded-tag".to_string(), + "cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64".to_string(), + ])?; + assert_eq!(expected, actual); + + Ok(()) + } } From 9a51a4e59b9336d1fb9565768f3125af9d942db8 Mon Sep 17 00:00:00 2001 From: John Sirois Date: Tue, 7 Oct 2025 16:55:42 -0700 Subject: [PATCH 2/2] Comply with 1.74.0 MSRV. --- src/module_writer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module_writer.rs b/src/module_writer.rs index 3adce005d..4b35581c4 100644 --- a/src/module_writer.rs +++ b/src/module_writer.rs @@ -591,7 +591,7 @@ impl FileTracker { } } -fn expand_compressed_tag(tag: &str) -> impl Iterator + use<'_> { +fn expand_compressed_tag(tag: &str) -> impl Iterator + '_ { tag.split('-') .map(|component| component.split('.')) .multi_cartesian_product()