def validate_substitute(value): if isinstance(value, dict): return cv.Schema({ cv.Required(CONF_FROM): cv.string, cv.Required(CONF_TO): cv.string, })(value) value = cv.string(value) if "->" not in value: raise cv.Invalid("Substitute mapping must contain '->'") a, b = value.split("->", 1) a, b = a.strip(), b.strip() return validate_substitute({ CONF_FROM: cv.string(a), CONF_TO: cv.string(b) })
def validator(value): if isinstance(value, float) and value.is_integer(): value = int(value) value = cv.string(value) if not value.endswith('V'): value += 'V' return cv.one_of(*values)(value)
def validate_pcf8574_gpio_mode(value): value = cv.string(value) if value.upper() == 'INPUT_PULLUP': raise cv.Invalid( "INPUT_PULLUP mode has been removed in 1.14 and been combined into " "INPUT mode (they were the same thing). Please use INPUT instead.") return cv.enum(PCF8674_GPIO_MODES, upper=True)(value)
def validate_yaml_filename(value): value = cv.string(value) if not (value.endswith(".yaml") or value.endswith(".yml")): raise cv.Invalid("Only YAML (.yaml / .yml) files are supported.") return value
def validate_homeassistant_event(value): value = cv.string(value) if not value.startswith("esphome."): raise cv.Invalid( "ESPHome can only generate Home Assistant events that begin with " "esphome. For example 'esphome.xyz'") return value
def validate_UUID(value): # print("UUID«", value) value = cv.string(value) # TASK improve the regex if re.match(r'^[0-9a-fA-F\-]{8,36}$', value) is None: raise cv.Invalid("valid UUID required") return value
def preload_core_config(config): if 'esphomeyaml' in config: _LOGGER.warning( "The esphomeyaml section has been renamed to esphome in 1.11.0. " "Please replace 'esphomeyaml:' in your configuration with 'esphome:'." ) config[CONF_ESPHOME] = config.pop('esphomeyaml') if CONF_ESPHOME not in config: raise EsphomeError(u"No esphome section in config") core_conf = config[CONF_ESPHOME] if CONF_PLATFORM not in core_conf: raise EsphomeError("esphome.platform not specified.") if CONF_BOARD not in core_conf: raise EsphomeError("esphome.board not specified.") if CONF_NAME not in core_conf: raise EsphomeError("esphome.name not specified.") try: CORE.esp_platform = validate_platform(core_conf[CONF_PLATFORM]) CORE.board = validate_board(core_conf[CONF_BOARD]) CORE.name = cv.valid_name(core_conf[CONF_NAME]) CORE.build_path = CORE.relative_path( cv.string(core_conf.get(CONF_BUILD_PATH, default_build_path()))) except vol.Invalid as e: raise EsphomeError(text_type(e))
def validate_enum_bound(value): value = cv.string(value) for unit in _units: if value.endswith(unit): value = value[: -len(unit)] break return enum_bound(value)
def validate_variant(value): value = cv.string(value).upper() if value == 'WS2813': value = 'WS2812X' if value == 'WS2812': value = '800KBPS' if value == 'LC8812': value = 'SK6812' return cv.one_of(*VARIANTS)(value)
def validate_rotation(value): value = cv.string(value) if value.endswith(u"°"): value = value[:-1] try: value = int(value) except ValueError: raise vol.Invalid(u"Expected integer for rotation") return cv.one_of(*DISPLAY_ROTATIONS)(value)
def validate_variant(value): value = cv.string(value).upper() if value == "WS2813": value = "WS2812X" if value == "WS2812": value = "800KBPS" if value == "LC8812": value = "SK6812" return cv.one_of(*VARIANTS)(value)
def validate_platform(value): value = cv.string(value) if value.upper() in ('ESP8266', 'ESPRESSIF8266'): return ESP_PLATFORM_ESP8266 if value.upper() in ('ESP32', 'ESPRESSIF32'): return ESP_PLATFORM_ESP32 raise vol.Invalid( u"Invalid platform '{}'. Only options are ESP8266 and ESP32. Please note " u"the old way to use the latest arduino framework version has been split up " u"into the arduino_version configuration option.".format(value))
def validate_datapoint(value): if isinstance(value, dict): return cv.Schema({ cv.Required(CONF_FROM): cv.float_, cv.Required(CONF_TO): cv.float_, })(value) value = cv.string(value) if "->" not in value: raise cv.Invalid("Datapoint mapping must contain '->'") a, b = value.split("->", 1) a, b = a.strip(), b.strip() return validate_datapoint({CONF_FROM: cv.float_(a), CONF_TO: cv.float_(b)})
def validate_mapping(value): if not isinstance(value, dict): value = cv.string(value) if "->" not in value: raise cv.Invalid("Mapping must contain '->'") a, b = value.split("->", 1) value = {CONF_FROM: a.strip(), CONF_TO: b.strip()} return cv.Schema({ cv.Required(CONF_FROM): cv.string, cv.Required(CONF_TO): cv.string })(value)
def validate_type(value): value = cv.string(value).upper() if 'R' not in value: raise vol.Invalid("Must have R in type") if 'G' not in value: raise vol.Invalid("Must have G in type") if 'B' not in value: raise vol.Invalid("Must have B in type") rest = set(value) - set('RGBW') if rest: raise vol.Invalid("Type has invalid color: {}".format(', '.join(rest))) if len(set(value)) != len(value): raise vol.Invalid("Type has duplicate color!") return value
def validate_type(value): value = cv.string(value).upper() if "R" not in value: raise cv.Invalid("Must have R in type") if "G" not in value: raise cv.Invalid("Must have G in type") if "B" not in value: raise cv.Invalid("Must have B in type") rest = set(value) - set("RGBW") if rest: raise cv.Invalid("Type has invalid color: {}".format(", ".join(rest))) if len(set(value)) != len(value): raise cv.Invalid("Type has duplicate color!") return value
def validate_substitution_key(value): value = cv.string(value) if not value: raise cv.Invalid("Substitution key must not be empty") if value[0] == '$': value = value[1:] if value[0].isdigit(): raise cv.Invalid("First character in substitutions cannot be a digit.") for char in value: if char not in VALID_SUBSTITUTIONS_CHARACTERS: raise cv.Invalid( u"Substitution must only consist of upper/lowercase characters, the underscore " u"and numbers. The character '{}' cannot be used".format(char)) return value
def validate_cron_raw(value): value = cv.string(value) value = value.split(' ') if len(value) != 6: raise cv.Invalid("Cron expression must consist of exactly 6 space-separated parts, " "not {}".format(len(value))) seconds, minutes, hours, days_of_month, months, days_of_week = value return { CONF_SECONDS: validate_cron_seconds(seconds), CONF_MINUTES: validate_cron_minutes(minutes), CONF_HOURS: validate_cron_hours(hours), CONF_DAYS_OF_MONTH: validate_cron_days_of_month(days_of_month), CONF_MONTHS: validate_cron_months(months), CONF_DAYS_OF_WEEK: validate_cron_days_of_week(days_of_week), }
def validator(value): if isinstance(value, list): for v in value: if not isinstance(v, int): raise cv.Invalid( "Expected integer for {} '{}', got {}".format(v, name, type(v))) if v < min_value or v > max_value: raise cv.Invalid( "{} {} is out of range (min={} max={}).".format(name, v, min_value, max_value)) return list(sorted(value)) value = cv.string(value) values = set() for part in value.split(','): values |= _parse_cron_part(part, min_value, max_value, special_mapping) return validator(list(values))
def validate_calibration_parameter(value): if isinstance(value, dict): return cv.Schema({ cv.Required(CONF_TEMPERATURE): cv.float_, cv.Required(CONF_VALUE): cv.float_, })(value) value = cv.string(value) parts = value.split('->') if len(parts) != 2: raise cv.Invalid("Calibration parameter must be of form 3000 -> 23°C") voltage = cv.resistance(parts[0].strip()) temperature = cv.temperature(parts[1].strip()) return validate_calibration_parameter({ CONF_TEMPERATURE: temperature, CONF_VALUE: voltage, })
def validator(value): if isinstance(value, list): for v in value: if not isinstance(v, int): raise cv.Invalid( f"Expected integer for {v} '{name}', got {type(v)}") if v < min_value or v > max_value: raise cv.Invalid( f"{name} {v} is out of range (min={min_value} max={max_value})." ) return list(sorted(value)) value = cv.string(value) values = set() for part in value.split(","): values |= _parse_cron_part(part, min_value, max_value, special_mapping) return validator(list(values))
def validate_url(value): value = cv.string(value) try: parsed = list(urlparse.urlparse(value)) except Exception as err: raise cv.Invalid("Invalid URL") from err if not parsed[0] or not parsed[1]: raise cv.Invalid("URL must have a URL scheme and host") if parsed[0] not in ["http", "https"]: raise cv.Invalid("Scheme must be http or https") if not parsed[2]: parsed[2] = "/" return urlparse.urlunparse(parsed)
def validate_url(value): value = cv.string(value) try: parsed = list(urlparse.urlparse(value)) except Exception: raise cv.Invalid('Invalid URL') if not parsed[0] or not parsed[1]: raise cv.Invalid('URL must have a URL scheme and host') if parsed[0] not in ['http', 'https']: raise cv.Invalid('Scheme must be http or https') if not parsed[2]: parsed[2] = '/' return urlparse.urlunparse(parsed)
def validate_acceleration(value): value = cv.string(value) for suffix in ('steps/s^2', 'steps/s*s', 'steps/s/s', 'steps/ss', 'steps/(s*s)'): if value.endswith(suffix): value = value[:-len(suffix)] if value == 'inf': return 1e6 try: value = float(value) except ValueError: raise vol.Invalid("Expected acceleration as floating point number, got {}".format(value)) if value <= 0: raise vol.Invalid("Acceleration must be larger than 0 steps/s^2!") return value
def validate_speed(value): value = cv.string(value) for suffix in ('steps/s', 'steps/s'): if value.endswith(suffix): value = value[:-len(suffix)] if value == 'inf': return 1e6 try: value = float(value) except ValueError: raise vol.Invalid("Expected speed as floating point number, got {}".format(value)) if value <= 0: raise vol.Invalid("Speed must be larger than 0 steps/s!") return value
def validate_speed(value): value = cv.string(value) for suffix in ("steps/s", "steps/s"): if value.endswith(suffix): value = value[: -len(suffix)] if value == "inf": return 1e6 try: value = float(value) except ValueError: # pylint: disable=raise-missing-from raise cv.Invalid(f"Expected speed as floating point number, got {value}") if value <= 0: raise cv.Invalid("Speed must be larger than 0 steps/s!") return value
def validate_acceleration(value): value = cv.string(value) for suffix in ('steps/s^2', 'steps/s*s', 'steps/s/s', 'steps/ss', 'steps/(s*s)'): if value.endswith(suffix): value = value[:-len(suffix)] if value == 'inf': return 1e6 try: value = float(value) except ValueError: # pylint: disable=raise-missing-from raise cv.Invalid( f"Expected acceleration as floating point number, got {value}") if value <= 0: raise cv.Invalid("Acceleration must be larger than 0 steps/s^2!") return value
def validate_commit(value): value = cv.string(value) if re.match(r"^[0-9a-f]{7,}$", value) is None: raise vol.Invalid( "Commit option only accepts commit hashes in hex format.") return value
def validate_fingerprint(value): value = cv.string(value) if re.match(r'^[0-9a-f]{40}$', value) is None: raise vol.Invalid(u"fingerprint must be valid SHA1 hash") return value
def test_string__invalid(value): with pytest.raises(Invalid): config_validation.string(value)