From 3ca65ffb0dbcfb7dfcc7372b8157bcd90f7f6f25 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 24 Aug 2026 12:32:38 -0500 Subject: [PATCH] Cover the file-like backoff tick, settle the batch worker return shape --- esphome/framework_helpers.py | 6 ++++-- tests/unit_tests/test_framework_helpers.py | 24 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/esphome/framework_helpers.py b/esphome/framework_helpers.py index 11d98986c9..2a2ce6dacf 100644 --- a/esphome/framework_helpers.py +++ b/esphome/framework_helpers.py @@ -782,8 +782,10 @@ def run_batch_downloads( # download error. with suppress(Exception): tracker(0) - return (name, err) - return None + failure = (name, err) + else: + failure = None + return failure ex = ThreadPoolExecutor(max_workers=max_workers) try: diff --git a/tests/unit_tests/test_framework_helpers.py b/tests/unit_tests/test_framework_helpers.py index fde56648b9..5916a2fd60 100644 --- a/tests/unit_tests/test_framework_helpers.py +++ b/tests/unit_tests/test_framework_helpers.py @@ -1241,8 +1241,6 @@ def test_logging_guard_ends_the_bar_row_before_a_record() -> None: def test_logging_guard_without_a_bar_is_a_no_op() -> None: """An unknown total draws no bar; the guard passes records through.""" - from esphome.framework_helpers import _BatchDownloadProgress - progress = _BatchDownloadProgress("Downloading", 0) with progress.logging_guard(): logging.getLogger("esphome.test").warning("plain record") @@ -1702,6 +1700,28 @@ class TestDownloadFromMirrors: assert mock_get.call_count == 2 mock_sleep.assert_called_once_with(2) + def test_backoff_tick_reports_filelike_bytes(self) -> None: + """For a file-like target the backoff tick carries f.tell(), so the + combined bar holds steady through the sweep retry.""" + target = io.BytesIO() + ticks: list[int] = [] + with ( + patch( + "requests.get", + side_effect=[ + req.ConnectionError("down"), + _mock_response(b"data"), + ], + ), + patch("esphome.framework_helpers._cancellable_sleep") as mock_sleep, + ): + download_from_mirrors( + ["https://mirror1.com/f"], {}, target, progress=ticks.append + ) + # No bytes had streamed at backoff time, so the tick carries 0 + assert mock_sleep.call_args == call(2, ticks.append, 0) + assert target.getvalue() == b"data" + def test_backoff_tick_reports_partial_bytes(self, tmp_path: Path) -> None: """The backoff tick carries the bytes already in the part file, so a combined bar holds steady instead of rewinding to zero."""