Extend package support (#14611)

This commit is contained in:
cdce8p 2018-05-25 22:41:50 +02:00 committed by Paulus Schoutsen
parent 48972c7570
commit 6ceafabd78
2 changed files with 98 additions and 14 deletions

View File

@ -548,6 +548,31 @@ def _identify_config_schema(module):
return '', schema
def _recursive_merge(pack_name, comp_name, config, conf, package):
"""Merge package into conf, recursively."""
for key, pack_conf in package.items():
if isinstance(pack_conf, dict):
if not pack_conf:
continue
conf[key] = conf.get(key, OrderedDict())
_recursive_merge(pack_name, comp_name, config,
conf=conf[key], package=pack_conf)
elif isinstance(pack_conf, list):
if not pack_conf:
continue
conf[key] = cv.ensure_list(conf.get(key))
conf[key].extend(cv.ensure_list(pack_conf))
else:
if conf.get(key) is not None:
_log_pkg_error(
pack_name, comp_name, config,
'has keys that are defined multiple times')
else:
conf[key] = pack_conf
def merge_packages_config(hass, config, packages,
_log_pkg_error=_log_pkg_error):
"""Merge packages into the top-level configuration. Mutate config."""
@ -607,11 +632,10 @@ def merge_packages_config(hass, config, packages,
config[comp_name][key] = val
continue
# The last merge type are sections that may occur only once
# The last merge type are sections that require recursive merging
if comp_name in config:
_log_pkg_error(
pack_name, comp_name, config, "may occur only once"
" and it already exist in your main configuration")
_recursive_merge(pack_name, comp_name, config,
conf=config[comp_name], package=comp_conf)
continue
config[comp_name] = comp_conf

View File

@ -654,21 +654,81 @@ def test_merge_type_mismatch(merge_log_err, hass):
assert len(config['light']) == 2
def test_merge_once_only(merge_log_err, hass):
"""Test if we have a merge for a comp that may occur only once."""
packages = {
'pack_2': {
'mqtt': {},
'api': {}, # No config schema
},
}
def test_merge_once_only_keys(merge_log_err, hass):
"""Test if we have a merge for a comp that may occur only once. Keys."""
packages = {'pack_2': {'api': {
'key_3': 3,
}}}
config = {
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
'mqtt': {}, 'api': {}
'api': {
'key_1': 1,
'key_2': 2,
}
}
config_util.merge_packages_config(hass, config, packages)
assert config['api'] == {'key_1': 1, 'key_2': 2, 'key_3': 3, }
# Duplicate keys error
packages = {'pack_2': {'api': {
'key': 2,
}}}
config = {
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
'api': {'key': 1, }
}
config_util.merge_packages_config(hass, config, packages)
assert merge_log_err.call_count == 1
assert len(config) == 3
def test_merge_once_only_lists(hass):
"""Test if we have a merge for a comp that may occur only once. Lists."""
packages = {'pack_2': {'api': {
'list_1': ['item_2', 'item_3'],
'list_2': ['item_1'],
'list_3': [],
}}}
config = {
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
'api': {
'list_1': ['item_1'],
}
}
config_util.merge_packages_config(hass, config, packages)
assert config['api'] == {
'list_1': ['item_1', 'item_2', 'item_3'],
'list_2': ['item_1'],
}
def test_merge_once_only_dictionaries(hass):
"""Test if we have a merge for a comp that may occur only once. Dicts."""
packages = {'pack_2': {'api': {
'dict_1': {
'key_2': 2,
'dict_1.1': {'key_1.2': 1.2, },
},
'dict_2': {'key_1': 1, },
'dict_3': {},
}}}
config = {
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
'api': {
'dict_1': {
'key_1': 1,
'dict_1.1': {'key_1.1': 1.1, }
},
}
}
config_util.merge_packages_config(hass, config, packages)
assert config['api'] == {
'dict_1': {
'key_1': 1,
'key_2': 2,
'dict_1.1': {'key_1.1': 1.1, 'key_1.2': 1.2, },
},
'dict_2': {'key_1': 1, },
}
def test_merge_id_schema(hass):