Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 55 additions & 13 deletions src/fromager/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,41 @@ def download_sdist(
return filepath


def _validate_wheel_with_local_version(filepath: pathlib.Path, basename: str) -> bool:
"""Check whether a wheel with a local version has valid dist-info under the base version.

Some third-party wheels name their dist-info directory using only the
public (base) version (e.g. ``pkg-1.0.dist-info``) while the wheel
filename carries a local segment (e.g. ``pkg-1.0+local``).
``wheelfile.WheelFile`` rejects these because it expects the directory
name to match the full filename version.

Returns ``True`` when the wheel has a local version **and** the
base-version dist-info directory contains both ``RECORD`` and
``METADATA``; ``False`` otherwise.
"""
_, version, _, _ = parse_wheel_filename(basename)
if not version.local:
return False

dist_name = basename.split("-", 1)[0]
base_dist_info = f"{dist_name}-{version.public}.dist-info"
with zipfile.ZipFile(filepath) as zf:
names = zf.namelist()
record_path = f"{base_dist_info}/RECORD"
metadata_path = f"{base_dist_info}/METADATA"
if record_path in names and metadata_path in names:
logger.warning(
"wheel %s has dist-info directory %s instead of expected %s-%s.dist-info",
basename,
base_dist_info,
dist_name,
version,
)
return True
return False


def download_wheel(
*,
destination_dir: pathlib.Path,
Expand All @@ -152,16 +187,16 @@ def download_wheel(
) -> pathlib.Path:
"""Download a wheel and verify it.

Validates that the filename is a valid wheel name (using
:func:`packaging.utils.parse_wheel_filename`) before downloading,
then checks that the zip archive is non-empty.

.. note::
Validates the filename with
:func:`packaging.utils.parse_wheel_filename`, downloads the file,
then opens it with :class:`wheel.wheelfile.WheelFile` to verify
that the dist-info directory and ``RECORD`` / ``METADATA`` files
exist.

The function does not validate dist-info ``METADATA`` and other
files described in the `binary distribution format
<https://packaging.python.org/en/latest/specifications/binary-distribution-format/>`_
specification.
When the wheel carries a local version segment in its filename but
the dist-info directory uses only the base version (a pattern seen
in some third-party builds), the strict ``WheelFile`` check is
relaxed via :func:`_validate_wheel_with_local_version`.

.. versionadded:: 0.90.0
"""
Expand All @@ -182,10 +217,17 @@ def download_wheel(
# NOTE: Does not validate that METADATA file is valid or consistent with
# wheel's distribution name and version.
# https://packaging.python.org/en/latest/specifications/binary-distribution-format/
with wheelfile.WheelFile(filepath) as wf:
di_metadata = f"{wf.dist_info_path}/METADATA"
if di_metadata not in wf.namelist():
raise wheelfile.WheelError(f"{di_metadata!r} missing")
try:
with wheelfile.WheelFile(filepath) as wf:
di_metadata = f"{wf.dist_info_path}/METADATA"
if di_metadata not in wf.namelist():
raise wheelfile.WheelError(f"{di_metadata!r} missing")
except wheelfile.WheelError:
# Some wheels omit the local version segment from the dist-info
# directory name (e.g. "pkg-1.0.dist-info" when the filename says
# "pkg-1.0+local"). Fall back to a manual check.
if not _validate_wheel_with_local_version(filepath, basename):
raise

return filepath

Expand Down
49 changes: 49 additions & 0 deletions tests/test_downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from wheel.wheelfile import WheelFile

from fromager.downloads import (
_validate_wheel_with_local_version,
download_git_source,
download_sdist,
download_url,
Expand Down Expand Up @@ -201,6 +202,54 @@ def test_download_wheel_missing_metadata(tmp_path: pathlib.Path) -> None:
)


def test_download_wheel_local_version_mismatch(tmp_path: pathlib.Path) -> None:
"""Wheel whose dist-info uses base version while filename has local."""
filename = "pkg-1.0+local123-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr(
"pkg-1.0.dist-info/METADATA",
"Metadata-Version: 1.0\nName: pkg\nVersion: 1.0+local123\n",
)
zf.writestr("pkg-1.0.dist-info/WHEEL", "Wheel-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
with _patch_download(f):
result = download_wheel(
destination_dir=tmp_path,
url=f"https://pkg.test/{filename}",
)
assert result == f


def test_validate_wheel_with_local_version_valid(tmp_path: pathlib.Path) -> None:
"""Fallback validation passes for a well-formed wheel with base-only dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is True


def test_validate_wheel_with_local_version_no_local(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when the filename has no local version."""
filename = "pkg-1.0-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is False


def test_validate_wheel_with_local_version_no_record(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when RECORD is missing from base-version dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
assert _validate_wheel_with_local_version(f, filename) is False
Comment on lines +224 to +250

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Missing test for absent METADATA in base-version dist-info.

There's a test for missing RECORD but not for missing METADATA. The implementation checks for both files, so this edge case should be covered.

🧪 Proposed test addition
 def test_validate_wheel_with_local_version_no_record(tmp_path: pathlib.Path) -> None:
     """Fallback returns False when RECORD is missing from base-version dist-info."""
     filename = "pkg-1.0+local-py3-none-any.whl"
     f = tmp_path / filename
     with zipfile.ZipFile(f, "w") as zf:
         zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
     assert _validate_wheel_with_local_version(f, filename) is False
+
+
+def test_validate_wheel_with_local_version_no_metadata(tmp_path: pathlib.Path) -> None:
+    """Fallback returns False when METADATA is missing from base-version dist-info."""
+    filename = "pkg-1.0+local-py3-none-any.whl"
+    f = tmp_path / filename
+    with zipfile.ZipFile(f, "w") as zf:
+        zf.writestr("pkg-1.0.dist-info/RECORD", "")
+    assert _validate_wheel_with_local_version(f, filename) is False
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_validate_wheel_with_local_version_valid(tmp_path: pathlib.Path) -> None:
"""Fallback validation passes for a well-formed wheel with base-only dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is True
def test_validate_wheel_with_local_version_no_local(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when the filename has no local version."""
filename = "pkg-1.0-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is False
def test_validate_wheel_with_local_version_no_record(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when RECORD is missing from base-version dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
assert _validate_wheel_with_local_version(f, filename) is False
def test_validate_wheel_with_local_version_valid(tmp_path: pathlib.Path) -> None:
"""Fallback validation passes for a well-formed wheel with base-only dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is True
def test_validate_wheel_with_local_version_no_local(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when the filename has no local version."""
filename = "pkg-1.0-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is False
def test_validate_wheel_with_local_version_no_record(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when RECORD is missing from base-version dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/METADATA", "Metadata-Version: 1.0\n")
assert _validate_wheel_with_local_version(f, filename) is False
def test_validate_wheel_with_local_version_no_metadata(tmp_path: pathlib.Path) -> None:
"""Fallback returns False when METADATA is missing from base-version dist-info."""
filename = "pkg-1.0+local-py3-none-any.whl"
f = tmp_path / filename
with zipfile.ZipFile(f, "w") as zf:
zf.writestr("pkg-1.0.dist-info/RECORD", "")
assert _validate_wheel_with_local_version(f, filename) is False
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_downloads.py` around lines 224 - 250, Add a test in
tests/test_downloads.py covering _validate_wheel_with_local_version when the
wheel has a local-version filename but the base-version dist-info is missing
METADATA; mirror the existing test_validate_wheel_with_local_version_no_record
setup, omit METADATA, and assert the helper returns False so both required
base-version files are exercised.

Source: Path instructions



# -- download_git_source ------------------------------------------------------

_MOCK_GIT_CLONE = "fromager.downloads.gitutils.git_clone_fast"
Expand Down
Loading