Пример #1
0
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
Пример #2
0
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