[yaml] Resolve top-level IncludeFile in load_yaml (#15557)

This commit is contained in:
J. Nick Koston
2026-04-08 02:39:14 -10:00
committed by GitHub
parent a8b7c7a4ac
commit a72609e640
2 changed files with 18 additions and 1 deletions

View File

@@ -599,9 +599,14 @@ def _load_yaml_internal(fname: Path) -> Any:
listener(fname)
try:
with fname.open(encoding="utf-8") as f_handle:
return parse_yaml(fname, f_handle)
res = parse_yaml(fname, f_handle)
except (UnicodeDecodeError, OSError) as err:
raise EsphomeError(f"Error reading file {fname}: {err}") from err
# Top-level !include returns a deferred IncludeFile; resolve it so
# callers always receive the final content.
if isinstance(res, IncludeFile):
res = res.load()
return res
def parse_yaml(file_name: Path, file_handle: TextIOWrapper, yaml_loader=None) -> Any:

View File

@@ -640,6 +640,18 @@ def test_include_in_list_context() -> None:
assert config["values"] == ["alpha", "beta", "gamma"]
def test_top_level_include_resolved_by_load_yaml(tmp_path: Path) -> None:
"""load_yaml resolves a top-level !include so callers always get a dict."""
child = tmp_path / "child.yaml"
child.write_text("key: value\n")
main = tmp_path / "main.yaml"
main.write_text("!include child.yaml\n")
result = yaml_util.load_yaml(main)
assert isinstance(result, dict)
assert result["key"] == "value"
def test_include_plain_filename_loads_after_deferred_refactor() -> None:
"""!include with a plain filename (no $ expressions) still loads correctly.