diff --git a/esphome/external_files.py b/esphome/external_files.py index 4627a0aed77..16821a10168 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -88,7 +88,9 @@ def _write_etag(local_file_path: Path, etag: str | None) -> None: ) -def has_remote_file_changed(url: str, local_file_path: Path) -> bool: +def has_remote_file_changed( + url: str, local_file_path: Path, timeout: int = NETWORK_TIMEOUT +) -> bool: if local_file_path.exists(): _LOGGER.debug("has_remote_file_changed: File exists at %s", local_file_path) try: @@ -104,7 +106,7 @@ def has_remote_file_changed(url: str, local_file_path: Path) -> bool: if etag := _read_etag(local_file_path): headers[IF_NONE_MATCH] = etag response = requests.head( - url, headers=headers, timeout=NETWORK_TIMEOUT, allow_redirects=True + url, headers=headers, timeout=timeout, allow_redirects=True ) _LOGGER.debug( @@ -156,7 +158,7 @@ def download_content(url: str, path: Path, timeout: int = NETWORK_TIMEOUT) -> by if CORE.skip_external_update and path.exists(): _LOGGER.debug("Skipping update for %s (refresh disabled)", url) return path.read_bytes() - if not has_remote_file_changed(url, path): + if not has_remote_file_changed(url, path, timeout): _LOGGER.debug("Remote file has not changed %s", url) return path.read_bytes() @@ -224,15 +226,17 @@ def download_content_many( path, url = next(iter(seen.items())) download_content(url, path, timeout) return + + def _download_one(path_url: tuple[Path, str]) -> None: + # `seen` stores entries as (path, url) so the dict can dedupe by + # path; flip them back to download_content's (url, path) order. + path, url = path_url + download_content(url, path, timeout) + workers = max(1, min(max_workers, len(seen))) with ThreadPoolExecutor(max_workers=workers) as ex: # list() forces iteration so exceptions surface here, not silently. - list( - ex.map( - lambda item: download_content(item[1], item[0], timeout), - seen.items(), - ) - ) + list(ex.map(_download_one, seen.items())) # Each component that uses external_files defines its own local