diff --git a/homeassistant/components/input_select/__init__.py b/homeassistant/components/input_select/__init__.py index 10c48ce6b3ec..c68e35470b71 100644 --- a/homeassistant/components/input_select/__init__.py +++ b/homeassistant/components/input_select/__init__.py @@ -1,12 +1,12 @@ """Support to select an option from a list.""" +from dataclasses import dataclass import logging from typing import Any, Self, cast, override import probatio -from homeassistant.components.select import ( - ATTR_CYCLE, +from homeassistant.components.select import ( # noqa: F401 ATTR_OPTION, ATTR_OPTIONS, SERVICE_SELECT_FIRST, @@ -25,24 +25,27 @@ from homeassistant.const import ( # noqa: F401 CONF_OPTIONS, SERVICE_RELOAD, ) -from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import collection, config_validation as cv from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.restore_state import RestoreEntity -import homeassistant.helpers.service from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType, VolDictType -from .const import InputSelectEntityStateAttribute +from .const import ( # noqa: F401 + DATA_INPUT_SELECT, + DOMAIN, + SERVICE_SET_OPTIONS, + InputSelectEntityStateAttribute, +) +from .services import async_setup_services _LOGGER = logging.getLogger(__name__) -DOMAIN = "input_select" CONF_INITIAL = "initial" -SERVICE_SET_OPTIONS = "set_options" STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 STORAGE_VERSION_MINOR = 2 @@ -112,7 +115,6 @@ CONFIG_SCHEMA = probatio.Schema( }, extra=probatio.ALLOW_EXTRA, ) -RELOAD_SERVICE_SCHEMA = probatio.Schema({}) class InputSelectStore(Store): @@ -133,6 +135,14 @@ class InputSelectStore(Store): return old_data +@dataclass(slots=True) +class InputSelectData: + """Runtime data for the input_select integration.""" + + component: EntityComponent[InputSelect] + yaml_collection: collection.YamlCollection + + async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up an input select.""" component = EntityComponent[InputSelect](_LOGGER, DOMAIN, hass) @@ -165,61 +175,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) - async def reload_service_handler(service_call: ServiceCall) -> None: - """Reload yaml entities.""" - conf = await component.async_prepare_reload(skip_reset=True) - await yaml_collection.async_load( - [{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()] - ) - - homeassistant.helpers.service.async_register_admin_service( - hass, - DOMAIN, - SERVICE_RELOAD, - reload_service_handler, - schema=RELOAD_SERVICE_SCHEMA, - ) - - component.async_register_entity_service( - SERVICE_SELECT_FIRST, - None, - InputSelect.async_first.__name__, - ) - - component.async_register_entity_service( - SERVICE_SELECT_LAST, - None, - InputSelect.async_last.__name__, - ) - - component.async_register_entity_service( - SERVICE_SELECT_NEXT, - {probatio.Optional(ATTR_CYCLE, default=True): bool}, - InputSelect.async_next.__name__, - ) - - component.async_register_entity_service( - SERVICE_SELECT_OPTION, - {probatio.Required(ATTR_OPTION): cv.string}, - InputSelect.async_select_option.__name__, - ) - - component.async_register_entity_service( - SERVICE_SELECT_PREVIOUS, - {probatio.Optional(ATTR_CYCLE, default=True): bool}, - InputSelect.async_previous.__name__, - ) - - component.async_register_entity_service( - SERVICE_SET_OPTIONS, - { - probatio.Required(ATTR_OPTIONS): probatio.All( - probatio.EnsureList(), probatio.NonEmpty(), [cv.string] - ) - }, - "async_set_options", - ) + hass.data[DATA_INPUT_SELECT] = InputSelectData(component, yaml_collection) + async_setup_services(hass) return True diff --git a/homeassistant/components/input_select/const.py b/homeassistant/components/input_select/const.py index 46e2e69d3371..ab8d2c72a658 100644 --- a/homeassistant/components/input_select/const.py +++ b/homeassistant/components/input_select/const.py @@ -1,6 +1,18 @@ """Constants for the input_select integration.""" from enum import StrEnum +from typing import TYPE_CHECKING, Final + +from homeassistant.util.hass_dict import HassKey + +if TYPE_CHECKING: + from . import InputSelectData + +DOMAIN: Final = "input_select" + +DATA_INPUT_SELECT: HassKey[InputSelectData] = HassKey(DOMAIN) + +SERVICE_SET_OPTIONS: Final = "set_options" class InputSelectEntityStateAttribute(StrEnum): diff --git a/homeassistant/components/input_select/services.py b/homeassistant/components/input_select/services.py new file mode 100644 index 000000000000..305cc8146dbf --- /dev/null +++ b/homeassistant/components/input_select/services.py @@ -0,0 +1,72 @@ +"""Services for the input_select integration.""" + +import probatio + +from homeassistant.components.select import ( + ATTR_CYCLE, + ATTR_OPTION, + ATTR_OPTIONS, + SERVICE_SELECT_FIRST, + SERVICE_SELECT_LAST, + SERVICE_SELECT_NEXT, + SERVICE_SELECT_OPTION, + SERVICE_SELECT_PREVIOUS, +) +from homeassistant.const import CONF_ID, SERVICE_RELOAD +from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.service import async_register_admin_service + +from .const import DATA_INPUT_SELECT, DOMAIN, SERVICE_SET_OPTIONS + +RELOAD_SERVICE_SCHEMA = probatio.Schema({}) + + +async def _async_reload_service(service_call: ServiceCall) -> None: + """Reload yaml entities.""" + hass = service_call.hass + data = hass.data[DATA_INPUT_SELECT] + conf = await data.component.async_prepare_reload(skip_reset=True) + await data.yaml_collection.async_load( + [{CONF_ID: id_, **(conf or {})} for id_, conf in conf.get(DOMAIN, {}).items()] + ) + + +@callback +def async_setup_services(hass: HomeAssistant) -> None: + """Register the input_select services.""" + async_register_admin_service( + hass, + DOMAIN, + SERVICE_RELOAD, + _async_reload_service, + schema=RELOAD_SERVICE_SCHEMA, + ) + + component = hass.data[DATA_INPUT_SELECT].component + component.async_register_entity_service(SERVICE_SELECT_FIRST, None, "async_first") + component.async_register_entity_service(SERVICE_SELECT_LAST, None, "async_last") + component.async_register_entity_service( + SERVICE_SELECT_NEXT, + {probatio.Optional(ATTR_CYCLE, default=True): bool}, + "async_next", + ) + component.async_register_entity_service( + SERVICE_SELECT_OPTION, + {probatio.Required(ATTR_OPTION): cv.string}, + "async_select_option", + ) + component.async_register_entity_service( + SERVICE_SELECT_PREVIOUS, + {probatio.Optional(ATTR_CYCLE, default=True): bool}, + "async_previous", + ) + component.async_register_entity_service( + SERVICE_SET_OPTIONS, + { + probatio.Required(ATTR_OPTIONS): probatio.All( + probatio.EnsureList(), probatio.NonEmpty(), [cv.string] + ) + }, + "async_set_options", + )