mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
Merge branch 'esp8266-native-ninja-emission' into esp8266-arduino-toolchain
This commit is contained in:
@@ -739,6 +739,15 @@ def normalize_dependencies(
|
||||
manifest_name,
|
||||
)
|
||||
continue
|
||||
if "version" in entry and not isinstance(entry["version"], str):
|
||||
# A container would raise from set.add(); an int fails
|
||||
# opaquely inside the registry resolution
|
||||
_LOGGER.warning(
|
||||
"Ignoring unrecognized dependency entry %r of %s",
|
||||
entry,
|
||||
manifest_name,
|
||||
)
|
||||
continue
|
||||
normalized.append(entry)
|
||||
return normalized
|
||||
if not isinstance(dependencies, (list, tuple)):
|
||||
@@ -761,6 +770,15 @@ def normalize_dependencies(
|
||||
manifest_name,
|
||||
)
|
||||
continue
|
||||
if "version" in entry and not isinstance(entry["version"], str):
|
||||
# A container would raise from set.add(); an int fails
|
||||
# opaquely inside the registry resolution
|
||||
_LOGGER.warning(
|
||||
"Ignoring unrecognized dependency entry %r of %s",
|
||||
entry,
|
||||
manifest_name,
|
||||
)
|
||||
continue
|
||||
normalized.append(entry)
|
||||
elif isinstance(entry, str) and entry:
|
||||
# PIO also accepts a bare list of names ("dependencies": ["Wire"])
|
||||
@@ -948,8 +966,12 @@ def _content_lengths(urls: list[str]) -> list[int]:
|
||||
def head(url: str) -> int:
|
||||
try:
|
||||
resp = requests.head(url, timeout=10, allow_redirects=True)
|
||||
if not resp.ok:
|
||||
_LOGGER.debug("HEAD %s returned %s", url, resp.status_code)
|
||||
return 0
|
||||
return int(resp.headers.get("content-length", 0))
|
||||
except Exception: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
except Exception as err: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
_LOGGER.debug("HEAD %s failed: %s", url, err)
|
||||
return 0
|
||||
|
||||
with ThreadPoolExecutor(max_workers=min(_DOWNLOAD_WORKERS, len(urls))) as ex:
|
||||
@@ -1000,16 +1022,19 @@ def _prefetch_wave(
|
||||
tracker = progress.tracker()
|
||||
try:
|
||||
component.download(salt=salt, namespace=namespace, progress=tracker)
|
||||
except Exception: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
except Exception as err: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
# The sequential call below retries and reports the failure
|
||||
_LOGGER.debug("Prefetch of %s failed: %s", component.name, err)
|
||||
tracker(0)
|
||||
|
||||
ex = ThreadPoolExecutor(max_workers=min(_DOWNLOAD_WORKERS, len(components)))
|
||||
try:
|
||||
with ThreadPoolExecutor(
|
||||
max_workers=min(_DOWNLOAD_WORKERS, len(components))
|
||||
) as ex:
|
||||
list(ex.map(_fetch, components))
|
||||
for future in [ex.submit(_fetch, component) for component in components]:
|
||||
future.result()
|
||||
finally:
|
||||
# On Ctrl-C drop the queued archives instead of downloading them
|
||||
# all before the process can exit; in-flight ones still finish.
|
||||
ex.shutdown(wait=True, cancel_futures=True)
|
||||
progress.done()
|
||||
|
||||
|
||||
|
||||
@@ -631,7 +631,7 @@ def test_lex_build_flags_dangling_flag_does_not_cross_entries(
|
||||
|
||||
|
||||
def test_prefetch_wave_downloads_registry_archives_in_parallel(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
setup_core, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Registry archives in one wave download concurrently, deduped by URL;
|
||||
git/local sources and failures are left to the sequential call."""
|
||||
@@ -670,12 +670,18 @@ def test_content_lengths_head_requests(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def fake_head(url, timeout, allow_redirects):
|
||||
if "bad" in url:
|
||||
raise requests.ConnectionError("down")
|
||||
return SimpleNamespace(headers={"content-length": "123"})
|
||||
if "gone" in url:
|
||||
return SimpleNamespace(ok=False, status_code=404, headers={})
|
||||
return SimpleNamespace(ok=True, headers={"content-length": "123"})
|
||||
|
||||
monkeypatch.setattr(
|
||||
lib.requests if hasattr(lib, "requests") else requests, "head", fake_head
|
||||
)
|
||||
assert lib._content_lengths(["https://x/a", "https://x/bad"]) == [123, 0]
|
||||
assert lib._content_lengths(["https://x/a", "https://x/bad", "https://x/gone"]) == [
|
||||
123,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
|
||||
|
||||
def test_prefetch_wave_cache_probe_failure_still_prefetches(
|
||||
@@ -766,6 +772,11 @@ def test_normalize_dependencies_forms(caplog) -> None:
|
||||
{"": "1.0", "Wire": {"name": 123, "version": "1.0"}, "SPI": "*"}, "libx"
|
||||
) == [{"name": "SPI", "owner": None, "version": "*"}]
|
||||
assert caplog.text.count("unrecognized dependency entry") == 5
|
||||
# A container or numeric version would raise from set.add() or fail
|
||||
# opaquely in the registry; both spellings warn and drop
|
||||
assert normalize_dependencies({"Foo": ["1.0", "2.0"]}, "libx") == []
|
||||
assert normalize_dependencies([{"name": "Foo", "version": 1}], "libx") == []
|
||||
assert caplog.text.count("unrecognized dependency entry") == 7
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
Reference in New Issue
Block a user