Add persistent notifications to bootstrap (#3738)

* Add persistent notifications to bootstrap

* Rebase, Fix test
This commit is contained in:
Johann Kellerman 2016-10-13 18:09:07 +02:00 committed by Paulus Schoutsen
parent 39a446c43c
commit cb322f72db
4 changed files with 36 additions and 15 deletions

View File

@ -32,6 +32,8 @@ _CURRENT_SETUP = []
ATTR_COMPONENT = 'component'
ERROR_LOG_FILENAME = 'home-assistant.log'
_PERSISTENT_PLATFORMS = set()
_PERSISTENT_VALIDATION = set()
def setup_component(hass: core.HomeAssistant, domain: str,
@ -149,7 +151,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
try:
config = component.CONFIG_SCHEMA(config)
except vol.Invalid as ex:
log_exception(ex, domain, config)
log_exception(ex, domain, config, hass)
return None
elif hasattr(component, 'PLATFORM_SCHEMA'):
@ -159,7 +161,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
try:
p_validated = component.PLATFORM_SCHEMA(p_config)
except vol.Invalid as ex:
log_exception(ex, domain, config)
log_exception(ex, domain, config, hass)
continue
# Not all platform components follow same pattern for platforms
@ -181,7 +183,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
p_validated = platform.PLATFORM_SCHEMA(p_validated)
except vol.Invalid as ex:
log_exception(ex, '{}.{}'.format(domain, p_name),
p_validated)
p_validated, hass)
continue
platforms.append(p_validated)
@ -211,6 +213,13 @@ def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
# Not found
if platform is None:
_LOGGER.error('Unable to find platform %s', platform_path)
_PERSISTENT_PLATFORMS.add(platform_path)
message = ('Unable to find the following platforms: ' +
', '.join(list(_PERSISTENT_PLATFORMS)) +
'(please check your configuration)')
persistent_notification.create(
hass, message, 'Invalid platforms', 'platform_errors')
return None
# Already loaded
@ -257,7 +266,7 @@ def from_config_dict(config: Dict[str, Any],
try:
conf_util.process_ha_core_config(hass, core_config)
except vol.Invalid as ex:
log_exception(ex, 'homeassistant', core_config)
log_exception(ex, 'homeassistant', core_config, hass)
return None
conf_util.process_ha_config_upgrade(hass)
@ -305,6 +314,7 @@ def from_config_dict(config: Dict[str, Any],
hass.loop.run_until_complete(
hass.loop.run_in_executor(None, component_setup)
)
return hass
@ -397,9 +407,16 @@ def _ensure_loader_prepared(hass: core.HomeAssistant) -> None:
loader.prepare(hass)
def log_exception(ex, domain, config):
def log_exception(ex, domain, config, hass=None):
"""Generate log exception for config validation."""
message = 'Invalid config for [{}]: '.format(domain)
if hass is not None:
_PERSISTENT_VALIDATION.add(domain)
message = ('The following platforms contain invalid configuration: ' +
', '.join(list(_PERSISTENT_VALIDATION)) +
' (please check your configuration)')
persistent_notification.create(
hass, message, 'Invalid config', 'invalid_config')
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\

View File

@ -199,9 +199,10 @@ def check(config_path):
res['secrets'][node.value] = val
return val
def mock_except(ex, domain, config): # pylint: disable=unused-variable
def mock_except(ex, domain, config, # pylint: disable=unused-variable
hass=None):
"""Mock bootstrap.log_exception."""
MOCKS['except'][1](ex, domain, config)
MOCKS['except'][1](ex, domain, config, hass)
res['except'][domain] = config.get(domain, config)
# Patches to skip functions

View File

@ -74,13 +74,15 @@ class TestCheckConfig(unittest.TestCase):
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir('component.yaml'))
change_yaml_files(res)
self.assertDictEqual({
'components': {},
'except': {'http': {'password': 'err123'}},
'secret_cache': {},
'secrets': {},
'yaml_files': ['.../component.yaml']
}, res)
self.assertDictEqual({}, res['components'])
self.assertDictEqual(
{'http': {'password': 'err123'}},
res['except']
)
self.assertDictEqual({}, res['secret_cache'])
self.assertDictEqual({}, res['secrets'])
self.assertListEqual(['.../component.yaml'], res['yaml_files'])
files = {
'platform.yaml': (BASE_CONFIG + 'mqtt:\n\n'

View File

@ -269,11 +269,12 @@ class TestBootstrap:
def test_home_assistant_core_config_validation(self):
"""Test if we pass in wrong information for HA conf."""
# Extensive HA conf validation testing is done in test_config.py
hass = get_test_home_assistant()
assert None is bootstrap.from_config_dict({
'homeassistant': {
'latitude': 'some string'
}
})
}, hass=hass)
def test_component_setup_with_validation_and_dependency(self):
"""Test all config is passed to dependencies."""