def validate_config(config): result = Config() def _comp_error(ex, path): # type: (vol.Invalid, List[basestring]) -> None if isinstance(ex, vol.MultipleInvalid): errors = ex.errors else: errors = [ex] for e in errors: path_ = path + e.path domain = result.lookup_domain(path_) or '' result.add_error(_format_vol_invalid(e, config, path, domain), path_) skip_paths = list() # type: List[ConfigPath] # Step 1: Load everything result.add_domain([CONF_ESPHOMEYAML], CONF_ESPHOMEYAML) result[CONF_ESPHOMEYAML] = config[CONF_ESPHOMEYAML] for domain, conf in config.items(): domain = str(domain) if domain == CONF_ESPHOMEYAML or domain.startswith(u'.'): skip_paths.append([domain]) continue result.add_domain([domain], domain) result[domain] = conf if conf is None: result[domain] = conf = {} component = get_component(domain) if component is None: result.add_error(u"Component not found: {}".format(domain), [domain]) skip_paths.append([domain]) continue if not isinstance(conf, list) and getattr(component, 'MULTI_CONF', False): result[domain] = conf = [conf] success = True dependencies = getattr(component, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in config: result.add_error( u"Component {} requires component {}".format( domain, dependency), [domain]) success = False if not success: skip_paths.append([domain]) continue success = True conflicts_with = getattr(component, 'CONFLICTS_WITH', []) for conflict in conflicts_with: if conflict in config: result.add_error( u"Component {} cannot be used together with component {}" u"".format(domain, conflict), [domain]) success = False if not success: skip_paths.append([domain]) continue esp_platforms = getattr(component, 'ESP_PLATFORMS', ESP_PLATFORMS) if CORE.esp_platform not in esp_platforms: result.add_error( u"Component {} doesn't support {}.".format( domain, CORE.esp_platform), [domain]) skip_paths.append([domain]) continue if not hasattr(component, 'PLATFORM_SCHEMA'): continue result.remove_domain([domain], domain) if not isinstance(conf, list) and conf: result[domain] = conf = [conf] for i, p_config in enumerate(conf): if not isinstance(p_config, dict): result.add_error(u"Platform schemas must have 'platform:' key", [domain, i]) skip_paths.append([domain, i]) continue p_name = p_config.get('platform') if p_name is None: result.add_error( u"No platform specified for {}".format(domain), [domain, i]) skip_paths.append([domain, i]) continue p_domain = u'{}.{}'.format(domain, p_name) result.add_domain([domain, i], p_domain) platform = get_platform(domain, p_name) if platform is None: result.add_error(u"Platform not found: '{}'".format(p_domain), [domain, i]) skip_paths.append([domain, i]) continue success = True dependencies = getattr(platform, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in config: result.add_error( u"Platform {} requires component {}" u"".format(p_domain, dependency), [domain, i]) success = False if not success: skip_paths.append([domain, i]) continue success = True conflicts_with = getattr(platform, 'CONFLICTS_WITH', []) for conflict in conflicts_with: if conflict in config: result.add_error( u"Platform {} cannot be used together with component {}" u"".format(p_domain, conflict), [domain, i]) success = False if not success: skip_paths.append([domain, i]) continue esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS) if CORE.esp_platform not in esp_platforms: result.add_error( u"Platform {} doesn't support {}." u"".format(p_domain, CORE.esp_platform), [domain, i]) skip_paths.append([domain, i]) continue # Step 2: Validate configuration try: result[CONF_ESPHOMEYAML] = core_config.CONFIG_SCHEMA( result[CONF_ESPHOMEYAML]) except vol.Invalid as ex: _comp_error(ex, [CONF_ESPHOMEYAML]) for domain, conf in result.items(): domain = str(domain) if [domain] in skip_paths: continue component = get_component(domain) if hasattr(component, 'CONFIG_SCHEMA'): multi_conf = getattr(component, 'MULTI_CONF', False) if multi_conf: for i, conf_ in enumerate(conf): try: validated = component.CONFIG_SCHEMA(conf_) result[domain][i] = validated except vol.Invalid as ex: _comp_error(ex, [domain, i]) else: try: validated = component.CONFIG_SCHEMA(conf) result[domain] = validated except vol.Invalid as ex: _comp_error(ex, [domain]) continue if not hasattr(component, 'PLATFORM_SCHEMA'): continue for i, p_config in enumerate(conf): if [domain, i] in skip_paths: continue p_name = p_config['platform'] platform = get_platform(domain, p_name) if hasattr(platform, 'PLATFORM_SCHEMA'): try: p_validated = platform.PLATFORM_SCHEMA(p_config) except vol.Invalid as ex: _comp_error(ex, [domain, i]) continue result[domain][i] = p_validated if not result.errors: # Only parse IDs if no validation error. Otherwise # user gets confusing messages do_id_pass(result) return result
def validate_config(config): global _ALL_COMPONENTS for req in REQUIRED_COMPONENTS: if req not in config: raise ESPHomeYAMLError( "Component {} is required for esphomeyaml.".format(req)) _ALL_COMPONENTS = list(config.keys()) result = Config() def _comp_error(ex, domain, config): result.add_error(_format_config_error(ex, domain, config), domain, config) try: result[CONF_ESPHOMEYAML] = core_config.CONFIG_SCHEMA( config[CONF_ESPHOMEYAML]) except vol.Invalid as ex: _comp_error(ex, CONF_ESPHOMEYAML, config[CONF_ESPHOMEYAML]) for domain, conf in config.iteritems(): domain = str(domain) if domain == CONF_ESPHOMEYAML or domain.startswith('.'): continue if conf is None: conf = {} component = get_component(domain) if component is None: result.add_error(u"Component not found: {}".format(domain), domain, conf) continue esp_platforms = getattr(component, 'ESP_PLATFORMS', ESP_PLATFORMS) if core.ESP_PLATFORM not in esp_platforms: result.add_error( u"Component {} doesn't support {}.".format( domain, core.ESP_PLATFORM), domain, conf) continue success = True dependencies = getattr(component, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in _ALL_COMPONENTS: result.add_error( u"Component {} requires component {}".format( domain, dependency), domain, conf) success = False if not success: continue if hasattr(component, 'CONFIG_SCHEMA'): try: validated = component.CONFIG_SCHEMA(conf) result[domain] = validated except vol.Invalid as ex: _comp_error(ex, domain, conf) continue if not hasattr(component, 'PLATFORM_SCHEMA'): continue platforms = [] for p_config in conf: if not isinstance(p_config, dict): result.add_error( u"Platform schemas must have 'platform:' key", ) continue p_name = p_config.get(u'platform') if p_name is None: result.add_error( u"No platform specified for {}".format(domain)) continue p_domain = u'{}.{}'.format(domain, p_name) platform = get_platform(domain, p_name) if platform is None: result.add_error(u"Platform not found: '{}'".format(p_domain), p_domain, p_config) continue success = True dependencies = getattr(platform, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in _ALL_COMPONENTS: result.add_error( u"Platform {} requires component {}".format( p_domain, dependency), p_domain, p_config) success = False if not success: continue esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS) if core.ESP_PLATFORM not in esp_platforms: result.add_error( u"Platform {} doesn't support {}.".format( p_domain, core.ESP_PLATFORM), p_domain, p_config) continue if hasattr(platform, u'PLATFORM_SCHEMA'): try: p_validated = platform.PLATFORM_SCHEMA(p_config) except vol.Invalid as ex: _comp_error(ex, p_domain, p_config) continue platforms.append(p_validated) result[domain] = platforms do_id_pass(result) return result