1 """Selectors for Home Assistant."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Mapping, Sequence
6 from enum
import StrEnum
7 from functools
import cache
9 from typing
import Any, Literal, Required, TypedDict, cast
12 import voluptuous
as vol
20 from .
import config_validation
as cv
22 SELECTORS: decorator.Registry[str, type[Selector]] = decorator.Registry()
26 """Get selector class type."""
27 if not isinstance(config, dict):
28 raise vol.Invalid(
"Expected a dictionary")
31 raise vol.Invalid(f
"Only one type can be specified. Found {', '.join(config)}")
33 selector_type: str =
list(config)[0]
35 if (selector_class := SELECTORS.get(selector_type))
is None:
36 raise vol.Invalid(f
"Unknown selector type {selector_type} found")
42 """Instantiate a selector."""
44 selector_type =
list(config)[0]
46 return selector_class(config[selector_type])
50 """Validate a selector."""
52 selector_type =
list(config)[0]
55 if config[selector_type]
is None:
56 return {selector_type: {}}
59 selector_type: cast(dict, selector_class.CONFIG_SCHEMA(config[selector_type]))
64 """Base class for selectors."""
66 CONFIG_SCHEMA: Callable
70 def __init__(self, config: Mapping[str, Any] |
None =
None) ->
None:
71 """Instantiate a selector."""
76 self.config = self.CONFIG_SCHEMA(config)
78 def __eq__(self, other: object) -> bool:
80 if not isinstance(other, Selector):
83 return self.selector_type == other.selector_type
and self.config == other.config
86 """Serialize Selector for voluptuous_serialize."""
87 return {
"selector": {self.selector_type: self.config}}
92 """Return a cached lookup of an entity feature enum.
94 This will import a module from disk and is run from an executor when
95 loading the services schema files.
97 module = importlib.import_module(f
"homeassistant.components.{domain}")
98 enum = getattr(module, enum_name)
99 feature = getattr(enum, feature_name)
100 return cast(int, feature.value)
104 """Validate a supported feature and resolve an enum string to its value."""
107 domain, enum, feature = supported_feature.split(
".", 2)
108 except ValueError
as exc:
110 f
"Invalid supported feature '{supported_feature}', expected "
111 "<domain>.<enum>.<member>"
116 except (ModuleNotFoundError, AttributeError)
as exc:
117 raise vol.Invalid(f
"Unknown supported feature '{supported_feature}'")
from exc
121 """Validate a supported feature and resolve an enum string to its value."""
123 if isinstance(supported_features, int):
124 return supported_features
128 for supported_feature
in supported_features:
134 ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA = vol.Schema(
137 vol.Optional(
"integration"): str,
139 vol.Optional(
"domain"): vol.All(cv.ensure_list, [str]),
141 vol.Optional(
"device_class"): vol.All(cv.ensure_list, [str]),
143 vol.Optional(
"supported_features"): [
144 vol.All(cv.ensure_list, [str], _validate_supported_features)
151 """Class to represent a single entity selector config."""
154 domain: str | list[str]
155 device_class: str | list[str]
156 supported_features: list[str]
159 DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA = vol.Schema(
162 vol.Optional(
"integration"): str,
164 vol.Optional(
"manufacturer"): str,
166 vol.Optional(
"model"): str,
168 vol.Optional(
"entity"): vol.All(
169 cv.ensure_list, [ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA]
176 """Class to represent a single device selector config."""
184 """Class to represent an action selector config."""
187 @SELECTORS.register(
"action")
189 """Selector of an action sequence (script syntax)."""
191 selector_type =
"action"
193 CONFIG_SCHEMA = vol.Schema({})
195 def __init__(self, config: ActionSelectorConfig |
None =
None) ->
None:
196 """Instantiate a selector."""
200 """Validate the passed selection."""
205 """Class to represent an addon selector config."""
211 @SELECTORS.register("addon")
213 """Selector of a add-on."""
215 selector_type =
"addon"
217 CONFIG_SCHEMA = vol.Schema(
219 vol.Optional(
"name"): str,
220 vol.Optional(
"slug"): str,
224 def __init__(self, config: AddonSelectorConfig |
None =
None) ->
None:
225 """Instantiate a selector."""
229 """Validate the passed selection."""
230 addon: str = vol.Schema(str)(data)
235 """Class to represent an area selector config."""
237 entity: EntityFilterSelectorConfig | list[EntityFilterSelectorConfig]
238 device: DeviceFilterSelectorConfig | list[DeviceFilterSelectorConfig]
242 @SELECTORS.register("area")
244 """Selector of a single or list of areas."""
246 selector_type =
"area"
248 CONFIG_SCHEMA = vol.Schema(
250 vol.Optional(
"entity"): vol.All(
252 [ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA],
254 vol.Optional(
"device"): vol.All(
256 [DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA],
258 vol.Optional(
"multiple", default=
False): cv.boolean,
262 def __init__(self, config: AreaSelectorConfig |
None =
None) ->
None:
263 """Instantiate a selector."""
267 """Validate the passed selection."""
268 if not self.config[
"multiple"]:
269 area_id: str = vol.Schema(str)(data)
271 if not isinstance(data, list):
272 raise vol.Invalid(
"Value should be a list")
273 return [vol.Schema(str)(val)
for val
in data]
277 """Class to represent an assist pipeline selector config."""
280 @SELECTORS.register("assist_pipeline")
282 """Selector for an assist pipeline."""
284 selector_type =
"assist_pipeline"
286 CONFIG_SCHEMA = vol.Schema({})
288 def __init__(self, config: AssistPipelineSelectorConfig |
None =
None) ->
None:
289 """Instantiate a selector."""
293 """Validate the passed selection."""
294 pipeline: str = vol.Schema(str)(data)
299 """Class to represent an attribute selector config."""
301 entity_id: Required[str]
302 hide_attributes: list[str]
305 @SELECTORS.register("attribute")
307 """Selector for an entity attribute."""
309 selector_type =
"attribute"
311 CONFIG_SCHEMA = vol.Schema(
313 vol.Required(
"entity_id"): cv.entity_id,
316 vol.Optional(
"hide_attributes"): [str],
320 def __init__(self, config: AttributeSelectorConfig) ->
None:
321 """Instantiate a selector."""
325 """Validate the passed selection."""
326 attribute: str = vol.Schema(str)(data)
331 """Class to represent a backup location selector config."""
334 @SELECTORS.register("backup_location")
336 """Selector of a backup location."""
338 selector_type =
"backup_location"
340 CONFIG_SCHEMA = vol.Schema({})
342 def __init__(self, config: BackupLocationSelectorConfig |
None =
None) ->
None:
343 """Instantiate a selector."""
347 """Validate the passed selection."""
348 name: str = vol.Match(
r"^(?:\/backup|\w+)$")(data)
353 """Class to represent a boolean selector config."""
356 @SELECTORS.register(
"boolean")
358 """Selector of a boolean value."""
360 selector_type =
"boolean"
362 CONFIG_SCHEMA = vol.Schema({})
364 def __init__(self, config: BooleanSelectorConfig |
None =
None) ->
None:
365 """Instantiate a selector."""
369 """Validate the passed selection."""
370 value: bool = vol.Coerce(bool)(data)
375 """Class to represent a color RGB selector config."""
378 @SELECTORS.register(
"color_rgb")
380 """Selector of an RGB color value."""
382 selector_type =
"color_rgb"
384 CONFIG_SCHEMA = vol.Schema({})
386 def __init__(self, config: ColorRGBSelectorConfig |
None =
None) ->
None:
387 """Instantiate a selector."""
391 """Validate the passed selection."""
392 value: list[int] = vol.All(list, vol.ExactSequence((cv.byte,) * 3))(data)
397 """Class to represent a color temp selector config."""
399 unit: ColorTempSelectorUnit
407 """Possible units for a color temperature selector."""
413 @SELECTORS.register("color_temp")
415 """Selector of an color temperature."""
417 selector_type =
"color_temp"
419 CONFIG_SCHEMA = vol.Schema(
421 vol.Optional(
"unit", default=ColorTempSelectorUnit.MIRED): vol.All(
422 vol.Coerce(ColorTempSelectorUnit),
lambda val: val.value
424 vol.Optional(
"min"): vol.Coerce(int),
425 vol.Optional(
"max"): vol.Coerce(int),
426 vol.Optional(
"max_mireds"): vol.Coerce(int),
427 vol.Optional(
"min_mireds"): vol.Coerce(int),
431 def __init__(self, config: ColorTempSelectorConfig |
None =
None) ->
None:
432 """Instantiate a selector."""
436 """Validate the passed selection."""
437 range_min = self.config.
get(
"min")
438 range_max = self.config.
get(
"max")
440 if range_min
is None:
441 range_min = self.config.
get(
"min_mireds")
443 if range_max
is None:
444 range_max = self.config.
get(
"max_mireds")
446 value: int = vol.All(
457 """Class to represent an condition selector config."""
460 @SELECTORS.register(
"condition")
462 """Selector of an condition sequence (script syntax)."""
464 selector_type =
"condition"
466 CONFIG_SCHEMA = vol.Schema({})
468 def __init__(self, config: ConditionSelectorConfig |
None =
None) ->
None:
469 """Instantiate a selector."""
473 """Validate the passed selection."""
474 return vol.Schema(cv.CONDITIONS_SCHEMA)(data)
478 """Class to represent a config entry selector config."""
483 @SELECTORS.register("config_entry")
485 """Selector of a config entry."""
487 selector_type =
"config_entry"
489 CONFIG_SCHEMA = vol.Schema(
491 vol.Optional(
"integration"): str,
495 def __init__(self, config: ConfigEntrySelectorConfig |
None =
None) ->
None:
496 """Instantiate a selector."""
500 """Validate the passed selection."""
501 config: str = vol.Schema(str)(data)
506 """Class to represent a constant selector config."""
510 value: str | int | bool
513 @SELECTORS.register("constant")
515 """Constant selector."""
517 selector_type =
"constant"
519 CONFIG_SCHEMA = vol.Schema(
521 vol.Optional(
"label"): str,
522 vol.Optional(
"translation_key"): cv.string,
523 vol.Required(
"value"): vol.Any(str, int, bool),
527 def __init__(self, config: ConstantSelectorConfig) ->
None:
528 """Instantiate a selector."""
532 """Validate the passed selection."""
533 vol.Schema(self.config[
"value"])(data)
534 return self.config[
"value"]
538 """Possible error correction levels for QR code selector."""
542 QUARTILE =
"quartile"
547 """Class to represent a QR code selector config."""
551 error_correction_level: QrErrorCorrectionLevel
554 @SELECTORS.register("qr_code")
556 """QR code selector."""
558 selector_type =
"qr_code"
560 CONFIG_SCHEMA = vol.Schema(
562 vol.Required(
"data"): str,
563 vol.Optional(
"scale"): int,
564 vol.Optional(
"error_correction_level"): vol.All(
565 vol.Coerce(QrErrorCorrectionLevel),
lambda val: val.value
570 def __init__(self, config: QrCodeSelectorConfig) ->
None:
571 """Instantiate a selector."""
575 """Validate the passed selection."""
576 vol.Schema(vol.Any(str,
None))(data)
577 return self.config[
"data"]
581 """Class to represent a conversation agent selector config."""
586 @SELECTORS.register("conversation_agent")
588 """Selector for a conversation agent."""
590 selector_type =
"conversation_agent"
592 CONFIG_SCHEMA = vol.Schema(
594 vol.Optional(
"language"): str,
598 def __init__(self, config: ConversationAgentSelectorConfig |
None =
None) ->
None:
599 """Instantiate a selector."""
603 """Validate the passed selection."""
604 agent: str = vol.Schema(str)(data)
609 """Class to represent a country selector config."""
615 @SELECTORS.register("country")
617 """Selector for a single-choice country select."""
619 selector_type =
"country"
621 CONFIG_SCHEMA = vol.Schema(
623 vol.Optional(
"countries"): [str],
624 vol.Optional(
"no_sort", default=
False): cv.boolean,
628 def __init__(self, config: CountrySelectorConfig |
None =
None) ->
None:
629 """Instantiate a selector."""
633 """Validate the passed selection."""
634 country: str = vol.Schema(str)(data)
635 if "countries" in self.config
and (
636 country
not in self.config[
"countries"]
or country
not in COUNTRIES
638 raise vol.Invalid(f
"Value {country} is not a valid option")
643 """Class to represent a date selector config."""
646 @SELECTORS.register(
"date")
648 """Selector of a date."""
650 selector_type =
"date"
652 CONFIG_SCHEMA = vol.Schema({})
654 def __init__(self, config: DateSelectorConfig |
None =
None) ->
None:
655 """Instantiate a selector."""
659 """Validate the passed selection."""
665 """Class to represent a date time selector config."""
668 @SELECTORS.register(
"datetime")
670 """Selector of a datetime."""
672 selector_type =
"datetime"
674 CONFIG_SCHEMA = vol.Schema({})
676 def __init__(self, config: DateTimeSelectorConfig |
None =
None) ->
None:
677 """Instantiate a selector."""
681 """Validate the passed selection."""
687 """Class to represent a device selector config."""
689 entity: EntityFilterSelectorConfig | list[EntityFilterSelectorConfig]
691 filter: DeviceFilterSelectorConfig | list[DeviceFilterSelectorConfig]
694 @SELECTORS.register("device")
696 """Selector of a single or list of devices."""
698 selector_type =
"device"
700 CONFIG_SCHEMA = DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA.extend(
702 vol.Optional(
"multiple", default=
False): cv.boolean,
703 vol.Optional(
"filter"): vol.All(
705 [DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA],
710 def __init__(self, config: DeviceSelectorConfig |
None =
None) ->
None:
711 """Instantiate a selector."""
715 """Validate the passed selection."""
716 if not self.config[
"multiple"]:
717 device_id: str = vol.Schema(str)(data)
719 if not isinstance(data, list):
720 raise vol.Invalid(
"Value should be a list")
721 return [vol.Schema(str)(val)
for val
in data]
725 """Class to represent a duration selector config."""
728 enable_millisecond: bool
732 @SELECTORS.register("duration")
734 """Selector for a duration."""
736 selector_type =
"duration"
738 CONFIG_SCHEMA = vol.Schema(
742 vol.Optional(
"enable_day"): cv.boolean,
744 vol.Optional(
"enable_millisecond"): cv.boolean,
746 vol.Optional(
"allow_negative"): cv.boolean,
750 def __init__(self, config: DurationSelectorConfig |
None =
None) ->
None:
751 """Instantiate a selector."""
755 """Validate the passed selection."""
756 if self.config.
get(
"allow_negative",
True):
757 cv.time_period_dict(data)
759 cv.positive_time_period_dict(data)
760 return cast(dict[str, float], data)
764 """Class to represent an entity selector config."""
766 exclude_entities: list[str]
767 include_entities: list[str]
769 filter: EntityFilterSelectorConfig | list[EntityFilterSelectorConfig]
772 @SELECTORS.register("entity")
774 """Selector of a single or list of entities."""
776 selector_type =
"entity"
778 CONFIG_SCHEMA = ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA.extend(
780 vol.Optional(
"exclude_entities"): [str],
781 vol.Optional(
"include_entities"): [str],
782 vol.Optional(
"multiple", default=
False): cv.boolean,
783 vol.Optional(
"filter"): vol.All(
785 [ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA],
790 def __init__(self, config: EntitySelectorConfig |
None =
None) ->
None:
791 """Instantiate a selector."""
795 """Validate the passed selection."""
797 include_entities = self.config.
get(
"include_entities")
798 exclude_entities = self.config.
get(
"exclude_entities")
801 e_or_u = cv.entity_id_or_uuid(e_or_u)
804 if allowed_domains := cv.ensure_list(self.config.
get(
"domain")):
806 if domain
not in allowed_domains:
808 f
"Entity {e_or_u} belongs to domain {domain}, "
809 f
"expected {allowed_domains}"
812 vol.In(include_entities)(e_or_u)
814 vol.NotIn(exclude_entities)(e_or_u)
817 if not self.config[
"multiple"]:
819 if not isinstance(data, list):
820 raise vol.Invalid(
"Value should be a list")
821 return cast(list, vol.Schema([validate])(data))
825 """Class to represent an floor selector config."""
827 entity: EntityFilterSelectorConfig | list[EntityFilterSelectorConfig]
828 device: DeviceFilterSelectorConfig | list[DeviceFilterSelectorConfig]
832 @SELECTORS.register("floor")
834 """Selector of a single or list of floors."""
836 selector_type =
"floor"
838 CONFIG_SCHEMA = vol.Schema(
840 vol.Optional(
"entity"): vol.All(
842 [ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA],
844 vol.Optional(
"device"): vol.All(
846 [DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA],
848 vol.Optional(
"multiple", default=
False): cv.boolean,
852 def __init__(self, config: FloorSelectorConfig |
None =
None) ->
None:
853 """Instantiate a selector."""
857 """Validate the passed selection."""
858 if not self.config[
"multiple"]:
859 floor_id: str = vol.Schema(str)(data)
861 if not isinstance(data, list):
862 raise vol.Invalid(
"Value should be a list")
863 return [vol.Schema(str)(val)
for val
in data]
867 """Class to represent an icon selector config."""
872 @SELECTORS.register("icon")
874 """Selector for an icon."""
876 selector_type =
"icon"
878 CONFIG_SCHEMA = vol.Schema(
879 {vol.Optional(
"placeholder"): str}
883 def __init__(self, config: IconSelectorConfig |
None =
None) ->
None:
884 """Instantiate a selector."""
888 """Validate the passed selection."""
889 icon: str = vol.Schema(str)(data)
894 """Class to represent a label selector config."""
899 @SELECTORS.register("label")
901 """Selector of a single or list of labels."""
903 selector_type =
"label"
905 CONFIG_SCHEMA = vol.Schema(
907 vol.Optional(
"multiple", default=
False): cv.boolean,
911 def __init__(self, config: LabelSelectorConfig |
None =
None) ->
None:
912 """Instantiate a selector."""
916 """Validate the passed selection."""
917 if not self.config[
"multiple"]:
918 label_id: str = vol.Schema(str)(data)
920 if not isinstance(data, list):
921 raise vol.Invalid(
"Value should be a list")
922 return [vol.Schema(str)(val)
for val
in data]
926 """Class to represent an language selector config."""
933 @SELECTORS.register("language")
935 """Selector for an language."""
937 selector_type =
"language"
939 CONFIG_SCHEMA = vol.Schema(
941 vol.Optional(
"languages"): [str],
942 vol.Optional(
"native_name", default=
False): cv.boolean,
943 vol.Optional(
"no_sort", default=
False): cv.boolean,
947 def __init__(self, config: LanguageSelectorConfig |
None =
None) ->
None:
948 """Instantiate a selector."""
952 """Validate the passed selection."""
953 language: str = vol.Schema(str)(data)
954 if "languages" in self.config
and language
not in self.config[
"languages"]:
955 raise vol.Invalid(f
"Value {language} is not a valid option")
960 """Class to represent a location selector config."""
966 @SELECTORS.register("location")
968 """Selector for a location."""
970 selector_type =
"location"
972 CONFIG_SCHEMA = vol.Schema(
973 {vol.Optional(
"radius"): bool, vol.Optional(
"icon"): str}
975 DATA_SCHEMA = vol.Schema(
977 vol.Required(
"latitude"): vol.Coerce(float),
978 vol.Required(
"longitude"): vol.Coerce(float),
979 vol.Optional(
"radius"): vol.Coerce(float),
983 def __init__(self, config: LocationSelectorConfig |
None =
None) ->
None:
984 """Instantiate a selector."""
988 """Validate the passed selection."""
989 location: dict[str, float] = self.
DATA_SCHEMADATA_SCHEMA(data)
994 """Class to represent a media selector config."""
997 @SELECTORS.register(
"media")
999 """Selector for media."""
1001 selector_type =
"media"
1003 CONFIG_SCHEMA = vol.Schema({})
1004 DATA_SCHEMA = vol.Schema(
1007 vol.Required(
"entity_id"): cv.entity_id_or_uuid,
1009 vol.Required(
"media_content_id"): str,
1011 vol.Required(
"media_content_type"): str,
1012 vol.Remove(
"metadata"): dict,
1016 def __init__(self, config: MediaSelectorConfig |
None =
None) ->
None:
1017 """Instantiate a selector."""
1021 """Validate the passed selection."""
1022 media: dict[str, float] = self.
DATA_SCHEMADATA_SCHEMA(data)
1027 """Class to represent a number selector config."""
1031 step: float | Literal[
"any"]
1032 unit_of_measurement: str
1033 mode: NumberSelectorMode
1037 """Possible modes for a number selector."""
1044 """Validate configuration."""
1045 if data[
"mode"] ==
"box":
1048 if "min" not in data
or "max" not in data:
1049 raise vol.Invalid(
"min and max are required in slider mode")
1054 @SELECTORS.register("number")
1056 """Selector of a numeric value."""
1058 selector_type =
"number"
1060 CONFIG_SCHEMA = vol.All(
1063 vol.Optional(
"min"): vol.Coerce(float),
1064 vol.Optional(
"max"): vol.Coerce(float),
1067 vol.Optional(
"step", default=1): vol.Any(
1068 "any", vol.All(vol.Coerce(float), vol.Range(min=1e-3))
1070 vol.Optional(CONF_UNIT_OF_MEASUREMENT): str,
1071 vol.Optional(CONF_MODE, default=NumberSelectorMode.SLIDER): vol.All(
1072 vol.Coerce(NumberSelectorMode),
lambda val: val.value
1079 def __init__(self, config: NumberSelectorConfig |
None =
None) ->
None:
1080 """Instantiate a selector."""
1084 """Validate the passed selection."""
1085 value: float = vol.Coerce(float)(data)
1087 if "min" in self.config
and value < self.config[
"min"]:
1088 raise vol.Invalid(f
"Value {value} is too small")
1090 if "max" in self.config
and value > self.config[
"max"]:
1091 raise vol.Invalid(f
"Value {value} is too large")
1097 """Class to represent an object selector config."""
1100 @SELECTORS.register(
"object")
1102 """Selector for an arbitrary object."""
1104 selector_type =
"object"
1106 CONFIG_SCHEMA = vol.Schema({})
1108 def __init__(self, config: ObjectSelectorConfig |
None =
None) ->
None:
1109 """Instantiate a selector."""
1113 """Validate the passed selection."""
1117 select_option = vol.All(
1121 vol.Required(
"value"): str,
1122 vol.Required(
"label"): str,
1129 """Class to represent a select option dict."""
1136 """Possible modes for a number selector."""
1139 DROPDOWN =
"dropdown"
1143 """Class to represent a select selector config."""
1145 options: Required[Sequence[SelectOptionDict] | Sequence[str]]
1148 mode: SelectSelectorMode
1149 translation_key: str
1153 @SELECTORS.register("select")
1155 """Selector for an single-choice input select."""
1157 selector_type =
"select"
1159 CONFIG_SCHEMA = vol.Schema(
1161 vol.Required(
"options"): vol.All(vol.Any([str], [select_option])),
1162 vol.Optional(
"multiple", default=
False): cv.boolean,
1163 vol.Optional(
"custom_value", default=
False): cv.boolean,
1164 vol.Optional(
"mode"): vol.All(
1165 vol.Coerce(SelectSelectorMode),
lambda val: val.value
1167 vol.Optional(
"translation_key"): cv.string,
1168 vol.Optional(
"sort", default=
False): cv.boolean,
1172 def __init__(self, config: SelectSelectorConfig) ->
None:
1173 """Instantiate a selector."""
1177 """Validate the passed selection."""
1178 options: Sequence[str] = []
1179 if config_options := self.config[
"options"]:
1180 if isinstance(config_options[0], str):
1181 options = cast(Sequence[str], config_options)
1185 for option
in cast(Sequence[SelectOptionDict], config_options)
1188 parent_schema: vol.In | vol.Any = vol.In(options)
1189 if self.config[
"custom_value"]:
1190 parent_schema = vol.Any(parent_schema, str)
1192 if not self.config[
"multiple"]:
1193 return parent_schema(vol.Schema(str)(data))
1194 if not isinstance(data, list):
1195 raise vol.Invalid(
"Value should be a list")
1196 return [parent_schema(vol.Schema(str)(val))
for val
in data]
1200 """Class to represent a target selector config."""
1202 entity: EntityFilterSelectorConfig | list[EntityFilterSelectorConfig]
1203 device: DeviceFilterSelectorConfig | list[DeviceFilterSelectorConfig]
1207 """Class to represent an state selector config."""
1209 entity_id: Required[str]
1212 @SELECTORS.register("state")
1214 """Selector for an entity state."""
1216 selector_type =
"state"
1218 CONFIG_SCHEMA = vol.Schema(
1220 vol.Required(
"entity_id"): cv.entity_id,
1229 def __init__(self, config: StateSelectorConfig) ->
None:
1230 """Instantiate a selector."""
1234 """Validate the passed selection."""
1235 state: str = vol.Schema(str)(data)
1239 @SELECTORS.register("target")
1241 """Selector of a target value (area ID, device ID, entity ID etc).
1243 Value should follow cv.TARGET_SERVICE_FIELDS format.
1246 selector_type =
"target"
1248 CONFIG_SCHEMA = vol.Schema(
1250 vol.Optional(
"entity"): vol.All(
1252 [ENTITY_FILTER_SELECTOR_CONFIG_SCHEMA],
1254 vol.Optional(
"device"): vol.All(
1256 [DEVICE_FILTER_SELECTOR_CONFIG_SCHEMA],
1261 TARGET_SELECTION_SCHEMA = vol.Schema(cv.TARGET_SERVICE_FIELDS)
1263 def __init__(self, config: TargetSelectorConfig |
None =
None) ->
None:
1264 """Instantiate a selector."""
1268 """Validate the passed selection."""
1274 """Class to represent an template selector config."""
1277 @SELECTORS.register(
"template")
1279 """Selector for an template."""
1281 selector_type =
"template"
1283 CONFIG_SCHEMA = vol.Schema({})
1285 def __init__(self, config: TemplateSelectorConfig |
None =
None) ->
None:
1286 """Instantiate a selector."""
1290 """Validate the passed selection."""
1291 template = cv.template(data)
1292 return template.template
1296 """Class to represent a text selector config."""
1301 type: TextSelectorType
1307 """Enum for text selector types."""
1311 DATETIME_LOCAL =
"datetime-local"
1315 PASSWORD =
"password"
1324 @SELECTORS.register("text")
1326 """Selector for a multi-line text string."""
1328 selector_type =
"text"
1330 CONFIG_SCHEMA = vol.Schema(
1332 vol.Optional(
"multiline", default=
False): bool,
1333 vol.Optional(
"prefix"): str,
1334 vol.Optional(
"suffix"): str,
1337 vol.Optional(
"type"): vol.All(
1338 vol.Coerce(TextSelectorType),
lambda val: val.value
1340 vol.Optional(
"autocomplete"): str,
1341 vol.Optional(
"multiple", default=
False): bool,
1345 def __init__(self, config: TextSelectorConfig |
None =
None) ->
None:
1346 """Instantiate a selector."""
1349 def __call__(self, data: Any) -> str | list[str]:
1350 """Validate the passed selection."""
1351 if not self.config[
"multiple"]:
1352 text: str = vol.Schema(str)(data)
1354 if not isinstance(data, list):
1355 raise vol.Invalid(
"Value should be a list")
1356 return [vol.Schema(str)(val)
for val
in data]
1360 """Class to represent a theme selector config."""
1363 @SELECTORS.register(
"theme")
1365 """Selector for an theme."""
1367 selector_type =
"theme"
1369 CONFIG_SCHEMA = vol.Schema(
1371 vol.Optional(
"include_default", default=
False): cv.boolean,
1375 def __init__(self, config: ThemeSelectorConfig |
None =
None) ->
None:
1376 """Instantiate a selector."""
1380 """Validate the passed selection."""
1381 theme: str = vol.Schema(str)(data)
1386 """Class to represent a time selector config."""
1389 @SELECTORS.register(
"time")
1391 """Selector of a time value."""
1393 selector_type =
"time"
1395 CONFIG_SCHEMA = vol.Schema({})
1397 def __init__(self, config: TimeSelectorConfig |
None =
None) ->
None:
1398 """Instantiate a selector."""
1402 """Validate the passed selection."""
1404 return cast(str, data)
1408 """Class to represent an trigger selector config."""
1411 @SELECTORS.register(
"trigger")
1413 """Selector of a trigger sequence (script syntax)."""
1415 selector_type =
"trigger"
1417 CONFIG_SCHEMA = vol.Schema({})
1419 def __init__(self, config: TriggerSelectorConfig |
None =
None) ->
None:
1420 """Instantiate a selector."""
1424 """Validate the passed selection."""
1425 return vol.Schema(cv.TRIGGER_SCHEMA)(data)
1429 """Class to represent a file selector config."""
1434 @SELECTORS.register("file")
1436 """Selector of a file."""
1438 selector_type =
"file"
1440 CONFIG_SCHEMA = vol.Schema(
1443 vol.Required(
"accept"): str,
1447 def __init__(self, config: FileSelectorConfig) ->
None:
1448 """Instantiate a selector."""
1452 """Validate the passed selection."""
1453 if not isinstance(data, str):
1454 raise vol.Invalid(
"Value should be a string")
1461 dumper.add_representer(
1463 lambda dumper, value: dumper.represent_odict(
1464 dumper,
"tag:yaml.org,2002:map", value.serialize()
None __init__(self, ActionSelectorConfig|None config=None)
Any __call__(self, Any data)
str __call__(self, Any data)
None __init__(self, AddonSelectorConfig|None config=None)
None __init__(self, AreaSelectorConfig|None config=None)
str|list[str] __call__(self, Any data)
None __init__(self, AssistPipelineSelectorConfig|None config=None)
str __call__(self, Any data)
None __init__(self, AttributeSelectorConfig config)
str __call__(self, Any data)
None __init__(self, BackupLocationSelectorConfig|None config=None)
str __call__(self, Any data)
bool __call__(self, Any data)
None __init__(self, BooleanSelectorConfig|None config=None)
list[int] __call__(self, Any data)
None __init__(self, ColorRGBSelectorConfig|None config=None)
int __call__(self, Any data)
None __init__(self, ColorTempSelectorConfig|None config=None)
None __init__(self, ConditionSelectorConfig|None config=None)
Any __call__(self, Any data)
None __init__(self, ConfigEntrySelectorConfig|None config=None)
str __call__(self, Any data)
Any __call__(self, Any data)
None __init__(self, ConstantSelectorConfig config)
str __call__(self, Any data)
None __init__(self, ConversationAgentSelectorConfig|None config=None)
Any __call__(self, Any data)
None __init__(self, CountrySelectorConfig|None config=None)
None __init__(self, DateSelectorConfig|None config=None)
Any __call__(self, Any data)
None __init__(self, DateTimeSelectorConfig|None config=None)
Any __call__(self, Any data)
str|list[str] __call__(self, Any data)
None __init__(self, DeviceSelectorConfig|None config=None)
None __init__(self, DurationSelectorConfig|None config=None)
dict[str, float] __call__(self, Any data)
None __init__(self, EntitySelectorConfig|None config=None)
str|list[str] __call__(self, Any data)
str __call__(self, Any data)
None __init__(self, FileSelectorConfig config)
str|list[str] __call__(self, Any data)
None __init__(self, FloorSelectorConfig|None config=None)
None __init__(self, IconSelectorConfig|None config=None)
str __call__(self, Any data)
str|list[str] __call__(self, Any data)
None __init__(self, LabelSelectorConfig|None config=None)
str __call__(self, Any data)
None __init__(self, LanguageSelectorConfig|None config=None)
dict[str, float] __call__(self, Any data)
None __init__(self, LocationSelectorConfig|None config=None)
None __init__(self, NumberSelectorConfig|None config=None)
float __call__(self, Any data)
None __init__(self, ObjectSelectorConfig|None config=None)
Any __call__(self, Any data)
Any __call__(self, Any data)
None __init__(self, QrCodeSelectorConfig config)
None __init__(self, SelectSelectorConfig config)
Any __call__(self, Any data)
None __init__(self, StateSelectorConfig config)
str __call__(self, Any data)
dict[str, list[str]] __call__(self, Any data)
None __init__(self, TargetSelectorConfig|None config=None)
None __init__(self, TemplateSelectorConfig|None config=None)
str __call__(self, Any data)
str __call__(self, Any data)
None __init__(self, ThemeSelectorConfig|None config=None)
str __call__(self, Any data)
None __init__(self, TimeSelectorConfig|None config=None)
None __init__(self, TriggerSelectorConfig|None config=None)
Any __call__(self, Any data)
web.Response get(self, web.Request request, str config_key)
dict[str, Any] validate(SchemaCommonFlowHandler handler, dict[str, Any] user_input)
bool valid_entity_id(str entity_id)
tuple[str, str] split_entity_id(str entity_id)
int _validate_supported_features(int|list[str] supported_features)
Selector selector(Any config)
None __init__(self, Mapping[str, Any]|None config=None)
int _entity_feature_flag(str domain, str enum_name, str feature_name)
Any validate_slider(Any data)
dict validate_selector(Any config)
bool __eq__(self, object other)
type[Selector] _get_selector_class(Any config)
int _validate_supported_feature(str supported_feature)
dict[str, dict[str, _T]] serialize(self)