From 2b64db994272d97807dbf9fe3b12df2d0eeabe49 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 27 Aug 2026 18:46:09 -0500 Subject: [PATCH] Announce size-less refetches and name every install failure --- esphome/platformio/registry.py | 8 +++- tests/unit_tests/test_platformio_registry.py | 43 +++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/esphome/platformio/registry.py b/esphome/platformio/registry.py index 01eb13196e..dc1f4441c5 100644 --- a/esphome/platformio/registry.py +++ b/esphome/platformio/registry.py @@ -196,7 +196,9 @@ def _batched_download_progress( def progress(done: int) -> None: nonlocal announced - if not announced and size and done < size: + # size-less registry entries still announce: streaming starts at + # done=0, while a verify no-op credits the full file in one tick + if not announced and done < (size or 1): _LOGGER.info("Re-downloading %s %s ...", name, version) announced = True extract_progress(0.0) @@ -419,5 +421,7 @@ def install_packages(specs: Collection[PackageSpec], downloads_dir: Path) -> Non max_workers=workers, ) if failures: - warn_batch_failures(failures[1:], "Could not install %s: %s") + # Warn on the first failure too: the raised exception's message may + # not name which package failed + warn_batch_failures(failures, "Could not install %s: %s") raise failures[0][1] diff --git a/tests/unit_tests/test_platformio_registry.py b/tests/unit_tests/test_platformio_registry.py index 03c5401ba5..e5023ca3f4 100644 --- a/tests/unit_tests/test_platformio_registry.py +++ b/tests/unit_tests/test_platformio_registry.py @@ -815,7 +815,10 @@ def test_install_packages_first_failure_reraised( registry.install_packages( [_spec("a", "1.0", tmp_path / "a"), _spec("b", "2.0", tmp_path / "b")], dl ) - assert "Could not install" in caplog.text + # Every failure is named, including the re-raised one: its exception + # message may not identify the package + assert "Could not install a" in caplog.text + assert "Could not install b" in caplog.text @contextmanager @@ -937,3 +940,41 @@ def test_install_package_batched_refetch_announced_once( progress(10) progress(20) assert caplog.text.count("Re-downloading pkg 1.0.0") == 1 + + +def test_install_package_batched_refetch_announced_without_size( + tmp_path: Path, caplog: pytest.LogCaptureFixture +) -> None: + """A size-less registry entry still announces its refetch on the first + streaming tick.""" + with ( + caplog.at_level(logging.INFO), + patch.object(registry, "download_with_resume") as mock_download, + patch.object(registry, "archive_extract_all") as mock_extract, + patch.object( + registry, + "registry_download", + return_value=("http://x/pkg.tar.gz", "abc123", None), + ), + ): + dest = tmp_path / "pkg" + (tmp_path / "dl").mkdir() + (tmp_path / "dl" / "pkg-1.0.0").write_bytes(b"x") + mock_extract.side_effect = lambda *_a, **_kw: (dest / "payload").mkdir( + parents=True + ) + registry.install_package( + "pkg", + "1.0.0", + dest, + [], + tmp_path / "dl", + expect=("payload",), + extract_progress=lambda _frac: None, + ) + progress = mock_download.call_args[1]["progress"] + # A verify no-op credits the whole (nonempty) file in one tick + progress(1) + assert "Re-downloading pkg 1.0.0" not in caplog.text + progress(0) + assert "Re-downloading pkg 1.0.0" in caplog.text