From 63e55bff5233b975a1062ddbf14ef2450115e500 Mon Sep 17 00:00:00 2001 From: Phil Bruckner Date: Fri, 10 Jul 2020 19:00:57 -0500 Subject: [PATCH] Remove legacy script mode and simplify remaining modes (#37729) --- .../components/automation/__init__.py | 16 +- homeassistant/components/automation/config.py | 46 +- homeassistant/components/script/__init__.py | 127 +--- homeassistant/const.py | 1 - homeassistant/helpers/script.py | 670 +++++------------- tests/components/automation/test_init.py | 99 +-- .../automation/test_numeric_state.py | 2 - tests/components/automation/test_state.py | 1 - tests/components/automation/test_template.py | 11 +- tests/components/script/test_init.py | 158 ++--- tests/helpers/test_script.py | 235 +++--- 11 files changed, 407 insertions(+), 959 deletions(-) diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index 642c1d5678d..7a6955869d7 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -15,7 +15,6 @@ from homeassistant.const import ( CONF_ID, CONF_MODE, CONF_PLATFORM, - CONF_QUEUE_SIZE, CONF_ZONE, EVENT_HOMEASSISTANT_STARTED, SERVICE_RELOAD, @@ -31,7 +30,12 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.restore_state import RestoreEntity -from homeassistant.helpers.script import SCRIPT_BASE_SCHEMA, Script, validate_queue_size +from homeassistant.helpers.script import ( + CONF_MAX, + SCRIPT_MODE_PARALLEL, + Script, + make_script_schema, +) from homeassistant.helpers.service import async_register_admin_service from homeassistant.helpers.typing import TemplateVarsType from homeassistant.loader import bind_hass @@ -99,7 +103,7 @@ _CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA]) PLATFORM_SCHEMA = vol.All( cv.deprecated(CONF_HIDE_ENTITY, invalidation_version="0.110"), - SCRIPT_BASE_SCHEMA.extend( + make_script_schema( { # str on purpose CONF_ID: str, @@ -110,9 +114,9 @@ PLATFORM_SCHEMA = vol.All( vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA, vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA, vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA, - } + }, + SCRIPT_MODE_PARALLEL, ), - validate_queue_size, ) @@ -507,7 +511,7 @@ async def _async_process_config(hass, config, component): config_block[CONF_ACTION], name, script_mode=config_block[CONF_MODE], - queue_size=config_block.get(CONF_QUEUE_SIZE, 0), + max_runs=config_block[CONF_MAX], logger=_LOGGER, ) diff --git a/homeassistant/components/automation/config.py b/homeassistant/components/automation/config.py index fe3066eb7b2..8d956258134 100644 --- a/homeassistant/components/automation/config.py +++ b/homeassistant/components/automation/config.py @@ -1,7 +1,6 @@ """Config validation helper for the automation integration.""" import asyncio import importlib -import logging import voluptuous as vol @@ -9,21 +8,14 @@ from homeassistant.components.device_automation.exceptions import ( InvalidDeviceAutomationConfig, ) from homeassistant.config import async_log_exception, config_without_domain -from homeassistant.const import CONF_ALIAS, CONF_ID, CONF_MODE, CONF_PLATFORM +from homeassistant.const import CONF_PLATFORM from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import condition, config_per_platform -from homeassistant.helpers.script import ( - SCRIPT_MODE_LEGACY, - async_validate_action_config, - validate_legacy_mode_actions, - warn_deprecated_legacy, -) +from homeassistant.helpers.script import async_validate_action_config from homeassistant.loader import IntegrationNotFound from . import CONF_ACTION, CONF_CONDITION, CONF_TRIGGER, DOMAIN, PLATFORM_SCHEMA -_LOGGER = logging.getLogger(__name__) - # mypy: allow-untyped-calls, allow-untyped-defs # mypy: no-check-untyped-defs, no-warn-return-any @@ -56,9 +48,6 @@ async def async_validate_config_item(hass, config, full_config=None): *[async_validate_action_config(hass, action) for action in config[CONF_ACTION]] ) - if config.get(CONF_MODE, SCRIPT_MODE_LEGACY) == SCRIPT_MODE_LEGACY: - validate_legacy_mode_actions(config[CONF_ACTION]) - return config @@ -78,35 +67,6 @@ async def _try_async_validate_config_item(hass, config, full_config=None): return config -def _deprecated_legacy_mode(config): - legacy_names = [] - legacy_unnamed_found = False - - for cfg in config[DOMAIN]: - mode = cfg.get(CONF_MODE) - if mode is None: - cfg[CONF_MODE] = SCRIPT_MODE_LEGACY - name = cfg.get(CONF_ID) or cfg.get(CONF_ALIAS) - if name: - legacy_names.append(name) - else: - legacy_unnamed_found = True - - if legacy_names or legacy_unnamed_found: - msgs = [] - if legacy_unnamed_found: - msgs.append("unnamed automations") - if legacy_names: - if len(legacy_names) == 1: - base_msg = "this automation" - else: - base_msg = "these automations" - msgs.append(f"{base_msg}: {', '.join(legacy_names)}") - warn_deprecated_legacy(_LOGGER, " and ".join(msgs)) - - return config - - async def async_validate_config(hass, config): """Validate config.""" automations = list( @@ -126,6 +86,4 @@ async def async_validate_config(hass, config): config = config_without_domain(config, DOMAIN) config[DOMAIN] = automations - _deprecated_legacy_mode(config) - return config diff --git a/homeassistant/components/script/__init__.py b/homeassistant/components/script/__init__.py index f444cc45d76..50c5b1740cf 100644 --- a/homeassistant/components/script/__init__.py +++ b/homeassistant/components/script/__init__.py @@ -11,7 +11,6 @@ from homeassistant.const import ( CONF_ALIAS, CONF_ICON, CONF_MODE, - CONF_QUEUE_SIZE, CONF_SEQUENCE, SERVICE_RELOAD, SERVICE_TOGGLE, @@ -25,12 +24,10 @@ from homeassistant.helpers.config_validation import make_entity_service_schema from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.script import ( - SCRIPT_BASE_SCHEMA, - SCRIPT_MODE_LEGACY, + CONF_MAX, + SCRIPT_MODE_SINGLE, Script, - validate_legacy_mode_actions, - validate_queue_size, - warn_deprecated_legacy, + make_script_schema, ) from homeassistant.helpers.service import async_set_service_schema from homeassistant.loader import bind_hass @@ -52,51 +49,24 @@ ENTITY_ID_FORMAT = DOMAIN + ".{}" EVENT_SCRIPT_STARTED = "script_started" -def _deprecated_legacy_mode(config): - legacy_scripts = [] - for object_id, cfg in config.items(): - mode = cfg.get(CONF_MODE) - if mode is None: - legacy_scripts.append(object_id) - cfg[CONF_MODE] = SCRIPT_MODE_LEGACY - if legacy_scripts: - warn_deprecated_legacy(_LOGGER, f"script(s): {', '.join(legacy_scripts)}") - return config - - -def _not_supported_in_legacy_mode(config): - if config.get(CONF_MODE, SCRIPT_MODE_LEGACY) == SCRIPT_MODE_LEGACY: - validate_legacy_mode_actions(config[CONF_SEQUENCE]) - - return config - - -SCRIPT_ENTRY_SCHEMA = vol.All( - SCRIPT_BASE_SCHEMA.extend( - { - vol.Optional(CONF_ALIAS): cv.string, - vol.Optional(CONF_ICON): cv.icon, - vol.Required(CONF_SEQUENCE): cv.SCRIPT_SCHEMA, - vol.Optional(CONF_DESCRIPTION, default=""): cv.string, - vol.Optional(CONF_FIELDS, default={}): { - cv.string: { - vol.Optional(CONF_DESCRIPTION): cv.string, - vol.Optional(CONF_EXAMPLE): cv.string, - } - }, - } - ), - validate_queue_size, - _not_supported_in_legacy_mode, +SCRIPT_ENTRY_SCHEMA = make_script_schema( + { + vol.Optional(CONF_ALIAS): cv.string, + vol.Optional(CONF_ICON): cv.icon, + vol.Required(CONF_SEQUENCE): cv.SCRIPT_SCHEMA, + vol.Optional(CONF_DESCRIPTION, default=""): cv.string, + vol.Optional(CONF_FIELDS, default={}): { + cv.string: { + vol.Optional(CONF_DESCRIPTION): cv.string, + vol.Optional(CONF_EXAMPLE): cv.string, + } + }, + }, + SCRIPT_MODE_SINGLE, ) CONFIG_SCHEMA = vol.Schema( - { - DOMAIN: vol.All( - cv.schema_with_slug_keys(SCRIPT_ENTRY_SCHEMA), _deprecated_legacy_mode - ) - }, - extra=vol.ALLOW_EXTRA, + {DOMAIN: cv.schema_with_slug_keys(SCRIPT_ENTRY_SCHEMA)}, extra=vol.ALLOW_EXTRA ) SCRIPT_SERVICE_SCHEMA = vol.Schema(dict) @@ -192,29 +162,26 @@ async def async_setup(hass, config): """Call a service to turn script on.""" variables = service.data.get(ATTR_VARIABLES) for script_entity in await component.async_extract_from_service(service): - if script_entity.script.is_legacy: - await hass.services.async_call( - DOMAIN, script_entity.object_id, variables, context=service.context - ) - else: - await script_entity.async_turn_on( - variables=variables, context=service.context, wait=False - ) + await script_entity.async_turn_on( + variables=variables, context=service.context, wait=False + ) async def turn_off_service(service): """Cancel a script.""" # Stopping a script is ok to be done in parallel - scripts = await component.async_extract_from_service(service) + script_entities = await component.async_extract_from_service(service) - if not scripts: + if not script_entities: return - await asyncio.wait([script.async_turn_off() for script in scripts]) + await asyncio.wait( + [script_entity.async_turn_off() for script_entity in script_entities] + ) async def toggle_service(service): """Toggle a script.""" for script_entity in await component.async_extract_from_service(service): - await script_entity.async_toggle(context=service.context) + await script_entity.async_toggle(context=service.context, wait=False) hass.services.async_register( DOMAIN, SERVICE_RELOAD, reload_service, schema=RELOAD_SERVICE_SCHEMA @@ -239,27 +206,14 @@ async def _async_process_config(hass, config, component): """Execute a service call to script.