Never shred a string dependency list, defer and de-duplicate drop warnings

A plain-string dependencies value comma-splits into names instead of
iterating into one-character libraries; entries that normalize to
nothing warn naming the manifest, and the walk's version-less skip logs
at debug for every backend. The not-bundled warning is deferred until
after the walk and stays quiet for names resolved transitively, so a
false skipping message cannot teach users to ignore the real one. An
explicitly requested bundled library that resolves to no sources and no
headers warns that the install may be incomplete.
This commit is contained in:
J. Nick Koston
2026-08-22 00:48:30 -05:00
parent 35c77165ca
commit 9bb899d8df
4 changed files with 113 additions and 19 deletions
+45
View File
@@ -920,3 +920,48 @@ def test_pinned_bundled_dependency_substitution_warns(
)
assert "Wire" in [lib.name for lib in libs]
assert "pins version ^2.0.0; using the library bundled" in caplog.text
def test_transitively_resolved_dependency_does_not_warn(
tmp_path: Path, caplog: pytest.LogCaptureFixture
) -> None:
"""A version-less dependency the walk resolved as another library's
registry dependency is present in the build; the skipping warning must
stay quiet for it."""
framework = _make_framework(tmp_path)
_add_library("ESP32Async/ESPAsyncWebServer", "3.9.6")
ws_dir = tmp_path / "converted" / "webserver"
(ws_dir / "src").mkdir(parents=True)
tcp_dir = tmp_path / "converted" / "tcp"
(tcp_dir / "src").mkdir(parents=True)
ws = _converted(
"esp32async__ESPAsyncWebServer",
ws_dir,
{"build": {}, "dependencies": [{"name": "ESPAsyncTCP"}]},
)
tcp = _converted("esp32async__ESPAsyncTCP", tcp_dir, {"build": {}})
with _emitting_converter(ws, tcp):
component.resolve_libraries(
framework,
pio_platform="espressif8266",
board_mcu="esp8266",
cache_key="arduino8266",
)
assert "is not bundled with the framework" not in caplog.text
def test_empty_bundled_library_warns(
tmp_path: Path, caplog: pytest.LogCaptureFixture
) -> None:
"""A bundled directory with no sources or headers is a broken install,
not a silent no-op archive."""
framework = _make_framework(tmp_path)
(framework / "libraries" / "Empty").mkdir()
_add_library("Empty", None)
component.resolve_libraries(
framework,
pio_platform="espressif8266",
board_mcu="esp8266",
cache_key="arduino8266",
)
assert "Bundled library Empty has no sources or headers" in caplog.text
+10 -4
View File
@@ -592,12 +592,18 @@ def test_source_kind_map_shape() -> None:
assert SOURCE_KIND_FOR_SUFFIX[".cpp"] == "cxx"
def test_normalize_dependencies_string_entries() -> None:
def test_normalize_dependencies_forms(caplog) -> None:
"""Every PIO-legal spelling normalizes; unrecognizable entries warn."""
from esphome.platformio.library import normalize_dependencies
"""PIO's bare string-list form coerces to name dicts; other non-dict
entries still drop."""
assert normalize_dependencies(["Wire", {"name": "SPI"}, 5, ""]) == [
assert normalize_dependencies(["Wire", {"name": "SPI"}, 5, ""], "libx") == [
{"name": "Wire"},
{"name": "SPI"},
]
assert caplog.text.count("unrecognized dependency entry") == 2
# A plain string is names, never iterated into characters
assert normalize_dependencies("Wire, SPI") == [
{"name": "Wire"},
{"name": "SPI"},
]
assert normalize_dependencies("Wire") == [{"name": "Wire"}]