[substitutions] [packages] Fix substitutions: !include file.yaml regression

Resolve a deferred IncludeFile before validating the substitutions shape in
do_substitution_pass, and before wrapping it in UserDict in do_packages_pass.

Fixes esphome/esphome#15848
This commit is contained in:
J. Nick Koston
2026-04-19 02:25:00 -05:00
parent 38d894dfe7
commit ba8e729443
7 changed files with 38 additions and 1 deletions
+8 -1
View File
@@ -516,7 +516,14 @@ def do_packages_pass(
if CONF_PACKAGES not in config:
return config
substitutions = UserDict(config.pop(CONF_SUBSTITUTIONS, {}))
raw_substitutions = config.pop(CONF_SUBSTITUTIONS, {})
if isinstance(raw_substitutions, yaml_util.IncludeFile):
# Resolve `substitutions: !include file.yaml` before feeding into UserDict.
with cv.prepend_path(CONF_SUBSTITUTIONS):
raw_substitutions, _ = resolve_include(
raw_substitutions, [], ContextVars(), strict_undefined=False
)
substitutions = UserDict(raw_substitutions)
processor = _PackageProcessor(
substitutions, command_line_substitutions, skip_update
)
@@ -429,6 +429,11 @@ def do_substitution_pass(
# Use merge_dicts_ordered to preserve OrderedDict type for move_to_end()
substitutions = config.pop(CONF_SUBSTITUTIONS, {})
with cv.prepend_path(CONF_SUBSTITUTIONS):
if isinstance(substitutions, IncludeFile):
# Resolve `substitutions: !include file.yaml` before validating the shape.
substitutions, _ = resolve_include(
substitutions, [], ContextVars(), strict_undefined=False
)
if not isinstance(substitutions, dict):
raise cv.Invalid(
f"Substitutions must be a key to value mapping, got {type(substitutions)}"
@@ -0,0 +1,5 @@
substitutions:
wifi_password: sub_password
wifi:
ssid: main_ssid
password: sub_password
@@ -0,0 +1,5 @@
substitutions: !include 15-substitutions_inc.yaml
wifi:
ssid: main_ssid
password: $wifi_password
@@ -0,0 +1 @@
wifi_password: sub_password
@@ -0,0 +1,5 @@
substitutions:
wifi_password: sub_password
wifi:
ssid: main_ssid
password: sub_password
@@ -0,0 +1,9 @@
substitutions: !include 15-substitutions_inc.yaml
packages:
wifi_pkg:
wifi:
password: $wifi_password
wifi:
ssid: main_ssid