示例#1
0
def validate_configuration(configuration):
    """Get the schema for validating the configuration."""
    valid_gpio_pin = ValidateGPIOPin()
    valid_numeric_position = ValidateNumericPosition()

    config = vol.Schema(
        {
            vol.Required(CONF_API):
            vol.Or(MQTT_CONFIGURATION_SCHEMA, HASS_CONFIGURATION_SCHEMA,
                   NULL_CONFIGURATION_SCHEMA),
            vol.Inclusive(CONF_OPEN_GARAGE_PIN, 'control'):
            valid_gpio_pin,
            vol.Inclusive(CONF_CLOSE_GARAGE_PIN, 'control'):
            valid_gpio_pin,
            vol.Optional(CONF_TOGGLE_GARAGE_PIN):
            valid_gpio_pin,
            vol.Optional(CONF_INVERT_RELAY, default=False):
            vol.Coerce(bool),
            vol.Required(CONF_POSITIONS):
            keys_with_schema(valid_numeric_position, VALID_GPIO_PINS),
            vol.Required(CONF_ENTITY_ID):
            entity_id
        },
        extra=vol.ALLOW_EXTRA)(configuration)

    if not config.get(CONF_OPEN_GARAGE_PIN) and not config.get(
            CONF_TOGGLE_GARAGE_PIN):
        raise vol.MultipleInvalid('({} and {}) or {}'.format(
            CONF_OPEN_GARAGE_PIN, CONF_CLOSE_GARAGE_PIN,
            CONF_TOGGLE_GARAGE_PIN))

    return config
示例#2
0
文件: __init__.py 项目: khzd/pi4home
 def validator(value):
     is_list = isinstance(value, list)
     if not is_list:
         value = [value]
     names = set()
     ret = []
     errors = []
     for i, effect in enumerate(value):
         path = [i] if is_list else []
         if not isinstance(effect, dict):
             errors.append(
                 vol.Invalid(
                     "Each effect must be a dictionary, not {}".format(
                         type(value)), path))
             continue
         if len(effect) > 1:
             errors.append(
                 vol.Invalid(
                     "Each entry in the 'effects:' option must be a single effect.",
                     path))
             continue
         if not effect:
             errors.append(
                 vol.Invalid(
                     "Found no effect for the {}th entry in 'effects:'!".
                     format(i), path))
             continue
         key = next(iter(effect.keys()))
         if key.startswith('fastled'):
             errors.append(
                 vol.Invalid(
                     "FastLED effects have been renamed to addressable effects. "
                     "Please use '{}'".format(
                         key.replace('fastled', 'addressable')), path))
             continue
         if key not in allowed_effects:
             errors.append(
                 vol.Invalid(
                     "The effect '{}' does not exist or is not allowed for this "
                     "light type".format(key), path))
             continue
         effect[key] = effect[key] or {}
         try:
             conf = EFFECTS_SCHEMA(effect)
         except vol.Invalid as err:
             err.prepend(path)
             errors.append(err)
             continue
         name = conf[key][CONF_NAME]
         if name in names:
             errors.append(
                 vol.Invalid(
                     u"Found the effect name '{}' twice. All effects must have "
                     u"unique names".format(name), [i]))
             continue
         names.add(name)
         ret.append(conf)
     if errors:
         raise vol.MultipleInvalid(errors)
     return ret
示例#3
0
def valid_preset_mode_configuration(config):
    """Validate that the preset mode reset payload is not one of the preset modes."""
    if PRESET_NONE in config.get(CONF_PRESET_MODES_LIST):
        raise ValueError("preset_modes must not include preset mode 'none'")
    if config.get(CONF_PRESET_MODE_COMMAND_TOPIC):
        for config_parameter in DEPRECATED_INVALID:
            if config.get(config_parameter):
                raise vol.MultipleInvalid(
                    "preset_modes cannot be used with deprecated away or hold mode config options"
                )
    return config
示例#4
0
文件: sensor.py 项目: pasna/myconfig
def indications_validator(indications: Any):
    if isinstance(indications, Mapping):
        temp_indications = {**indications}

        dict_indications = {}

        for key in indications.keys():
            key_str = str(key)
            match = RE_INDICATIONS_KEY.search(key_str)
            if match:
                value = cv.positive_float(indications[key])

                idx = cv.positive_int(match.group(3))
                if idx in dict_indications and dict_indications[idx] != value:
                    raise vol.Invalid(
                        'altering indication value for same index: %s' %
                        (idx, ),
                        path=[key_str])

                dict_indications[idx] = value
                del temp_indications[key]

        if temp_indications:
            errors = [
                vol.Invalid('extra keys not allowed', path=[key])
                for key in temp_indications.keys()
            ]
            if len(errors) == 1:
                raise errors[0]
            raise vol.MultipleInvalid(errors)

        list_indications = []

        for key in sorted(dict_indications.keys()):
            if len(list_indications) < key - 1:
                raise vol.Invalid('missing indication index: %d' % (key - 1, ))
            list_indications.append(dict_indications[key])

    else:
        try:
            indications = map(str.strip, cv.string(indications).split(','))
        except (vol.Invalid, vol.MultipleInvalid):
            indications = cv.ensure_list(indications)

        list_indications = list(map(cv.positive_float, indications))

    if len(list_indications) < 1:
        raise vol.Invalid('empty set of indications provided')

    return list_indications
示例#5
0
def _unique_username_validator(
        configs: List[Mapping[str, Any]]) -> List[Mapping[str, Any]]:
    existing_usernames = set()
    exceptions = []
    for i, config in enumerate(configs):
        if config[CONF_USERNAME] in existing_usernames:
            exceptions.append(
                vol.Invalid('duplicate username entry detected', [i]))
        else:
            existing_usernames.add(config[CONF_USERNAME])

    if len(exceptions) > 1:
        raise vol.MultipleInvalid(exceptions)
    elif len(exceptions) == 1:
        raise exceptions[0]

    return configs
示例#6
0
 def validator_(value):
     if isinstance(value, list):
         try:
             # First try as a sequence of actions
             return [schema({CONF_THEN: value})]
         except vol.Invalid as err:
             # Next try as a sequence of automations
             try:
                 return vol.Schema([schema])(value)
             except vol.Invalid as err2:
                 raise vol.MultipleInvalid([err, err2])
     elif isinstance(value, dict):
         if CONF_THEN in value:
             return [schema(value)]
         return [schema({CONF_THEN: value})]
     # This should only happen with invalid configs, but let's have a nice error message.
     return [schema(value)]
示例#7
0
def validate_event_data(obj: dict) -> dict:
    """Validate that a trigger has a valid event data."""
    # Return if there's no event data to validate
    if ATTR_EVENT_DATA not in obj:
        return obj

    event_source = obj[ATTR_EVENT_SOURCE]
    event_name = obj[ATTR_EVENT]
    event_data = obj[ATTR_EVENT_DATA]
    try:
        EVENT_MODEL_MAP[event_source][event_name](**event_data)
    except ValidationError as exc:
        # Filter out required field errors if keys can be missing, and if there are
        # still errors, raise an exception
        if errors := [
                error for error in exc.errors()
                if error["type"] != "value_error.missing"
        ]:
            raise vol.MultipleInvalid(errors) from exc
示例#8
0
    def validator_(value):
        if isinstance(value, list):
            try:
                # First try as a sequence of actions
                return [schema({CONF_THEN: value})]
            except vol.Invalid as err:
                if err.path and err.path[0] == CONF_THEN:
                    err.path.pop(0)

                # Next try as a sequence of automations
                try:
                    return cv.Schema([schema])(value)
                except vol.Invalid as err2:
                    if 'Unable to find action' in str(err):
                        raise err2
                    raise vol.MultipleInvalid([err, err2])
        elif isinstance(value, dict):
            if CONF_THEN in value:
                return [schema(value)]
            return [schema({CONF_THEN: value})]
        # This should only happen with invalid configs, but let's have a nice error message.
        return [schema(value)]
示例#9
0
def ensure_multiple_invalid(err):
    if isinstance(err, vol.MultipleInvalid):
        return err
    return vol.MultipleInvalid(err)
示例#10
0
        def validate_mapping(path, iterable, out):
            required_keys = all_required_keys.copy()

            # Build a map of all provided key-value pairs.
            # The type(out) is used to retain ordering in case a ordered
            # map type is provided as input.
            key_value_map = type(out)()
            for key, value in iterable:
                key_value_map[key] = value

            # Insert default values for non-existing keys.
            for key in all_default_keys:
                if (
                    not isinstance(key.default, vol.Undefined)
                    and key.schema not in key_value_map
                ):
                    # A default value has been specified for this missing key, insert it.
                    key_value_map[key.schema] = key.default()

            error = None
            errors = []
            for key, value in key_value_map.items():
                key_path = path + [key]
                # Optimization. Validate against the matching key first, then fallback to the rest
                relevant_candidates = itertools.chain(
                    candidates_by_key.get(key, []), additional_candidates
                )

                # compare each given key/value against all compiled key/values
                # schema key, (compiled key, compiled value)
                for skey, (ckey, cvalue) in relevant_candidates:
                    try:
                        new_key = ckey(key_path, key)
                    except vol.Invalid as e:
                        if len(e.path) > len(key_path):
                            raise
                        if not error or len(e.path) > len(error.path):
                            error = e
                        continue
                    # Backtracking is not performed once a key is selected, so if
                    # the value is invalid we immediately throw an exception.
                    exception_errors = []
                    try:
                        cval = cvalue(key_path, value)
                        out[new_key] = cval
                    except vol.MultipleInvalid as e:
                        exception_errors.extend(e.errors)
                    except vol.Invalid as e:
                        exception_errors.append(e)

                    if exception_errors:
                        for err in exception_errors:
                            if len(err.path) <= len(key_path):
                                err.error_type = invalid_msg
                            errors.append(err)
                        # If there is a validation error for a required
                        # key, this means that the key was provided.
                        # Discard the required key so it does not
                        # create an additional, noisy exception.
                        required_keys.discard(skey)
                        break

                    # Key and value okay, mark as found in case it was
                    # a Required() field.
                    required_keys.discard(skey)

                    break
                else:
                    if self.extra == vol.ALLOW_EXTRA:
                        out[key] = value
                    elif self.extra != vol.REMOVE_EXTRA:
                        if isinstance(key, str) and key_names:
                            matches = difflib.get_close_matches(key, key_names)
                            errors.append(
                                ExtraKeysInvalid(
                                    "extra keys not allowed",
                                    key_path,
                                    candidates=matches,
                                )
                            )
                        else:
                            errors.append(
                                vol.Invalid("extra keys not allowed", key_path)
                            )

            # for any required keys left that weren't found and don't have defaults:
            for key in required_keys:
                msg = getattr(key, "msg", None) or "required key not provided"
                errors.append(vol.RequiredFieldInvalid(msg, path + [key]))
            if errors:
                raise vol.MultipleInvalid(errors)

            return out