From dbd9afce389fb69af65db40711fa158f6057d3aa Mon Sep 17 00:00:00 2001 From: Justin Larkin Date: Tue, 15 Sep 2026 09:58:07 -0400 Subject: [PATCH 1/2] fix(sources): normalize sdist filenames per PEP 625 The default_build_sdist function was constructing sdist filenames using req.name directly, which could contain uppercase letters, dots, or hyphens that were not normalized per PEP 625. This caused filenames to disagree with upstream artifacts and broke filename-keyed comparison operations. Apply PEP 503 canonicalization (lowercase, replace [._-] with _) when constructing sdist filenames, ensuring compliance with PEP 625. Fixes #1317 Co-Authored-By: Claude Haiku 4.5 Signed-off-by: Justin Larkin --- src/fromager/sources.py | 3 ++- tests/test_sources.py | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/fromager/sources.py b/src/fromager/sources.py index 534573d4..da7cc592 100644 --- a/src/fromager/sources.py +++ b/src/fromager/sources.py @@ -13,6 +13,7 @@ import resolvelib from packaging.requirements import Requirement from packaging.utils import ( + canonicalize_name, parse_sdist_filename, ) from packaging.version import Version @@ -533,7 +534,7 @@ def default_build_sdist( # # For cases where the PEP 517 approach works, use # pep517_build_sdist(). - sdist_filename = ctx.sdists_builds / f"{req.name}-{version}.tar.gz" + sdist_filename = ctx.sdists_builds / f"{canonicalize_name(req.name).replace('-', '_')}-{version}.tar.gz" if sdist_filename.exists(): sdist_filename.unlink() ensure_pkg_info( diff --git a/tests/test_sources.py b/tests/test_sources.py index 1ed0904b..c5f9e3d4 100644 --- a/tests/test_sources.py +++ b/tests/test_sources.py @@ -742,3 +742,47 @@ def test_build_sdist_raises_wrong_directory( sdist_root_dir=tmp_path / "src", build_env=build_env, ) + + +@pytest.mark.parametrize( + "req_name,expected_filename_part", + [ + ("colpali-engine", "colpali_engine"), # dashes -> underscores + ("Colpali-Engine", "colpali_engine"), # case-insensitive + normalization + ("Cython", "cython"), # case-insensitive + ("oslo.messaging", "oslo_messaging"), # dots -> underscores + ("ruamel-yaml", "ruamel_yaml"), # dashes -> underscores + ], +) +def test_default_build_sdist_normalizes_filename( + req_name: str, + expected_filename_part: str, + tmp_context: context.WorkContext, + tmp_path: pathlib.Path, +) -> None: + """Test that default_build_sdist creates normalized PEP 625 filenames.""" + req = Requirement(f"{req_name}==1.0.0") + version = Version("1.0.0") + sdist_root_dir = tmp_path / "src" + sdist_root_dir.mkdir(parents=True) + + build_env = Mock() + + with patch("fromager.packagesettings.get_extra_environ", return_value={}): + with patch("fromager.sources.ensure_pkg_info"): + with patch("fromager.sources.tarballs.tar_reproducible"): + # Call default_build_sdist + sdist_file = sources.default_build_sdist( + ctx=tmp_context, + extra_environ={}, + req=req, + version=version, + sdist_root_dir=sdist_root_dir, + build_env=build_env, + build_dir=sdist_root_dir, + ) + + # Verify the filename is normalized according to PEP 625 + expected_filename = f"{expected_filename_part}-1.0.0.tar.gz" + assert sdist_file.name == expected_filename + assert sdist_file.parent == tmp_context.sdists_builds From 358253c86713f49ca09743a0a132a2d8ccfb14a4 Mon Sep 17 00:00:00 2001 From: Justin Larkin Date: Thu, 17 Sep 2026 17:35:58 -0400 Subject: [PATCH 2/2] fix(sources): break long line to meet 88-character limit Extract the normalized package name to a variable to keep lines within the project's configured line length limit of 88 characters. Co-Authored-By: Claude Haiku 4.5 Signed-off-by: Justin Larkin --- src/fromager/sources.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fromager/sources.py b/src/fromager/sources.py index da7cc592..5409a181 100644 --- a/src/fromager/sources.py +++ b/src/fromager/sources.py @@ -534,7 +534,8 @@ def default_build_sdist( # # For cases where the PEP 517 approach works, use # pep517_build_sdist(). - sdist_filename = ctx.sdists_builds / f"{canonicalize_name(req.name).replace('-', '_')}-{version}.tar.gz" + normalized_name = canonicalize_name(req.name).replace("-", "_") + sdist_filename = ctx.sdists_builds / f"{normalized_name}-{version}.tar.gz" if sdist_filename.exists(): sdist_filename.unlink() ensure_pkg_info(