From 86c1dfd0ebc97e7b172d2697e20d0f6997f61b9e Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 13 May 2026 12:06:00 +0200 Subject: [PATCH 1/2] fix(sources): PEP 625 sdist name by default `default_download_source` now uses PEP 625-compatible sdist name instead of relying on remote URL file name. This solves a file conflict when multiple packages use the same remote sources. The file name is the normalized, lower-case package name with `-` replaced by `_`, e.g. `flit_core` instead of `flit-core` or `zope_interface` instead of `zope.interface`. Zip file support is incompatible with PEP 625. The package setting `download_source.destination_filename` can also define a PEP 625-incompatible file name. We should tackle these issues in the near future. - https://packaging.python.org/en/latest/specifications/source-distribution-format/ - https://peps.python.org/pep-0625/ Signed-off-by: Christian Heimes --- src/fromager/sources.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/fromager/sources.py b/src/fromager/sources.py index 996eb333..bd308adb 100644 --- a/src/fromager/sources.py +++ b/src/fromager/sources.py @@ -212,6 +212,15 @@ def default_download_source( url = pbi.download_source_url(version=version, default=download_url) if url is None: raise ValueError(f"Could not determine download URL for {req}") + if destination_filename is None: + url_filename = resolver.extract_filename_from_url(url) + if url_filename.endswith(".zip"): + destination_filename = f"{pbi.override_module_name}-{version}.zip" + else: + destination_filename = f"{pbi.override_module_name}-{version}.tar.gz" + logger.debug( + "config has no destination_filename, use default %r", destination_filename + ) source_filename = _download_source_check( req=req, destination_dir=sdists_downloads_dir, From 9e4b6e1037211d8289b2e1c37bde16031aa5a5c1 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 14 May 2026 06:56:10 -0400 Subject: [PATCH 2/2] test(sources): add tests for PEP 625 default sdist filename Verify that when no destination_filename is configured, the sdist gets a PEP 625 normalized name from override_module_name instead of the remote URL basename. Also verify that .zip extension is preserved. Co-Authored-By: Claude Signed-off-by: Ryan Petrello --- tests/test_sources.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test_sources.py b/tests/test_sources.py index 19ad7f06..57f18478 100644 --- a/tests/test_sources.py +++ b/tests/test_sources.py @@ -166,6 +166,48 @@ def test_patch_sources_apply_only_unversioned( apply_patch.assert_called_once_with(req, unversioned_patch_file, source_root_dir) +@pytest.mark.parametrize( + "pkg,version_str,url,expected_filename", + [ + ( + "mlserver-sklearn==1.6.0", + "1.6.0", + "https://github.test/SeldonIO/MLServer/archive/refs/tags/1.6.0.tar.gz", + "mlserver_sklearn-1.6.0.tar.gz", + ), + ( + "some-pkg==2.0", + "2.0", + "https://github.test/owner/repo/archive/refs/tags/v2.0.zip", + "some_pkg-2.0.zip", + ), + ], +) +@patch("fromager.sources._download_source_check") +def test_default_download_source_no_destination_filename( + download_source_check: Mock, + tmp_context: context.WorkContext, + pkg: str, + version_str: str, + url: str, + expected_filename: str, +) -> None: + """When no destination_filename is configured, use PEP 625 normalized name.""" + req = Requirement(pkg) + version = Version(version_str) + + sources.default_download_source( + tmp_context, req, version, url, tmp_context.sdists_downloads + ) + + download_source_check.assert_called_with( + req=req, + destination_dir=tmp_context.sdists_downloads, + url=url, + destination_filename=expected_filename, + ) + + @patch("fromager.sources.vendor_rust.vendor_rust") @patch("fromager.sources.pyproject.apply_project_override") @patch("fromager.sources.patch_source")