[platformio] Extract toolchain-agnostic PlatformIO library converter (#17243)

This commit is contained in:
Jonathan Swoboda
2026-06-28 07:03:09 -04:00
committed by GitHub
parent bda789052d
commit d3892b8399
4 changed files with 1023 additions and 730 deletions
+24 -59
View File
@@ -14,23 +14,23 @@ from esphome.const import (
Platform,
)
from esphome.core import CORE, Library
import esphome.espidf.component
from esphome.espidf.component import (
generate_cmakelists_txt,
generate_idf_component_yml,
generate_idf_components,
)
import esphome.platformio.library
from esphome.platformio.library import (
ConvertedLibrary as IDFComponent,
GitSource,
IDFComponent,
InvalidIDFComponent,
URLSource,
_check_library_data,
_collect_filtered_files,
_node_key,
_normalize_dependencies,
_parse_library_json,
_parse_library_properties,
_resolve_registry_version,
_split_list_by_condition,
generate_cmakelists_txt,
generate_idf_component_yml,
generate_idf_components,
collect_filtered_files,
split_list_by_condition,
)
@@ -70,7 +70,7 @@ def test_collect_filtered_files_basic(tmp_path):
f2.parent.mkdir(parents=True)
f2.write_text("int b;")
result = _collect_filtered_files(tmp_path, ["+<*>"])
result = collect_filtered_files(tmp_path, ["+<*>"])
assert str(f1) in result
assert str(f2) in result
@@ -81,7 +81,7 @@ def test_collect_filtered_files_exclude(tmp_path):
f1.write_text("int a;")
f2.write_text("int b;")
result = _collect_filtered_files(tmp_path, ["+<*> -<*.cpp>"])
result = collect_filtered_files(tmp_path, ["+<*> -<*.cpp>"])
assert str(f1) in result
assert str(f2) not in result
@@ -89,7 +89,7 @@ def test_collect_filtered_files_exclude(tmp_path):
def test_split_list_by_condition():
items = ["-Iinclude", "-Llib", "-Wall"]
matched, rest = _split_list_by_condition(
matched, rest = split_list_by_condition(
items, lambda x: x[2:] if x.startswith("-I") else None
)
@@ -202,41 +202,6 @@ def test_generate_idf_component_yml_missing_path_raises(tmp_component):
generate_idf_component_yml(tmp_component)
def test_check_library_data_valid(esp32_idf_core):
_check_library_data({"platforms": "*", "frameworks": "*"})
def test_check_library_data_valid2(esp32_idf_core):
_check_library_data({"platforms": "*"})
def test_check_library_data_valid3(esp32_idf_core):
_check_library_data({})
def test_check_library_data_valid4(esp32_idf_core):
_check_library_data({"platforms": "espressif32", "frameworks": "*"})
def test_check_library_data_valid5(esp32_idf_core):
_check_library_data({"platforms": "*", "frameworks": "espidf"})
def test_check_library_data_invalid_platform(esp32_idf_core):
with pytest.raises(InvalidIDFComponent):
_check_library_data({"platforms": ["other"], "frameworks": "*"})
def test_check_library_data_invalid_framework(
esp32_idf_core: None, caplog: pytest.LogCaptureFixture
) -> None:
# Framework mismatch is a warning, not a hard skip: the library is still
# included so that PIO manifests that only list "arduino" (but actually
# compile under IDF) can be used without forking them.
_check_library_data({"name": "lib", "platforms": "*", "frameworks": ["other"]})
assert "do not include 'espidf'" in caplog.text
def test_extra_script_captures_libpath_libs_and_defines(tmp_path):
from esphome.espidf.extra_script import captured_as_build_flags, run_extra_script
@@ -453,7 +418,7 @@ def _patch_registry(monkeypatch, versions):
``get_compatible_registry_versions`` / ``pick_best_registry_version`` run on
the canned data so the intersection logic is exercised for real.
"""
registry = esphome.espidf.component._make_registry_client()
registry = esphome.platformio.library._make_registry_client()
monkeypatch.setattr(
registry,
"fetch_registry_package",
@@ -467,7 +432,7 @@ def _patch_registry(monkeypatch, versions):
},
)
monkeypatch.setattr(
esphome.espidf.component, "_make_registry_client", lambda: registry
esphome.platformio.library, "_make_registry_client", lambda: registry
)
@@ -535,7 +500,7 @@ def test_generate_idf_components_dedupes_shared_dependency(
return owner, pkgname, version, f"http://x/{pkgname}.tar.gz"
monkeypatch.setattr(
esphome.espidf.component, "_resolve_registry_version", fake_resolve
esphome.platformio.library, "_resolve_registry_version", fake_resolve
)
top = generate_idf_components(
@@ -594,7 +559,7 @@ def test_generate_idf_components_lib_ignore_filters_top_level_and_dependencies(
return owner, pkgname, "1.0.0", f"http://x/{pkgname}.tar.gz"
monkeypatch.setattr(
esphome.espidf.component, "_resolve_registry_version", fake_resolve
esphome.platformio.library, "_resolve_registry_version", fake_resolve
)
# lib_ignore is read from CORE.platformio_options (stored there by
# _add_platformio_options); matched by lowercase short name.
@@ -640,7 +605,7 @@ def test_generate_idf_components_handles_dependency_cycle(
monkeypatch.setattr(IDFComponent, "download", fake_download)
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner,
@@ -697,7 +662,7 @@ def test_generate_idf_components_git_overrides_registry_warns(
monkeypatch.setattr(IDFComponent, "download", fake_download)
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner,
@@ -733,7 +698,7 @@ def test_generate_idf_components_missing_manifest_raises(
monkeypatch.setattr(IDFComponent, "download", fake_download)
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner,
@@ -777,7 +742,7 @@ def test_generate_idf_components_warns_on_noncanonical_duplicate(
monkeypatch.setattr(IDFComponent, "download", fake_download)
# Bare "shared" and "owner/shared" both resolve to canonical owner/shared.
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner or "owner",
@@ -810,7 +775,7 @@ def test_generate_idf_components_incompatible_top_level_raises(
monkeypatch.setattr(IDFComponent, "download", fake_download)
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner,
@@ -820,7 +785,7 @@ def test_generate_idf_components_incompatible_top_level_raises(
),
)
with pytest.raises(RuntimeError, match="not compatible with ESP-IDF"):
with pytest.raises(RuntimeError, match="not compatible with espidf"):
generate_idf_components([Library("esphome/A", "1.0.0", None)])
@@ -846,7 +811,7 @@ def test_generate_idf_components_incompatible_dependency_skipped(
monkeypatch.setattr(IDFComponent, "download", fake_download)
monkeypatch.setattr(
esphome.espidf.component,
esphome.platformio.library,
"_resolve_registry_version",
lambda owner, pkgname, requirements: (
owner,
@@ -892,7 +857,7 @@ def test_git_source_salt_scopes_domain(monkeypatch: pytest.MonkeyPatch) -> None:
return Path("/cloned"), None
monkeypatch.setattr(
esphome.espidf.component.git, "clone_or_update", fake_clone_or_update
esphome.platformio.library.git, "clone_or_update", fake_clone_or_update
)
source = GitSource("https://github.com/esphome/noise-c.git", "v1.0")