Address Copilot review on PR #16021

- download_content_many now de-duplicates by `path` so two callers
  asking for the same cache file (e.g. the same URL referenced twice
  in a config) can't race on download_content's non-atomic write. When
  duplicates are present, the first-seen URL for that path wins.
- Clamp `max_workers` to at least 1 so an invalid caller value can't
  raise ValueError out of ThreadPoolExecutor.
This commit is contained in:
J. Nick Koston
2026-04-26 09:55:27 -05:00
parent 54493faafc
commit a877acf1d1
2 changed files with 55 additions and 6 deletions
+36
View File
@@ -350,6 +350,42 @@ def test_download_content_many_propagates_errors(
external_files.download_content_many(items)
@patch("esphome.external_files.download_content")
def test_download_content_many_dedupes_by_path(
mock_download: MagicMock, setup_core: Path
) -> None:
"""Two items pointing at the same cache path must collapse to one
download -- otherwise concurrent writes race on the same file.
"""
path = setup_core / "shared"
items = [
("https://example.com/a", path),
("https://example.com/b", path),
("https://example.com/a", path),
]
external_files.download_content_many(items)
assert mock_download.call_count == 1
# First-seen URL wins, matching dict-insertion order.
args, _ = mock_download.call_args
assert args[0] == "https://example.com/a"
assert args[1] == path
@patch("esphome.external_files.download_content")
def test_download_content_many_clamps_invalid_max_workers(
mock_download: MagicMock, setup_core: Path
) -> None:
"""`max_workers <= 0` must not raise from ThreadPoolExecutor; it should
be clamped up to at least 1 worker.
"""
items = [
("https://example.com/a", setup_core / "a"),
("https://example.com/b", setup_core / "b"),
]
external_files.download_content_many(items, max_workers=0)
assert mock_download.call_count == 2
@patch("esphome.external_files.download_content_many")
def test_download_web_files_in_config_filters_and_dispatches(
mock_many: MagicMock, setup_core: Path