mirror of
https://github.com/esphome/esphome.git
synced 2025-03-14 06:38:17 +00:00
Add support for template variables in remote packages from Github
This commit is contained in:
parent
74f7197543
commit
2f892b97ce
@ -1,8 +1,8 @@
|
||||
from pathlib import Path
|
||||
|
||||
import esphome.config_validation as cv
|
||||
from esphome import git, yaml_util
|
||||
from esphome.config_helpers import merge_config
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ESPHOME,
|
||||
CONF_FILE,
|
||||
@ -14,8 +14,9 @@ from esphome.const import (
|
||||
CONF_REFRESH,
|
||||
CONF_URL,
|
||||
CONF_USERNAME,
|
||||
CONF_VARS,
|
||||
__version__ as ESPHOME_VERSION,
|
||||
)
|
||||
from esphome.const import __version__ as ESPHOME_VERSION
|
||||
from esphome.core import EsphomeError
|
||||
|
||||
DOMAIN = CONF_PACKAGES
|
||||
@ -81,6 +82,7 @@ BASE_SCHEMA = cv.All(
|
||||
cv.Optional(CONF_REFRESH, default="1d"): cv.All(
|
||||
cv.string, cv.source_refresh
|
||||
),
|
||||
cv.Optional(CONF_VARS): dict,
|
||||
}
|
||||
),
|
||||
cv.has_at_least_one_key(CONF_FILE, CONF_FILES),
|
||||
@ -107,6 +109,11 @@ def _process_base_package(config: dict) -> dict:
|
||||
password=config.get(CONF_PASSWORD),
|
||||
)
|
||||
files: list[str] = config[CONF_FILES]
|
||||
vars: dict = config.get(CONF_VARS)
|
||||
if vars:
|
||||
vars = {k: str(v) for k, v in vars.items()}
|
||||
else:
|
||||
vars = {}
|
||||
|
||||
def get_packages(files) -> dict:
|
||||
packages = {}
|
||||
@ -132,7 +139,7 @@ def _process_base_package(config: dict) -> dict:
|
||||
f"Current ESPHome Version is too old to use this package: {ESPHOME_VERSION} < {min_version}"
|
||||
)
|
||||
|
||||
packages[file] = new_yaml
|
||||
packages[file] = yaml_util.substitute_vars(new_yaml, vars)
|
||||
except EsphomeError as e:
|
||||
raise cv.Invalid(
|
||||
f"{file} is not a valid YAML file. Please check the file contents.\n{e}"
|
||||
|
@ -927,6 +927,7 @@ CONF_VALUE = "value"
|
||||
CONF_VALUE_FONT = "value_font"
|
||||
CONF_VARIABLES = "variables"
|
||||
CONF_VARIANT = "variant"
|
||||
CONF_VARS = "vars"
|
||||
CONF_VERSION = "version"
|
||||
CONF_VIBRATIONS = "vibrations"
|
||||
CONF_VISIBLE = "visible"
|
||||
|
@ -283,38 +283,6 @@ class ESPHomeLoaderMixin:
|
||||
vars = {k: str(v) for k, v in vars.items()}
|
||||
return file, vars
|
||||
|
||||
def substitute_vars(config, vars):
|
||||
from esphome.components import substitutions
|
||||
from esphome.const import CONF_DEFAULTS, CONF_SUBSTITUTIONS
|
||||
|
||||
org_subs = None
|
||||
result = config
|
||||
if not isinstance(config, dict):
|
||||
# when the included yaml contains a list or a scalar
|
||||
# wrap it into an OrderedDict because do_substitution_pass expects it
|
||||
result = OrderedDict([("yaml", config)])
|
||||
elif CONF_SUBSTITUTIONS in result:
|
||||
org_subs = result.pop(CONF_SUBSTITUTIONS)
|
||||
|
||||
defaults = {}
|
||||
if CONF_DEFAULTS in result:
|
||||
defaults = result.pop(CONF_DEFAULTS)
|
||||
|
||||
result[CONF_SUBSTITUTIONS] = vars
|
||||
for k, v in defaults.items():
|
||||
if k not in result[CONF_SUBSTITUTIONS]:
|
||||
result[CONF_SUBSTITUTIONS][k] = v
|
||||
|
||||
# Ignore missing vars that refer to the top level substitutions
|
||||
substitutions.do_substitution_pass(result, None, ignore_missing=True)
|
||||
result.pop(CONF_SUBSTITUTIONS)
|
||||
|
||||
if not isinstance(config, dict):
|
||||
result = result["yaml"] # unwrap the result
|
||||
elif org_subs:
|
||||
result[CONF_SUBSTITUTIONS] = org_subs
|
||||
return result
|
||||
|
||||
if isinstance(node, yaml.nodes.MappingNode):
|
||||
file, vars = extract_file_vars(node)
|
||||
else:
|
||||
@ -482,6 +450,39 @@ def _find_files(directory, pattern):
|
||||
yield filename
|
||||
|
||||
|
||||
def substitute_vars(config, vars):
|
||||
from esphome.components import substitutions
|
||||
from esphome.const import CONF_DEFAULTS, CONF_SUBSTITUTIONS
|
||||
|
||||
org_subs = None
|
||||
result = config
|
||||
if not isinstance(config, dict):
|
||||
# when the included yaml contains a list or a scalar
|
||||
# wrap it into an OrderedDict because do_substitution_pass expects it
|
||||
result = OrderedDict([("yaml", config)])
|
||||
elif CONF_SUBSTITUTIONS in result:
|
||||
org_subs = result.pop(CONF_SUBSTITUTIONS)
|
||||
|
||||
defaults = {}
|
||||
if CONF_DEFAULTS in result:
|
||||
defaults = result.pop(CONF_DEFAULTS)
|
||||
|
||||
result[CONF_SUBSTITUTIONS] = vars
|
||||
for k, v in defaults.items():
|
||||
if k not in result[CONF_SUBSTITUTIONS]:
|
||||
result[CONF_SUBSTITUTIONS][k] = v
|
||||
|
||||
# Ignore missing vars that refer to the top level substitutions
|
||||
substitutions.do_substitution_pass(result, None, ignore_missing=True)
|
||||
result.pop(CONF_SUBSTITUTIONS)
|
||||
|
||||
if not isinstance(config, dict):
|
||||
result = result["yaml"] # unwrap the result
|
||||
elif org_subs:
|
||||
result[CONF_SUBSTITUTIONS] = org_subs
|
||||
return result
|
||||
|
||||
|
||||
def is_secret(value):
|
||||
try:
|
||||
return _SECRET_VALUES[str(value)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user