mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 14:16:40 +00:00
[packages] Allow list instead of dict for packages (#8688)
This commit is contained in:
parent
3ed03edfec
commit
a31d8ec309
@ -24,22 +24,13 @@ DOMAIN = CONF_PACKAGES
|
||||
|
||||
|
||||
def validate_git_package(config: dict):
|
||||
if CONF_URL not in config:
|
||||
return config
|
||||
config = BASE_SCHEMA(config)
|
||||
new_config = config
|
||||
for key, conf in config.items():
|
||||
if CONF_URL in conf:
|
||||
try:
|
||||
conf = BASE_SCHEMA(conf)
|
||||
if CONF_FILE in conf:
|
||||
new_config[key][CONF_FILES] = [conf[CONF_FILE]]
|
||||
del new_config[key][CONF_FILE]
|
||||
except cv.MultipleInvalid as e:
|
||||
with cv.prepend_path([key]):
|
||||
raise e
|
||||
except cv.Invalid as e:
|
||||
raise cv.Invalid(
|
||||
"Extra keys not allowed in git based package",
|
||||
path=[key] + e.path,
|
||||
) from e
|
||||
if CONF_FILE in config:
|
||||
new_config[CONF_FILES] = [config[CONF_FILE]]
|
||||
del new_config[CONF_FILE]
|
||||
return new_config
|
||||
|
||||
|
||||
@ -74,8 +65,8 @@ BASE_SCHEMA = cv.All(
|
||||
cv.Required(CONF_URL): cv.url,
|
||||
cv.Optional(CONF_USERNAME): cv.string,
|
||||
cv.Optional(CONF_PASSWORD): cv.string,
|
||||
cv.Exclusive(CONF_FILE, "files"): validate_yaml_filename,
|
||||
cv.Exclusive(CONF_FILES, "files"): cv.All(
|
||||
cv.Exclusive(CONF_FILE, CONF_FILES): validate_yaml_filename,
|
||||
cv.Exclusive(CONF_FILES, CONF_FILES): cv.All(
|
||||
cv.ensure_list(
|
||||
cv.Any(
|
||||
validate_yaml_filename,
|
||||
@ -100,14 +91,17 @@ BASE_SCHEMA = cv.All(
|
||||
cv.has_at_least_one_key(CONF_FILE, CONF_FILES),
|
||||
)
|
||||
|
||||
PACKAGE_SCHEMA = cv.All(
|
||||
cv.Any(validate_source_shorthand, BASE_SCHEMA, dict), validate_git_package
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
CONFIG_SCHEMA = cv.Any(
|
||||
cv.Schema(
|
||||
{
|
||||
str: cv.Any(validate_source_shorthand, BASE_SCHEMA, dict),
|
||||
str: PACKAGE_SCHEMA,
|
||||
}
|
||||
),
|
||||
validate_git_package,
|
||||
cv.ensure_list(PACKAGE_SCHEMA),
|
||||
)
|
||||
|
||||
|
||||
@ -183,25 +177,33 @@ def _process_base_package(config: dict) -> dict:
|
||||
return {"packages": packages}
|
||||
|
||||
|
||||
def _process_package(package_config, config):
|
||||
recursive_package = package_config
|
||||
if CONF_URL in package_config:
|
||||
package_config = _process_base_package(package_config)
|
||||
if isinstance(package_config, dict):
|
||||
recursive_package = do_packages_pass(package_config)
|
||||
config = merge_config(recursive_package, config)
|
||||
return config
|
||||
|
||||
|
||||
def do_packages_pass(config: dict):
|
||||
if CONF_PACKAGES not in config:
|
||||
return config
|
||||
packages = config[CONF_PACKAGES]
|
||||
with cv.prepend_path(CONF_PACKAGES):
|
||||
packages = CONFIG_SCHEMA(packages)
|
||||
if not isinstance(packages, dict):
|
||||
if isinstance(packages, dict):
|
||||
for package_name, package_config in reversed(packages.items()):
|
||||
with cv.prepend_path(package_name):
|
||||
config = _process_package(package_config, config)
|
||||
elif isinstance(packages, list):
|
||||
for package_config in reversed(packages):
|
||||
config = _process_package(package_config, config)
|
||||
else:
|
||||
raise cv.Invalid(
|
||||
f"Packages must be a key to value mapping, got {type(packages)} instead"
|
||||
f"Packages must be a key to value mapping or list, got {type(packages)} instead"
|
||||
)
|
||||
|
||||
for package_name, package_config in reversed(packages.items()):
|
||||
with cv.prepend_path(package_name):
|
||||
recursive_package = package_config
|
||||
if CONF_URL in package_config:
|
||||
package_config = _process_base_package(package_config)
|
||||
if isinstance(package_config, dict):
|
||||
recursive_package = do_packages_pass(package_config)
|
||||
config = merge_config(recursive_package, config)
|
||||
|
||||
del config[CONF_PACKAGES]
|
||||
return config
|
||||
|
@ -76,10 +76,11 @@ def test_package_unused(basic_esphome, basic_wifi):
|
||||
|
||||
def test_package_invalid_dict(basic_esphome, basic_wifi):
|
||||
"""
|
||||
Ensures an error is raised if packages is not valid.
|
||||
If a url: key is present, it's expected to be well-formed remote package spec. Ensure an error is raised if not.
|
||||
Any other simple dict passed as a package will be merged as usual but may fail later validation.
|
||||
|
||||
"""
|
||||
config = {CONF_ESPHOME: basic_esphome, CONF_PACKAGES: basic_wifi}
|
||||
config = {CONF_ESPHOME: basic_esphome, CONF_PACKAGES: basic_wifi | {CONF_URL: ""}}
|
||||
|
||||
with pytest.raises(cv.Invalid):
|
||||
do_packages_pass(config)
|
||||
|
3
tests/components/packages/package.yaml
Normal file
3
tests/components/packages/package.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
sensor:
|
||||
- platform: template
|
||||
id: package_sensor
|
11
tests/components/packages/test.esp32-ard.yaml
Normal file
11
tests/components/packages/test.esp32-ard.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
packages:
|
||||
- sensor:
|
||||
- platform: template
|
||||
id: inline_sensor
|
||||
- !include package.yaml
|
||||
- github://esphome/esphome/tests/components/template/common.yaml@dev
|
||||
- url: https://github.com/esphome/esphome
|
||||
file: tests/components/binary_sensor_map/common.yaml
|
||||
ref: dev
|
||||
refresh: 1d
|
||||
|
13
tests/components/packages/test.esp32-idf.yaml
Normal file
13
tests/components/packages/test.esp32-idf.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
packages:
|
||||
sensor:
|
||||
sensor:
|
||||
- platform: template
|
||||
id: inline_sensor
|
||||
local: !include package.yaml
|
||||
shorthand: github://esphome/esphome/tests/components/template/common.yaml@dev
|
||||
github:
|
||||
url: https://github.com/esphome/esphome
|
||||
file: tests/components/binary_sensor_map/common.yaml
|
||||
ref: dev
|
||||
refresh: 1d
|
||||
|
Loading…
x
Reference in New Issue
Block a user