mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 18:24:13 +01:00
Recommend similar keys for spelling errors (#458)
* Recommend similar keys for spelling errors Fixes https://github.com/esphome/feature-requests/issues/68 * Fixes * Fix
This commit is contained in:
parent
38e7b597d6
commit
1c7ca4bc6f
57 changed files with 302 additions and 137 deletions
|
@ -131,7 +131,7 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
|||
|
||||
# Next try as a sequence of automations
|
||||
try:
|
||||
return vol.Schema([schema])(value)
|
||||
return cv.Schema([schema])(value)
|
||||
except vol.Invalid as err2:
|
||||
if 'Unable to find action' in str(err):
|
||||
raise err2
|
||||
|
@ -146,7 +146,7 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
|||
def validator(value):
|
||||
value = validator_(value)
|
||||
if extra_validators is not None:
|
||||
value = vol.Schema([extra_validators])(value)
|
||||
value = cv.Schema([extra_validators])(value)
|
||||
if single:
|
||||
if len(value) != 1:
|
||||
raise vol.Invalid("Cannot have more than 1 automation for templates")
|
||||
|
@ -156,7 +156,7 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
|||
return validator
|
||||
|
||||
|
||||
AUTOMATION_SCHEMA = vol.Schema({
|
||||
AUTOMATION_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger),
|
||||
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation),
|
||||
vol.Optional(CONF_IF): validate_recursive_condition,
|
||||
|
@ -187,7 +187,7 @@ def or_condition_to_code(config, condition_id, arg_type, template_arg):
|
|||
yield Pvariable(condition_id, rhs, type=type)
|
||||
|
||||
|
||||
RANGE_CONDITION_SCHEMA = vol.All(vol.Schema({
|
||||
RANGE_CONDITION_SCHEMA = vol.All(cv.Schema({
|
||||
vol.Optional(CONF_ABOVE): cv.templatable(cv.float_),
|
||||
vol.Optional(CONF_BELOW): cv.templatable(cv.float_),
|
||||
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))
|
||||
|
@ -250,7 +250,7 @@ def if_action_to_code(config, action_id, arg_type, template_arg):
|
|||
yield action
|
||||
|
||||
|
||||
WHILE_ACTION_SCHEMA = vol.Schema({
|
||||
WHILE_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_CONDITION): validate_recursive_condition,
|
||||
vol.Required(CONF_THEN): validate_recursive_action,
|
||||
})
|
||||
|
@ -270,7 +270,7 @@ def while_action_to_code(config, action_id, arg_type, template_arg):
|
|||
|
||||
|
||||
def validate_wait_until(value):
|
||||
schema = vol.Schema({
|
||||
schema = cv.Schema({
|
||||
vol.Required(CONF_CONDITION): validate_recursive_condition
|
||||
})
|
||||
if isinstance(value, dict) and CONF_CONDITION in value:
|
||||
|
|
|
@ -12,7 +12,7 @@ MULTI_CONF = True
|
|||
|
||||
ADS1115Component = sensor.sensor_ns.class_('ADS1115Component', Component, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
|
||||
vol.Required(CONF_ADDRESS): cv.i2c_address,
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)
|
||||
|
|
|
@ -13,7 +13,7 @@ MULTI_CONF = True
|
|||
CONF_APDS9960_ID = 'apds9960_id'
|
||||
APDS9960 = sensor.sensor_ns.class_('APDS9960', PollingComponent, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(APDS9960),
|
||||
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||
|
|
|
@ -15,7 +15,7 @@ HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction',
|
|||
KeyValuePair = api_ns.class_('KeyValuePair')
|
||||
TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair')
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(APIServer),
|
||||
vol.Optional(CONF_PORT, default=6053): cv.port,
|
||||
vol.Optional(CONF_PASSWORD, default=''): cv.string_strict,
|
||||
|
@ -49,16 +49,16 @@ def lib_deps(config):
|
|||
|
||||
|
||||
CONF_HOMEASSISTANT_SERVICE = 'homeassistant.service'
|
||||
HOMEASSISTANT_SERVIC_ACTION_SCHEMA = vol.Schema({
|
||||
HOMEASSISTANT_SERVIC_ACTION_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.use_variable_id(APIServer),
|
||||
vol.Required(CONF_SERVICE): cv.string,
|
||||
vol.Optional(CONF_DATA): vol.Schema({
|
||||
vol.Optional(CONF_DATA): cv.Schema({
|
||||
cv.string: cv.string,
|
||||
}),
|
||||
vol.Optional(CONF_DATA_TEMPLATE): vol.Schema({
|
||||
vol.Optional(CONF_DATA_TEMPLATE): cv.Schema({
|
||||
cv.string: cv.string,
|
||||
}),
|
||||
vol.Optional(CONF_VARIABLES): vol.Schema({
|
||||
vol.Optional(CONF_VARIABLES): cv.Schema({
|
||||
cv.string: cv.lambda_,
|
||||
}),
|
||||
})
|
||||
|
|
|
@ -62,7 +62,7 @@ FILTERS_SCHEMA = cv.ensure_list({
|
|||
vol.Optional(CONF_HEARTBEAT): cv.invalid("The heartbeat filter has been removed in 1.11.0"),
|
||||
}, cv.has_exactly_one_key(*FILTER_KEYS))
|
||||
|
||||
MULTI_CLICK_TIMING_SCHEMA = vol.Schema({
|
||||
MULTI_CLICK_TIMING_SCHEMA = cv.Schema({
|
||||
vol.Optional(CONF_STATE): cv.boolean,
|
||||
vol.Optional(CONF_MIN_LENGTH): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_MAX_LENGTH): cv.positive_time_period_milliseconds,
|
||||
|
|
|
@ -41,7 +41,7 @@ RCSwitchTypeDReceiver = remote_ns.class_('RCSwitchTypeDReceiver', RCSwitchRawRec
|
|||
|
||||
def validate_raw(value):
|
||||
if isinstance(value, dict):
|
||||
return vol.Schema({
|
||||
return cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(int32),
|
||||
vol.Required(CONF_DATA): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)],
|
||||
})(value)
|
||||
|
@ -52,29 +52,29 @@ def validate_raw(value):
|
|||
|
||||
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(RemoteReceiver),
|
||||
vol.Optional(CONF_JVC): vol.Schema({
|
||||
vol.Optional(CONF_JVC): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_LG): vol.Schema({
|
||||
vol.Optional(CONF_LG): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True),
|
||||
}),
|
||||
vol.Optional(CONF_NEC): vol.Schema({
|
||||
vol.Optional(CONF_NEC): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
|
||||
}),
|
||||
vol.Optional(CONF_SAMSUNG): vol.Schema({
|
||||
vol.Optional(CONF_SAMSUNG): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_SONY): vol.Schema({
|
||||
vol.Optional(CONF_SONY): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=12): cv.one_of(12, 15, 20, int=True),
|
||||
}),
|
||||
vol.Optional(CONF_PANASONIC): vol.Schema({
|
||||
vol.Optional(CONF_PANASONIC): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_RC5): vol.Schema({
|
||||
vol.Optional(CONF_RC5): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): vol.All(cv.hex_int, vol.Range(min=0, max=0x1F)),
|
||||
vol.Required(CONF_COMMAND): vol.All(cv.hex_int, vol.Range(min=0, max=0x3F)),
|
||||
}),
|
||||
|
|
|
@ -36,7 +36,7 @@ def to_code(config):
|
|||
BUILD_FLAGS = '-DUSE_TEMPLATE_BINARY_SENSOR'
|
||||
|
||||
CONF_BINARY_SENSOR_TEMPLATE_PUBLISH = 'binary_sensor.template.publish'
|
||||
BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(binary_sensor.BinarySensor),
|
||||
vol.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||
})
|
||||
|
|
|
@ -55,7 +55,7 @@ def to_code(config):
|
|||
BUILD_FLAGS = '-DUSE_TEMPLATE_COVER'
|
||||
|
||||
CONF_COVER_TEMPLATE_PUBLISH = 'cover.template.publish'
|
||||
COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(cover.Cover),
|
||||
vol.Required(CONF_STATE): cv.templatable(cover.validate_cover_state),
|
||||
})
|
||||
|
|
|
@ -9,10 +9,10 @@ from esphome.cpp_types import Component, ComponentPtr, esphome_ns, std_vector
|
|||
CustomComponentConstructor = esphome_ns.class_('CustomComponentConstructor')
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor),
|
||||
vol.Required(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_COMPONENTS): cv.ensure_list(vol.Schema({
|
||||
vol.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(Component)
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)),
|
||||
})
|
||||
|
|
|
@ -11,7 +11,7 @@ from esphome.cpp_types import App, PollingComponent
|
|||
DallasComponent = sensor.sensor_ns.class_('DallasComponent', PollingComponent)
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(DallasComponent),
|
||||
vol.Required(CONF_PIN): pins.input_pin,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import voluptuous as vol
|
||||
|
||||
import esphome.config_validation as cv
|
||||
from esphome.cpp_generator import add
|
||||
from esphome.cpp_types import App
|
||||
|
||||
DEPENDENCIES = ['logger']
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({})
|
||||
CONFIG_SCHEMA = cv.Schema({})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
|
|
|
@ -38,14 +38,14 @@ EXT1_WAKEUP_MODES = {
|
|||
CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
|
||||
CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent),
|
||||
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
|
||||
validate_pin_number),
|
||||
vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32,
|
||||
cv.one_of(*WAKEUP_PIN_MODES), upper=True),
|
||||
vol.Optional(CONF_ESP32_EXT1_WAKEUP): vol.All(cv.only_on_esp32, vol.Schema({
|
||||
vol.Optional(CONF_ESP32_EXT1_WAKEUP): vol.All(cv.only_on_esp32, cv.Schema({
|
||||
vol.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number),
|
||||
vol.Required(CONF_MODE): cv.one_of(*EXT1_WAKEUP_MODES, upper=True),
|
||||
})),
|
||||
|
|
|
@ -13,7 +13,7 @@ ESP32BLEBeacon = esphome_ns.class_('ESP32BLEBeacon', Component)
|
|||
CONF_MAJOR = 'major'
|
||||
CONF_MINOR = 'minor'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(ESP32BLEBeacon),
|
||||
vol.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True),
|
||||
vol.Required(CONF_UUID): cv.uuid,
|
||||
|
|
|
@ -18,7 +18,7 @@ XIAOMI_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
|||
cv.GenerateID(): cv.declare_variable_id(XiaomiSensor)
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker),
|
||||
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_seconds,
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)
|
||||
|
|
|
@ -46,7 +46,7 @@ VOLTAGE_ATTENUATION = {
|
|||
|
||||
ESP32TouchComponent = binary_sensor.binary_sensor_ns.class_('ESP32TouchComponent', Component)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent),
|
||||
vol.Optional(CONF_SETUP_MODE): cv.boolean,
|
||||
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
|
||||
|
|
|
@ -46,7 +46,7 @@ def validate(config):
|
|||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(EthernetComponent),
|
||||
vol.Required(CONF_TYPE): cv.one_of(*ETHERNET_TYPES, upper=True),
|
||||
vol.Required(CONF_MDC_PIN): pins.output_pin,
|
||||
|
|
|
@ -14,7 +14,7 @@ PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
|||
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput),
|
||||
vol.Optional(CONF_SPEED): vol.Schema({
|
||||
vol.Optional(CONF_SPEED): cv.Schema({
|
||||
vol.Required(CONF_LOW): cv.percentage,
|
||||
vol.Required(CONF_MEDIUM): cv.percentage,
|
||||
vol.Required(CONF_HIGH): cv.percentage,
|
||||
|
|
|
@ -19,8 +19,8 @@ Glyph = display.display_ns.class_('Glyph')
|
|||
|
||||
def validate_glyphs(value):
|
||||
if isinstance(value, list):
|
||||
value = vol.Schema([cv.string])(value)
|
||||
value = vol.Schema([cv.string])(list(value))
|
||||
value = cv.Schema([cv.string])(value)
|
||||
value = cv.Schema([cv.string])(list(value))
|
||||
|
||||
def comparator(x, y):
|
||||
x_ = x.encode('utf-8')
|
||||
|
@ -69,7 +69,7 @@ def validate_truetype_file(value):
|
|||
DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
|
||||
CONF_RAW_DATA_ID = 'raw_data_id'
|
||||
|
||||
FONT_SCHEMA = vol.Schema({
|
||||
FONT_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(Font),
|
||||
vol.Required(CONF_FILE): validate_truetype_file,
|
||||
vol.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs,
|
||||
|
|
|
@ -10,7 +10,7 @@ GlobalVariableComponent = esphome_ns.class_('GlobalVariableComponent', Component
|
|||
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(GlobalVariableComponent),
|
||||
vol.Required(CONF_TYPE): cv.string_strict,
|
||||
vol.Optional(CONF_INITIAL_VALUE): cv.string_strict,
|
||||
|
|
|
@ -11,7 +11,7 @@ from esphome.cpp_types import App, Component, esphome_ns
|
|||
I2CComponent = esphome_ns.class_('I2CComponent', Component)
|
||||
I2CDevice = pins.I2CDevice
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(I2CComponent),
|
||||
vol.Optional(CONF_SDA, default='SDA'): pins.input_pin,
|
||||
vol.Optional(CONF_SCL, default='SCL'): pins.input_pin,
|
||||
|
|
|
@ -20,7 +20,7 @@ Image_ = display.display_ns.class_('Image')
|
|||
|
||||
CONF_RAW_DATA_ID = 'raw_data_id'
|
||||
|
||||
IMAGE_SCHEMA = vol.Schema({
|
||||
IMAGE_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(Image_),
|
||||
vol.Required(CONF_FILE): cv.file_,
|
||||
vol.Optional(CONF_RESIZE): cv.dimensions,
|
||||
|
|
|
@ -9,7 +9,7 @@ from esphome.cpp_types import App, NoArg, PollingComponent, Trigger, esphome_ns
|
|||
|
||||
IntervalTrigger = esphome_ns.class_('IntervalTrigger', Trigger.template(NoArg), PollingComponent)
|
||||
|
||||
CONFIG_SCHEMA = automation.validate_automation(vol.Schema({
|
||||
CONFIG_SCHEMA = automation.validate_automation(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(IntervalTrigger),
|
||||
vol.Required(CONF_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema))
|
||||
|
|
|
@ -88,22 +88,22 @@ ADDRESSABLE_EFFECTS = RGB_EFFECTS + [CONF_ADDRESSABLE_LAMBDA, CONF_ADDRESSABLE_R
|
|||
CONF_ADDRESSABLE_TWINKLE, CONF_ADDRESSABLE_RANDOM_TWINKLE,
|
||||
CONF_ADDRESSABLE_FIREWORKS, CONF_ADDRESSABLE_FLICKER]
|
||||
|
||||
EFFECTS_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_LAMBDA): vol.Schema({
|
||||
EFFECTS_SCHEMA = cv.Schema({
|
||||
vol.Optional(CONF_LAMBDA): cv.Schema({
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
vol.Required(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_RANDOM): vol.Schema({
|
||||
vol.Optional(CONF_RANDOM): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(RandomLightEffect),
|
||||
vol.Optional(CONF_NAME, default="Random"): cv.string,
|
||||
vol.Optional(CONF_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_STROBE): vol.Schema({
|
||||
vol.Optional(CONF_STROBE): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(StrobeLightEffect),
|
||||
vol.Optional(CONF_NAME, default="Strobe"): cv.string,
|
||||
vol.Optional(CONF_COLORS): vol.All(cv.ensure_list(vol.Schema({
|
||||
vol.Optional(CONF_COLORS): vol.All(cv.ensure_list(cv.Schema({
|
||||
vol.Optional(CONF_STATE, default=True): cv.boolean,
|
||||
vol.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage,
|
||||
vol.Optional(CONF_RED, default=1.0): cv.percentage,
|
||||
|
@ -114,24 +114,24 @@ EFFECTS_SCHEMA = vol.Schema({
|
|||
}), cv.has_at_least_one_key(CONF_STATE, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE,
|
||||
CONF_WHITE)), vol.Length(min=2)),
|
||||
}),
|
||||
vol.Optional(CONF_FLICKER): vol.Schema({
|
||||
vol.Optional(CONF_FLICKER): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FlickerLightEffect),
|
||||
vol.Optional(CONF_NAME, default="Flicker"): cv.string,
|
||||
vol.Optional(CONF_ALPHA): cv.percentage,
|
||||
vol.Optional(CONF_INTENSITY): cv.percentage,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_LAMBDA): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_LAMBDA): cv.Schema({
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
vol.Required(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_RAINBOW): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_RAINBOW): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableRainbowLightEffect),
|
||||
vol.Optional(CONF_NAME, default="Rainbow"): cv.string,
|
||||
vol.Optional(CONF_SPEED): cv.uint32_t,
|
||||
vol.Optional(CONF_WIDTH): cv.uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_COLOR_WIPE): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_COLOR_WIPE): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableColorWipeEffect),
|
||||
vol.Optional(CONF_NAME, default="Color Wipe"): cv.string,
|
||||
vol.Optional(CONF_COLORS): cv.ensure_list({
|
||||
|
@ -145,24 +145,24 @@ EFFECTS_SCHEMA = vol.Schema({
|
|||
vol.Optional(CONF_ADD_LED_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_REVERSE): cv.boolean,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_SCAN): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_SCAN): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableScanEffect),
|
||||
vol.Optional(CONF_NAME, default="Scan"): cv.string,
|
||||
vol.Optional(CONF_MOVE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_TWINKLE): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_TWINKLE): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableTwinkleEffect),
|
||||
vol.Optional(CONF_NAME, default="Twinkle"): cv.string,
|
||||
vol.Optional(CONF_TWINKLE_PROBABILITY): cv.percentage,
|
||||
vol.Optional(CONF_PROGRESS_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_RANDOM_TWINKLE): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_RANDOM_TWINKLE): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableRandomTwinkleEffect),
|
||||
vol.Optional(CONF_NAME, default="Random Twinkle"): cv.string,
|
||||
vol.Optional(CONF_TWINKLE_PROBABILITY): cv.percentage,
|
||||
vol.Optional(CONF_PROGRESS_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_FIREWORKS): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_FIREWORKS): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableFireworksEffect),
|
||||
vol.Optional(CONF_NAME, default="Fireworks"): cv.string,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
|
@ -170,7 +170,7 @@ EFFECTS_SCHEMA = vol.Schema({
|
|||
vol.Optional(CONF_USE_RANDOM_COLOR): cv.boolean,
|
||||
vol.Optional(CONF_FADE_OUT_RATE): cv.uint8_t,
|
||||
}),
|
||||
vol.Optional(CONF_ADDRESSABLE_FLICKER): vol.Schema({
|
||||
vol.Optional(CONF_ADDRESSABLE_FLICKER): cv.Schema({
|
||||
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableFlickerEffect),
|
||||
vol.Optional(CONF_NAME, default="Addressable Flicker"): cv.string,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
|
|
|
@ -73,13 +73,13 @@ def validate_local_no_higher_than_global(value):
|
|||
|
||||
LogComponent = esphome_ns.class_('LogComponent', Component)
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(LogComponent),
|
||||
vol.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
|
||||
vol.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes,
|
||||
vol.Optional(CONF_HARDWARE_UART, default='UART0'): uart_selection,
|
||||
vol.Optional(CONF_LEVEL): is_log_level,
|
||||
vol.Optional(CONF_LOGS): vol.Schema({
|
||||
vol.Optional(CONF_LOGS): cv.Schema({
|
||||
cv.string: is_log_level,
|
||||
})
|
||||
}), validate_local_no_higher_than_global)
|
||||
|
@ -129,8 +129,8 @@ def required_build_flags(config):
|
|||
def maybe_simple_message(schema):
|
||||
def validator(value):
|
||||
if isinstance(value, dict):
|
||||
return vol.Schema(schema)(value)
|
||||
return vol.Schema(schema)({CONF_FORMAT: value})
|
||||
return cv.Schema(schema)(value)
|
||||
return cv.Schema(schema)({CONF_FORMAT: value})
|
||||
|
||||
return validator
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ MULTI_CONF = True
|
|||
CONF_MPR121_ID = 'mpr121_id'
|
||||
MPR121Component = binary_sensor.binary_sensor_ns.class_('MPR121Component', Component, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(MPR121Component),
|
||||
vol.Optional(CONF_ADDRESS): cv.i2c_address
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)
|
||||
|
|
|
@ -26,7 +26,7 @@ def validate_message_just_topic(value):
|
|||
return MQTT_MESSAGE_BASE({CONF_TOPIC: value})
|
||||
|
||||
|
||||
MQTT_MESSAGE_BASE = vol.Schema({
|
||||
MQTT_MESSAGE_BASE = cv.Schema({
|
||||
vol.Required(CONF_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
|
||||
vol.Optional(CONF_RETAIN, default=True): cv.boolean,
|
||||
|
@ -67,7 +67,7 @@ def validate_fingerprint(value):
|
|||
return value
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
|
||||
vol.Required(CONF_BROKER): cv.string_strict,
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
|
@ -193,7 +193,7 @@ def to_code(config):
|
|||
|
||||
|
||||
CONF_MQTT_PUBLISH = 'mqtt.publish'
|
||||
MQTT_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.use_variable_id(MQTTClientComponent),
|
||||
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
|
||||
vol.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload),
|
||||
|
@ -228,7 +228,7 @@ def mqtt_publish_action_to_code(config, action_id, arg_type, template_arg):
|
|||
|
||||
|
||||
CONF_MQTT_PUBLISH_JSON = 'mqtt.publish_json'
|
||||
MQTT_PUBLISH_JSON_ACTION_SCHEMA = vol.Schema({
|
||||
MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.use_variable_id(MQTTClientComponent),
|
||||
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
|
||||
vol.Required(CONF_PAYLOAD): cv.lambda_,
|
||||
|
|
|
@ -12,7 +12,7 @@ from esphome.cpp_types import App, Component
|
|||
MY9231OutputComponent = output.output_ns.class_('MY9231OutputComponent', Component)
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(MY9231OutputComponent),
|
||||
vol.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema,
|
||||
|
|
|
@ -12,7 +12,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
OTAComponent = esphome_ns.class_('OTAComponent', Component)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(OTAComponent),
|
||||
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
|
|
|
@ -13,7 +13,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
|||
|
||||
})
|
||||
|
||||
BINARY_OUTPUT_SCHEMA = vol.Schema({
|
||||
BINARY_OUTPUT_SCHEMA = cv.Schema({
|
||||
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
})
|
||||
|
@ -95,7 +95,7 @@ def output_turn_off_to_code(config, action_id, arg_type, template_arg):
|
|||
|
||||
|
||||
CONF_OUTPUT_SET_LEVEL = 'output.set_level'
|
||||
OUTPUT_SET_LEVEL_ACTION = vol.Schema({
|
||||
OUTPUT_SET_LEVEL_ACTION = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(FloatOutput),
|
||||
vol.Required(CONF_LEVEL): cv.templatable(cv.percentage),
|
||||
})
|
||||
|
|
|
@ -13,7 +13,7 @@ MULTI_CONF = True
|
|||
PCA9685OutputComponent = output.output_ns.class_('PCA9685OutputComponent',
|
||||
Component, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
|
||||
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
|
||||
vol.Range(min=23.84, max=1525.88)),
|
||||
|
|
|
@ -20,7 +20,7 @@ PCF8675_GPIO_MODES = {
|
|||
PCF8574GPIOInputPin = io_ns.class_('PCF8574GPIOInputPin', GPIOInputPin)
|
||||
PCF8574GPIOOutputPin = io_ns.class_('PCF8574GPIOOutputPin', GPIOOutputPin)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(pins.PCF8574Component),
|
||||
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
|
||||
vol.Optional(CONF_PCF8575, default=False): cv.boolean,
|
||||
|
|
|
@ -17,7 +17,7 @@ PN532Component = binary_sensor.binary_sensor_ns.class_('PN532Component', Polling
|
|||
spi.SPIDevice)
|
||||
PN532Trigger = binary_sensor.binary_sensor_ns.class_('PN532Trigger', Trigger.template(std_string))
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(PN532Component),
|
||||
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
|
||||
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
|
||||
|
|
|
@ -11,7 +11,7 @@ PowerSupplyComponent = esphome_ns.class_('PowerSupplyComponent', Component)
|
|||
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
|
||||
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import voluptuous as vol
|
||||
|
||||
from esphome.components import binary_sensor, uart
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_UART_ID
|
||||
|
@ -12,7 +10,7 @@ DEPENDENCIES = ['uart']
|
|||
RDM6300Component = binary_sensor.binary_sensor_ns.class_('RDM6300Component', Component,
|
||||
uart.UARTDevice)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(RDM6300Component),
|
||||
cv.GenerateID(CONF_UART_ID): cv.use_variable_id(uart.UARTComponent),
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)
|
||||
|
|
|
@ -40,7 +40,7 @@ def validate_dumpers_all(value):
|
|||
raise vol.Invalid("Not valid dumpers")
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent),
|
||||
vol.Required(CONF_PIN): pins.gpio_input_pin_schema,
|
||||
vol.Optional(CONF_DUMP, default=[]):
|
||||
|
|
|
@ -39,7 +39,7 @@ RC_SWITCH_TIMING_SCHEMA = vol.All([cv.uint8_t], vol.Length(min=2, max=2))
|
|||
|
||||
RC_SWITCH_PROTOCOL_SCHEMA = vol.Any(
|
||||
vol.All(vol.Coerce(int), vol.Range(min=1, max=7)),
|
||||
vol.Schema({
|
||||
cv.Schema({
|
||||
vol.Required(CONF_PULSE_LENGTH): cv.uint32_t,
|
||||
vol.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA,
|
||||
vol.Optional(CONF_ZERO, default=[1, 3]): RC_SWITCH_TIMING_SCHEMA,
|
||||
|
@ -48,23 +48,23 @@ RC_SWITCH_PROTOCOL_SCHEMA = vol.Any(
|
|||
})
|
||||
)
|
||||
|
||||
RC_SWITCH_RAW_SCHEMA = vol.Schema({
|
||||
RC_SWITCH_RAW_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_CODE): validate_rc_switch_code,
|
||||
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
|
||||
})
|
||||
RC_SWITCH_TYPE_A_SCHEMA = vol.Schema({
|
||||
RC_SWITCH_TYPE_A_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_GROUP): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
|
||||
vol.Required(CONF_DEVICE): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
|
||||
vol.Required(CONF_STATE): cv.boolean,
|
||||
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
|
||||
})
|
||||
RC_SWITCH_TYPE_B_SCHEMA = vol.Schema({
|
||||
RC_SWITCH_TYPE_B_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
|
||||
vol.Required(CONF_CHANNEL): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
|
||||
vol.Required(CONF_STATE): cv.boolean,
|
||||
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
|
||||
})
|
||||
RC_SWITCH_TYPE_C_SCHEMA = vol.Schema({
|
||||
RC_SWITCH_TYPE_C_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_FAMILY): cv.one_of('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||
'l', 'm', 'n', 'o', 'p', lower=True),
|
||||
vol.Required(CONF_GROUP): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
|
||||
|
@ -72,14 +72,14 @@ RC_SWITCH_TYPE_C_SCHEMA = vol.Schema({
|
|||
vol.Required(CONF_STATE): cv.boolean,
|
||||
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
|
||||
})
|
||||
RC_SWITCH_TYPE_D_SCHEMA = vol.Schema({
|
||||
RC_SWITCH_TYPE_D_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_GROUP): cv.one_of('a', 'b', 'c', 'd', lower=True),
|
||||
vol.Required(CONF_DEVICE): vol.All(cv.uint8_t, vol.Range(min=1, max=3)),
|
||||
vol.Required(CONF_STATE): cv.boolean,
|
||||
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent),
|
||||
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(cv.percentage_int,
|
||||
|
|
|
@ -44,12 +44,12 @@ FILTERS_SCHEMA = cv.ensure_list({
|
|||
vol.Optional(CONF_MULTIPLY): cv.float_,
|
||||
vol.Optional(CONF_FILTER_OUT): cv.float_,
|
||||
vol.Optional(CONF_FILTER_NAN): None,
|
||||
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({
|
||||
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(cv.Schema({
|
||||
vol.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int,
|
||||
vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int,
|
||||
vol.Optional(CONF_SEND_FIRST_AT): cv.positive_not_null_int,
|
||||
}), validate_send_first_at),
|
||||
vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({
|
||||
vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): cv.Schema({
|
||||
vol.Optional(CONF_ALPHA, default=0.1): cv.positive_float,
|
||||
vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int,
|
||||
}),
|
||||
|
|
|
@ -64,7 +64,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|||
cv.GenerateID(): cv.declare_variable_id(BME680GasResistanceSensor),
|
||||
})),
|
||||
vol.Optional(CONF_IIR_FILTER): cv.one_of(*IIR_FILTER_OPTIONS, upper=True),
|
||||
vol.Optional(CONF_HEATER): vol.Any(None, vol.All(vol.Schema({
|
||||
vol.Optional(CONF_HEATER): vol.Any(None, vol.All(cv.Schema({
|
||||
vol.Optional(CONF_TEMPERATURE, default=320): vol.All(vol.Coerce(int), vol.Range(200, 400)),
|
||||
vol.Optional(CONF_DURATION, default='150ms'): vol.All(
|
||||
cv.positive_time_period_milliseconds, vol.Range(max=core.TimePeriod(milliseconds=4032)))
|
||||
|
|
|
@ -24,7 +24,7 @@ INA3221PowerSensor = sensor.sensor_ns.class_('INA3221PowerSensor', sensor.EmptyP
|
|||
|
||||
SENSOR_KEYS = [CONF_BUS_VOLTAGE, CONF_SHUNT_VOLTAGE, CONF_CURRENT, CONF_POWER]
|
||||
|
||||
INA3221_CHANNEL_SCHEMA = vol.All(vol.Schema({
|
||||
INA3221_CHANNEL_SCHEMA = vol.All(cv.Schema({
|
||||
vol.Optional(CONF_BUS_VOLTAGE): cv.nameable(sensor.SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(INA3221VoltageSensor),
|
||||
})),
|
||||
|
|
|
@ -41,7 +41,7 @@ def validate_internal_filter(value):
|
|||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(PulseCounterSensorComponent),
|
||||
vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
|
||||
vol.Optional(CONF_COUNT_MODE): vol.Schema({
|
||||
vol.Optional(CONF_COUNT_MODE): cv.Schema({
|
||||
vol.Required(CONF_RISING_EDGE): COUNT_MODE_SCHEMA,
|
||||
vol.Required(CONF_FALLING_EDGE): COUNT_MODE_SCHEMA,
|
||||
}),
|
||||
|
|
|
@ -35,7 +35,7 @@ def to_code(config):
|
|||
BUILD_FLAGS = '-DUSE_TEMPLATE_SENSOR'
|
||||
|
||||
CONF_SENSOR_TEMPLATE_PUBLISH = 'sensor.template.publish'
|
||||
SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(sensor.Sensor),
|
||||
vol.Required(CONF_STATE): cv.templatable(cv.float_),
|
||||
})
|
||||
|
|
|
@ -12,7 +12,7 @@ SPIComponent = esphome_ns.class_('SPIComponent', Component)
|
|||
SPIDevice = esphome_ns.class_('SPIDevice')
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(SPIComponent),
|
||||
vol.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema,
|
||||
|
|
|
@ -8,7 +8,7 @@ from esphome.cpp_types import App, Component, esphome_ns
|
|||
|
||||
StatusLEDComponent = esphome_ns.class_('StatusLEDComponent', Component)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(StatusLEDComponent),
|
||||
vol.Optional(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema)
|
||||
|
|
|
@ -60,7 +60,7 @@ def validate_speed(value):
|
|||
return value
|
||||
|
||||
|
||||
STEPPER_SCHEMA = vol.Schema({
|
||||
STEPPER_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_MAX_SPEED): validate_speed,
|
||||
vol.Optional(CONF_ACCELERATION): validate_acceleration,
|
||||
vol.Optional(CONF_DECELERATION): validate_acceleration,
|
||||
|
@ -85,7 +85,7 @@ def setup_stepper(stepper_var, config):
|
|||
BUILD_FLAGS = '-DUSE_STEPPER'
|
||||
|
||||
CONF_STEPPER_SET_TARGET = 'stepper.set_target'
|
||||
STEPPER_SET_TARGET_ACTION_SCHEMA = vol.Schema({
|
||||
STEPPER_SET_TARGET_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(Stepper),
|
||||
vol.Required(CONF_TARGET): cv.templatable(cv.int_),
|
||||
})
|
||||
|
@ -105,7 +105,7 @@ def stepper_set_target_to_code(config, action_id, arg_type, template_arg):
|
|||
|
||||
|
||||
CONF_STEPPER_REPORT_POSITION = 'stepper.report_position'
|
||||
STEPPER_REPORT_POSITION_ACTION_SCHEMA = vol.Schema({
|
||||
STEPPER_REPORT_POSITION_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(Stepper),
|
||||
vol.Required(CONF_POSITION): cv.templatable(cv.int_),
|
||||
})
|
||||
|
|
|
@ -31,7 +31,7 @@ def validate_substitution_key(value):
|
|||
return value
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
validate_substitution_key: cv.string_strict,
|
||||
})
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ RCSwitchTypeDTransmitter = remote_ns.class_('RCSwitchTypeDTransmitter', RCSwitch
|
|||
|
||||
def validate_raw(value):
|
||||
if isinstance(value, dict):
|
||||
return vol.Schema({
|
||||
return cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(int32),
|
||||
vol.Required(CONF_DATA): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)],
|
||||
vol.Optional(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)),
|
||||
|
@ -55,29 +55,29 @@ def validate_raw(value):
|
|||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(RemoteTransmitter),
|
||||
vol.Optional(CONF_JVC): vol.Schema({
|
||||
vol.Optional(CONF_JVC): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_LG): vol.Schema({
|
||||
vol.Optional(CONF_LG): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True),
|
||||
}),
|
||||
vol.Optional(CONF_NEC): vol.Schema({
|
||||
vol.Optional(CONF_NEC): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
|
||||
}),
|
||||
vol.Optional(CONF_SAMSUNG): vol.Schema({
|
||||
vol.Optional(CONF_SAMSUNG): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_SONY): vol.Schema({
|
||||
vol.Optional(CONF_SONY): cv.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=12): cv.one_of(12, 15, 20, int=True),
|
||||
}),
|
||||
vol.Optional(CONF_PANASONIC): vol.Schema({
|
||||
vol.Optional(CONF_PANASONIC): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Optional(CONF_RC5): vol.Schema({
|
||||
vol.Optional(CONF_RC5): cv.Schema({
|
||||
vol.Required(CONF_ADDRESS): vol.All(cv.hex_int, vol.Range(min=0, max=0x1F)),
|
||||
vol.Required(CONF_COMMAND): vol.All(cv.hex_int, vol.Range(min=0, max=0x3F)),
|
||||
}),
|
||||
|
@ -88,7 +88,7 @@ PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
|||
vol.Optional(CONF_RC_SWITCH_TYPE_C): RC_SWITCH_TYPE_C_SCHEMA,
|
||||
vol.Optional(CONF_RC_SWITCH_TYPE_D): RC_SWITCH_TYPE_D_SCHEMA,
|
||||
|
||||
vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({
|
||||
vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, cv.Schema({
|
||||
vol.Required(CONF_TIMES): cv.positive_not_null_int,
|
||||
vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds,
|
||||
})),
|
||||
|
|
|
@ -55,7 +55,7 @@ def to_code(config):
|
|||
BUILD_FLAGS = '-DUSE_TEMPLATE_SWITCH'
|
||||
|
||||
CONF_SWITCH_TEMPLATE_PUBLISH = 'switch.template.publish'
|
||||
SWITCH_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
SWITCH_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(switch.Switch),
|
||||
vol.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||
})
|
||||
|
|
|
@ -20,7 +20,7 @@ def validate_data(value):
|
|||
if isinstance(value, str):
|
||||
return value
|
||||
if isinstance(value, list):
|
||||
return vol.Schema([cv.hex_uint8_t])(value)
|
||||
return cv.Schema([cv.hex_uint8_t])(value)
|
||||
raise vol.Invalid("data must either be a string wrapped in quotes or a list of bytes")
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ def to_code(config):
|
|||
BUILD_FLAGS = '-DUSE_TEMPLATE_TEXT_SENSOR'
|
||||
|
||||
CONF_TEXT_SENSOR_TEMPLATE_PUBLISH = 'text_sensor.template.publish'
|
||||
TEXT_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
|
||||
TEXT_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(text_sensor.TextSensor),
|
||||
vol.Required(CONF_STATE): cv.templatable(cv.string_strict),
|
||||
})
|
||||
|
|
|
@ -11,7 +11,7 @@ UARTComponent = esphome_ns.class_('UARTComponent', Component)
|
|||
UARTDevice = esphome_ns.class_('UARTDevice')
|
||||
MULTI_CONF = True
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(UARTComponent),
|
||||
vol.Optional(CONF_TX_PIN): pins.output_pin,
|
||||
vol.Optional(CONF_RX_PIN): pins.input_pin,
|
||||
|
|
|
@ -9,7 +9,7 @@ from esphome.cpp_types import App, Component, StoringController, esphome_ns
|
|||
|
||||
WebServer = esphome_ns.class_('WebServer', Component, StoringController)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(WebServer),
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
vol.Optional(CONF_CSS_URL): cv.string,
|
||||
|
|
|
@ -42,7 +42,7 @@ def validate_channel(value):
|
|||
return value
|
||||
|
||||
|
||||
AP_MANUAL_IP_SCHEMA = vol.Schema({
|
||||
AP_MANUAL_IP_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_STATIC_IP): cv.ipv4,
|
||||
vol.Required(CONF_GATEWAY): cv.ipv4,
|
||||
vol.Required(CONF_SUBNET): cv.ipv4,
|
||||
|
@ -53,7 +53,7 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({
|
|||
vol.Optional(CONF_DNS2, default="1.0.0.1"): cv.ipv4,
|
||||
})
|
||||
|
||||
WIFI_NETWORK_BASE = vol.Schema({
|
||||
WIFI_NETWORK_BASE = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(WiFiAP),
|
||||
vol.Optional(CONF_SSID): cv.ssid,
|
||||
vol.Optional(CONF_PASSWORD): validate_password,
|
||||
|
@ -105,7 +105,7 @@ def validate(config):
|
|||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
CONFIG_SCHEMA = vol.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(WiFiComponent),
|
||||
vol.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA),
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ from esphome.util import safe_print
|
|||
from typing import List, Optional, Tuple, Union # noqa
|
||||
from esphome.core import ConfigType # noqa
|
||||
from esphome.yaml_util import is_secret
|
||||
from esphome.voluptuous_schema import ExtraKeysInvalid
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -414,17 +415,21 @@ def humanize_error(config, validation_error):
|
|||
def _format_vol_invalid(ex, config, path, domain):
|
||||
# type: (vol.Invalid, ConfigType, ConfigPath, basestring) -> unicode
|
||||
message = u''
|
||||
if u'extra keys not allowed' in ex.error_message:
|
||||
try:
|
||||
paren = ex.path[-2]
|
||||
except IndexError:
|
||||
paren = domain
|
||||
try:
|
||||
paren = ex.path[-2]
|
||||
except IndexError:
|
||||
paren = domain
|
||||
|
||||
if isinstance(ex, ExtraKeysInvalid):
|
||||
if ex.candidates:
|
||||
message += u'[{}] is an invalid option for [{}]. Did you mean {}?'.format(
|
||||
ex.path[-1], paren, u', '.join(u'[{}]'.format(x) for x in ex.candidates))
|
||||
else:
|
||||
message += u'[{}] is an invalid option for [{}]. Please check the indentation.'.format(
|
||||
ex.path[-1], paren)
|
||||
elif u'extra keys not allowed' in ex.error_message:
|
||||
message += u'[{}] is an invalid option for [{}].'.format(ex.path[-1], paren)
|
||||
elif u'required key not provided' in ex.error_message:
|
||||
try:
|
||||
paren = ex.path[-2]
|
||||
except IndexError:
|
||||
paren = domain
|
||||
message += u"'{}' is a required option for [{}].".format(ex.path[-1], paren)
|
||||
else:
|
||||
message += humanize_error(_nested_getitem(config, path), ex)
|
||||
|
|
|
@ -17,11 +17,13 @@ from esphome.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY,
|
|||
from esphome.core import CORE, HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \
|
||||
TimePeriodMilliseconds, TimePeriodSeconds
|
||||
from esphome.py_compat import integer_types, string_types, text_type
|
||||
from esphome.voluptuous_schema import _Schema
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
Schema = _Schema
|
||||
port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535))
|
||||
float_ = vol.Coerce(float)
|
||||
positive_float = vol.All(float_, vol.Range(min=0))
|
||||
|
@ -203,7 +205,7 @@ def templatable(other_validators):
|
|||
if isinstance(value, Lambda):
|
||||
return value
|
||||
if isinstance(other_validators, dict):
|
||||
return vol.Schema(other_validators)(value)
|
||||
return Schema(other_validators)(value)
|
||||
return other_validators(value)
|
||||
|
||||
return validator
|
||||
|
@ -273,7 +275,7 @@ def has_at_most_one_key(*keys):
|
|||
TIME_PERIOD_ERROR = "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h"
|
||||
|
||||
time_period_dict = vol.All(
|
||||
dict, vol.Schema({
|
||||
dict, Schema({
|
||||
'days': float_,
|
||||
'hours': float_,
|
||||
'minutes': float_,
|
||||
|
@ -727,17 +729,17 @@ def nameable(*schemas):
|
|||
return validator
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
PLATFORM_SCHEMA = Schema({
|
||||
vol.Required(CONF_PLATFORM): valid,
|
||||
})
|
||||
|
||||
MQTT_COMPONENT_AVAILABILITY_SCHEMA = vol.Schema({
|
||||
MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema({
|
||||
vol.Required(CONF_TOPIC): subscribe_topic,
|
||||
vol.Optional(CONF_PAYLOAD_AVAILABLE, default='online'): mqtt_payload,
|
||||
vol.Optional(CONF_PAYLOAD_NOT_AVAILABLE, default='offline'): mqtt_payload,
|
||||
})
|
||||
|
||||
MQTT_COMPONENT_SCHEMA = vol.Schema({
|
||||
MQTT_COMPONENT_SCHEMA = Schema({
|
||||
vol.Optional(CONF_NAME): string,
|
||||
vol.Optional(CONF_RETAIN): vol.All(requires_component('mqtt'), boolean),
|
||||
vol.Optional(CONF_DISCOVERY): vol.All(requires_component('mqtt'), boolean),
|
||||
|
@ -751,6 +753,6 @@ MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend({
|
|||
vol.Optional(CONF_COMMAND_TOPIC): vol.All(requires_component('mqtt'), subscribe_topic),
|
||||
})
|
||||
|
||||
COMPONENT_SCHEMA = vol.Schema({
|
||||
COMPONENT_SCHEMA = Schema({
|
||||
vol.Optional(CONF_SETUP_PRIORITY): float_
|
||||
})
|
||||
|
|
|
@ -87,11 +87,11 @@ def validate_commit(value):
|
|||
|
||||
ESPHOME_CORE_VERSION_SCHEMA = vol.Any(
|
||||
validate_simple_esphome_core_version,
|
||||
vol.Schema({
|
||||
cv.Schema({
|
||||
vol.Required(CONF_LOCAL): validate_local_esphome_core_version,
|
||||
}),
|
||||
vol.All(
|
||||
vol.Schema({
|
||||
cv.Schema({
|
||||
vol.Optional(CONF_REPOSITORY, default=LIBRARY_URI_REPO): cv.string,
|
||||
vol.Optional(CONF_COMMIT): validate_commit,
|
||||
vol.Optional(CONF_BRANCH): cv.string,
|
||||
|
@ -159,7 +159,7 @@ def default_build_path():
|
|||
return CORE.name
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_NAME): cv.valid_name,
|
||||
vol.Required(CONF_PLATFORM): cv.one_of('ESP8266', 'ESPRESSIF8266', 'ESP32', 'ESPRESSIF32',
|
||||
upper=True),
|
||||
|
@ -168,7 +168,7 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
vol.Optional(CONF_ARDUINO_VERSION, default='recommended'): validate_arduino_version,
|
||||
vol.Optional(CONF_USE_CUSTOM_CODE, default=False): cv.boolean,
|
||||
vol.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string,
|
||||
vol.Optional(CONF_PLATFORMIO_OPTIONS): vol.Schema({
|
||||
vol.Optional(CONF_PLATFORMIO_OPTIONS): cv.Schema({
|
||||
cv.string_strict: vol.Any([cv.string], cv.string),
|
||||
}),
|
||||
vol.Optional(CONF_ESP8266_RESTORE_FROM_FLASH): vol.All(cv.only_on_esp8266, cv.boolean),
|
||||
|
|
|
@ -320,13 +320,13 @@ def pin_mode(value):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
GPIO_FULL_OUTPUT_PIN_SCHEMA = vol.Schema({
|
||||
GPIO_FULL_OUTPUT_PIN_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_NUMBER): output_pin,
|
||||
vol.Optional(CONF_MODE): pin_mode,
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
})
|
||||
|
||||
GPIO_FULL_INPUT_PIN_SCHEMA = vol.Schema({
|
||||
GPIO_FULL_INPUT_PIN_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_NUMBER): input_pin,
|
||||
vol.Optional(CONF_MODE): pin_mode,
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
|
@ -351,7 +351,7 @@ def shorthand_input_pullup_pin(value):
|
|||
I2CDevice = esphome_ns.class_('I2CDevice')
|
||||
PCF8574Component = io_ns.class_('PCF8574Component', Component, I2CDevice)
|
||||
|
||||
PCF8574_OUTPUT_PIN_SCHEMA = vol.Schema({
|
||||
PCF8574_OUTPUT_PIN_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_PCF8574): cv.use_variable_id(PCF8574Component),
|
||||
vol.Required(CONF_NUMBER): vol.Coerce(int),
|
||||
vol.Optional(CONF_MODE): cv.one_of("OUTPUT", upper=True),
|
||||
|
|
161
esphome/voluptuous_schema.py
Normal file
161
esphome/voluptuous_schema.py
Normal file
|
@ -0,0 +1,161 @@
|
|||
import difflib
|
||||
import itertools
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from esphome.py_compat import string_types
|
||||
|
||||
|
||||
class ExtraKeysInvalid(vol.Invalid):
|
||||
def __init__(self, *arg, **kwargs):
|
||||
self.candidates = kwargs.pop('candidates')
|
||||
vol.Invalid.__init__(self, *arg, **kwargs)
|
||||
|
||||
|
||||
# pylint: disable=protected-access, unidiomatic-typecheck
|
||||
class _Schema(vol.Schema):
|
||||
"""Custom cv.Schema that prints similar keys on error."""
|
||||
def _compile_mapping(self, schema, invalid_msg=None):
|
||||
invalid_msg = invalid_msg or 'mapping value'
|
||||
|
||||
# Keys that may be required
|
||||
all_required_keys = set(key for key in schema
|
||||
if key is not vol.Extra and
|
||||
((self.required and not isinstance(key, (vol.Optional, vol.Remove)))
|
||||
or isinstance(key, vol.Required)))
|
||||
|
||||
# Keys that may have defaults
|
||||
all_default_keys = set(key for key in schema
|
||||
if isinstance(key, (vol.Required, vol.Optional)))
|
||||
|
||||
_compiled_schema = {}
|
||||
for skey, svalue in vol.iteritems(schema):
|
||||
new_key = self._compile(skey)
|
||||
new_value = self._compile(svalue)
|
||||
_compiled_schema[skey] = (new_key, new_value)
|
||||
|
||||
candidates = list(vol.schema_builder._iterate_mapping_candidates(_compiled_schema))
|
||||
|
||||
# After we have the list of candidates in the correct order, we want to apply some
|
||||
# optimization so that each
|
||||
# key in the data being validated will be matched against the relevant schema keys only.
|
||||
# No point in matching against different keys
|
||||
additional_candidates = []
|
||||
candidates_by_key = {}
|
||||
for skey, (ckey, cvalue) in candidates:
|
||||
if type(skey) in vol.primitive_types:
|
||||
candidates_by_key.setdefault(skey, []).append((skey, (ckey, cvalue)))
|
||||
elif isinstance(skey, vol.Marker) and type(skey.schema) in vol.primitive_types:
|
||||
candidates_by_key.setdefault(skey.schema, []).append((skey, (ckey, cvalue)))
|
||||
else:
|
||||
# These are wildcards such as 'int', 'str', 'Remove' and others which should be
|
||||
# applied to all keys
|
||||
additional_candidates.append((skey, (ckey, cvalue)))
|
||||
|
||||
key_names = []
|
||||
for skey in schema:
|
||||
if isinstance(skey, string_types):
|
||||
key_names.append(skey)
|
||||
elif isinstance(skey, vol.Marker) and isinstance(skey.schema, string_types):
|
||||
key_names.append(skey.schema)
|
||||
|
||||
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]
|
||||
remove_key = False
|
||||
|
||||
# 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 = []
|
||||
# check if the key is marked for removal
|
||||
is_remove = new_key is vol.Remove
|
||||
try:
|
||||
cval = cvalue(key_path, value)
|
||||
# include if it's not marked for removal
|
||||
if not is_remove:
|
||||
out[new_key] = cval
|
||||
else:
|
||||
remove_key = True
|
||||
continue
|
||||
except vol.MultipleInvalid as e:
|
||||
exception_errors.extend(e.errors)
|
||||
except vol.Invalid as e:
|
||||
exception_errors.append(e)
|
||||
|
||||
if exception_errors:
|
||||
if is_remove or remove_key:
|
||||
continue
|
||||
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 remove_key:
|
||||
# remove key
|
||||
continue
|
||||
elif self.extra == vol.ALLOW_EXTRA:
|
||||
out[key] = value
|
||||
elif self.extra != vol.REMOVE_EXTRA:
|
||||
if isinstance(key, string_types) 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 = key.msg if hasattr(key, 'msg') and key.msg else 'required key not provided'
|
||||
errors.append(vol.RequiredFieldInvalid(msg, path + [key]))
|
||||
if errors:
|
||||
raise vol.MultipleInvalid(errors)
|
||||
|
||||
return out
|
||||
|
||||
return validate_mapping
|
Loading…
Reference in a new issue