From 9d1c18d70769f982ed0a654dcc09154a4f62b8b8 Mon Sep 17 00:00:00 2001 From: Branch Vincent Date: Tue, 10 Jun 2025 22:54:14 -0700 Subject: [PATCH] fix: support a SOURCE_DATE_EPOCH prior to 1980 --- src/pdm/backend/wheel.py | 5 ++--- tests/test_api.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/pdm/backend/wheel.py b/src/pdm/backend/wheel.py index 6cd743c..7828ffd 100644 --- a/src/pdm/backend/wheel.py +++ b/src/pdm/backend/wheel.py @@ -48,9 +48,8 @@ except (ValueError, KeyError): ZIPINFO_DATE_TIME = (2016, 1, 1, 0, 0, 0) else: - if _env_date[0] < 1980: - raise ValueError("zipinfo date can't be earlier than 1980") - ZIPINFO_DATE_TIME = _env_date + # `zipfile.ZipInfo` does not support timestamps before 1980 + ZIPINFO_DATE_TIME = max(_env_date, (1980, 1, 1, 0, 0, 0)) def _open_for_write(path: str | Path) -> IO[str]: diff --git a/tests/test_api.py b/tests/test_api.py index 91d5a90..6198a29 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import email +import importlib import os import sys import tarfile @@ -404,6 +407,31 @@ def test_build_wheel_preserve_permission(dist: Path) -> None: assert filemode & 0o111 +@pytest.mark.parametrize("name", ["demo-package"]) +@pytest.mark.parametrize( + ("epoch", "expected_date_time"), + [ + ("0", (1980, 1, 1, 0, 0, 0)), + ("nan", (2016, 1, 1, 0, 0, 0)), + ("1580601700", (2020, 2, 2, 0, 1, 40)), + ], +) +def test_build_wheel_respects_source_date_epoch( + monkeypatch: pytest.MonkeyPatch, + dist: Path, + epoch: str, + expected_date_time: tuple[int, ...], +) -> None: + monkeypatch.setenv("SOURCE_DATE_EPOCH", epoch) + from pdm.backend import wheel + + importlib.reload(wheel) + wheel_name = api.build_wheel(dist.as_posix()) + with zipfile.ZipFile(dist / wheel_name) as zf: + zip_info = zf.getinfo("demo_package-0.1.0.dist-info/WHEEL") + assert zip_info.date_time == expected_date_time + + @pytest.mark.usefixtures("scm") @pytest.mark.parametrize("name", ["demo-using-scm"]) def test_build_wheel_write_version_to_file(fixture_project: Path, dist) -> None: