From dde73c05cbcd2d63c5b532ef54780fbabcc5f964 Mon Sep 17 00:00:00 2001 From: Artur Pragacz <49985303+arturpragacz@users.noreply.github.com> Date: Tue, 22 Jul 2025 23:06:51 +0200 Subject: [PATCH] Order selectors alphabetically in helper (#149269) --- homeassistant/helpers/selector.py | 222 +++++++++++++++--------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/homeassistant/helpers/selector.py b/homeassistant/helpers/selector.py index 2429b4b23e8..ad0c909003e 100644 --- a/homeassistant/helpers/selector.py +++ b/homeassistant/helpers/selector.py @@ -575,49 +575,6 @@ class ConstantSelector(Selector[ConstantSelectorConfig]): return self.config["value"] -class QrErrorCorrectionLevel(StrEnum): - """Possible error correction levels for QR code selector.""" - - LOW = "low" - MEDIUM = "medium" - QUARTILE = "quartile" - HIGH = "high" - - -class QrCodeSelectorConfig(BaseSelectorConfig, total=False): - """Class to represent a QR code selector config.""" - - data: str - scale: int - error_correction_level: QrErrorCorrectionLevel - - -@SELECTORS.register("qr_code") -class QrCodeSelector(Selector[QrCodeSelectorConfig]): - """QR code selector.""" - - selector_type = "qr_code" - - CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( - { - vol.Required("data"): str, - vol.Optional("scale"): int, - vol.Optional("error_correction_level"): vol.All( - vol.Coerce(QrErrorCorrectionLevel), lambda val: val.value - ), - } - ) - - def __init__(self, config: QrCodeSelectorConfig) -> None: - """Instantiate a selector.""" - super().__init__(config) - - def __call__(self, data: Any) -> Any: - """Validate the passed selection.""" - vol.Schema(vol.Any(str, None))(data) - return self.config["data"] - - class ConversationAgentSelectorConfig(BaseSelectorConfig, total=False): """Class to represent a conversation agent selector config.""" @@ -872,6 +829,39 @@ class EntitySelector(Selector[EntitySelectorConfig]): return cast(list, vol.Schema([validate])(data)) # Output is a list +class FileSelectorConfig(BaseSelectorConfig): + """Class to represent a file selector config.""" + + accept: str # required + + +@SELECTORS.register("file") +class FileSelector(Selector[FileSelectorConfig]): + """Selector of a file.""" + + selector_type = "file" + + CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( + { + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept + vol.Required("accept"): str, + } + ) + + def __init__(self, config: FileSelectorConfig) -> None: + """Instantiate a selector.""" + super().__init__(config) + + def __call__(self, data: Any) -> str: + """Validate the passed selection.""" + if not isinstance(data, str): + raise vol.Invalid("Value should be a string") + + UUID(data) + + return data + + class FloorSelectorConfig(BaseSelectorConfig, total=False): """Class to represent an floor selector config.""" @@ -1213,6 +1203,49 @@ class ObjectSelector(Selector[ObjectSelectorConfig]): return data +class QrErrorCorrectionLevel(StrEnum): + """Possible error correction levels for QR code selector.""" + + LOW = "low" + MEDIUM = "medium" + QUARTILE = "quartile" + HIGH = "high" + + +class QrCodeSelectorConfig(BaseSelectorConfig, total=False): + """Class to represent a QR code selector config.""" + + data: str + scale: int + error_correction_level: QrErrorCorrectionLevel + + +@SELECTORS.register("qr_code") +class QrCodeSelector(Selector[QrCodeSelectorConfig]): + """QR code selector.""" + + selector_type = "qr_code" + + CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( + { + vol.Required("data"): str, + vol.Optional("scale"): int, + vol.Optional("error_correction_level"): vol.All( + vol.Coerce(QrErrorCorrectionLevel), lambda val: val.value + ), + } + ) + + def __init__(self, config: QrCodeSelectorConfig) -> None: + """Instantiate a selector.""" + super().__init__(config) + + def __call__(self, data: Any) -> Any: + """Validate the passed selection.""" + vol.Schema(vol.Any(str, None))(data) + return self.config["data"] + + select_option = vol.All( dict, vol.Schema( @@ -1295,6 +1328,41 @@ class SelectSelector(Selector[SelectSelectorConfig]): return [parent_schema(vol.Schema(str)(val)) for val in data] +class StateSelectorConfig(BaseSelectorConfig, total=False): + """Class to represent an state selector config.""" + + entity_id: str + hide_states: list[str] + + +@SELECTORS.register("state") +class StateSelector(Selector[StateSelectorConfig]): + """Selector for an entity state.""" + + selector_type = "state" + + CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( + { + vol.Optional("entity_id"): cv.entity_id, + vol.Optional("hide_states"): [str], + # The attribute to filter on, is currently deliberately not + # configurable/exposed. We are considering separating state + # selectors into two types: one for state and one for attribute. + # Limiting the public use, prevents breaking changes in the future. + # vol.Optional("attribute"): str, + } + ) + + def __init__(self, config: StateSelectorConfig) -> None: + """Instantiate a selector.""" + super().__init__(config) + + def __call__(self, data: Any) -> str: + """Validate the passed selection.""" + state: str = vol.Schema(str)(data) + return state + + class StatisticSelectorConfig(BaseSelectorConfig, total=False): """Class to represent a statistic selector config.""" @@ -1335,41 +1403,6 @@ class TargetSelectorConfig(BaseSelectorConfig, total=False): device: DeviceFilterSelectorConfig | list[DeviceFilterSelectorConfig] -class StateSelectorConfig(BaseSelectorConfig, total=False): - """Class to represent an state selector config.""" - - entity_id: str - hide_states: list[str] - - -@SELECTORS.register("state") -class StateSelector(Selector[StateSelectorConfig]): - """Selector for an entity state.""" - - selector_type = "state" - - CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( - { - vol.Optional("entity_id"): cv.entity_id, - vol.Optional("hide_states"): [str], - # The attribute to filter on, is currently deliberately not - # configurable/exposed. We are considering separating state - # selectors into two types: one for state and one for attribute. - # Limiting the public use, prevents breaking changes in the future. - # vol.Optional("attribute"): str, - } - ) - - def __init__(self, config: StateSelectorConfig) -> None: - """Instantiate a selector.""" - super().__init__(config) - - def __call__(self, data: Any) -> str: - """Validate the passed selection.""" - state: str = vol.Schema(str)(data) - return state - - @SELECTORS.register("target") class TargetSelector(Selector[TargetSelectorConfig]): """Selector of a target value (area ID, device ID, entity ID etc). @@ -1559,39 +1592,6 @@ class TriggerSelector(Selector[TriggerSelectorConfig]): return vol.Schema(cv.TRIGGER_SCHEMA)(data) -class FileSelectorConfig(BaseSelectorConfig): - """Class to represent a file selector config.""" - - accept: str # required - - -@SELECTORS.register("file") -class FileSelector(Selector[FileSelectorConfig]): - """Selector of a file.""" - - selector_type = "file" - - CONFIG_SCHEMA = BASE_SELECTOR_CONFIG_SCHEMA.extend( - { - # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept - vol.Required("accept"): str, - } - ) - - def __init__(self, config: FileSelectorConfig) -> None: - """Instantiate a selector.""" - super().__init__(config) - - def __call__(self, data: Any) -> str: - """Validate the passed selection.""" - if not isinstance(data, str): - raise vol.Invalid("Value should be a string") - - UUID(data) - - return data - - dumper.add_representer( Selector, lambda dumper, value: dumper.represent_odict(