Add descriptive fields to script config (#26056)
* Add descriptive fields to script config * Add script descriptions to hass.data["service_description_cache"] * Import SERVICE_DESCRIPTION_CACHE * Register script descriptions via async_set_service_schema * Add scripts test for loading and reloading service descriptions * Minor cleanup * Clean up script schema
This commit is contained in:
parent
9bcb48985b
commit
7090970436
3 changed files with 128 additions and 1 deletions
|
@ -20,6 +20,7 @@ from homeassistant.helpers.entity import ToggleEntity
|
|||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.service import async_set_service_schema
|
||||
|
||||
from homeassistant.helpers.script import Script
|
||||
|
||||
|
@ -31,6 +32,9 @@ ATTR_LAST_ACTION = "last_action"
|
|||
ATTR_LAST_TRIGGERED = "last_triggered"
|
||||
ATTR_VARIABLES = "variables"
|
||||
|
||||
CONF_DESCRIPTION = "description"
|
||||
CONF_EXAMPLE = "example"
|
||||
CONF_FIELDS = "fields"
|
||||
CONF_SEQUENCE = "sequence"
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
|
@ -38,7 +42,17 @@ ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
|||
GROUP_NAME_ALL_SCRIPTS = "all scripts"
|
||||
|
||||
SCRIPT_ENTRY_SCHEMA = vol.Schema(
|
||||
{CONF_ALIAS: cv.string, vol.Required(CONF_SEQUENCE): cv.SCRIPT_SCHEMA}
|
||||
{
|
||||
CONF_ALIAS: cv.string,
|
||||
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,
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
|
@ -137,6 +151,13 @@ async def _async_process_config(hass, config, component):
|
|||
DOMAIN, object_id, service_handler, schema=SCRIPT_SERVICE_SCHEMA
|
||||
)
|
||||
|
||||
# Register the service description
|
||||
service_desc = {
|
||||
CONF_DESCRIPTION: cfg[CONF_DESCRIPTION],
|
||||
CONF_FIELDS: cfg[CONF_FIELDS],
|
||||
}
|
||||
async_set_service_schema(hass, DOMAIN, object_id, service_desc)
|
||||
|
||||
await component.async_add_entities(scripts)
|
||||
|
||||
|
||||
|
|
|
@ -231,6 +231,20 @@ async def async_get_all_descriptions(hass):
|
|||
return descriptions
|
||||
|
||||
|
||||
@ha.callback
|
||||
@bind_hass
|
||||
def async_set_service_schema(hass, domain, service, schema):
|
||||
"""Register a description for a service."""
|
||||
hass.data.setdefault(SERVICE_DESCRIPTION_CACHE, {})
|
||||
|
||||
description = {
|
||||
"description": schema.get("description") or "",
|
||||
"fields": schema.get("fields") or {},
|
||||
}
|
||||
|
||||
hass.data[SERVICE_DESCRIPTION_CACHE]["{}.{}".format(domain, service)] = description
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def entity_service_call(
|
||||
hass, platforms, func, call, service_name="", required_features=None
|
||||
|
|
|
@ -17,6 +17,7 @@ from homeassistant.const import (
|
|||
EVENT_SCRIPT_STARTED,
|
||||
)
|
||||
from homeassistant.core import Context, callback, split_entity_id
|
||||
from homeassistant.helpers.service import async_get_all_descriptions
|
||||
from homeassistant.loader import bind_hass
|
||||
from homeassistant.setup import setup_component, async_setup_component
|
||||
from homeassistant.exceptions import ServiceNotFound
|
||||
|
@ -244,6 +245,61 @@ class TestScriptComponent(unittest.TestCase):
|
|||
assert self.hass.services.has_service(script.DOMAIN, "test2")
|
||||
|
||||
|
||||
async def test_service_descriptions(hass):
|
||||
"""Test that service descriptions are loaded and reloaded correctly."""
|
||||
# Test 1: has "description" but no "fields"
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"script",
|
||||
{
|
||||
"script": {
|
||||
"test": {
|
||||
"description": "test description",
|
||||
"sequence": [{"delay": {"seconds": 5}}],
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
descriptions = await async_get_all_descriptions(hass)
|
||||
|
||||
assert descriptions[DOMAIN]["test"]["description"] == "test description"
|
||||
assert not descriptions[DOMAIN]["test"]["fields"]
|
||||
|
||||
# Test 2: has "fields" but no "description"
|
||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD, blocking=True)
|
||||
with patch(
|
||||
"homeassistant.config.load_yaml_config_file",
|
||||
return_value={
|
||||
"script": {
|
||||
"test": {
|
||||
"fields": {
|
||||
"test_param": {
|
||||
"description": "test_param description",
|
||||
"example": "test_param example",
|
||||
}
|
||||
},
|
||||
"sequence": [{"delay": {"seconds": 5}}],
|
||||
}
|
||||
}
|
||||
},
|
||||
):
|
||||
with patch("homeassistant.config.find_config_file", return_value=""):
|
||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD, blocking=True)
|
||||
|
||||
descriptions = await async_get_all_descriptions(hass)
|
||||
|
||||
assert descriptions[script.DOMAIN]["test"]["description"] == ""
|
||||
assert (
|
||||
descriptions[script.DOMAIN]["test"]["fields"]["test_param"]["description"]
|
||||
== "test_param description"
|
||||
)
|
||||
assert (
|
||||
descriptions[script.DOMAIN]["test"]["fields"]["test_param"]["example"]
|
||||
== "test_param example"
|
||||
)
|
||||
|
||||
|
||||
async def test_shared_context(hass):
|
||||
"""Test that the shared context is passed down the chain."""
|
||||
event = "test_event"
|
||||
|
@ -306,3 +362,39 @@ async def test_turning_no_scripts_off(hass):
|
|||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_TURN_OFF, {"entity_id": []}, blocking=True
|
||||
)
|
||||
|
||||
|
||||
async def test_async_get_descriptions_script(hass):
|
||||
"""Test async_set_service_schema for the script integration."""
|
||||
script = hass.components.script
|
||||
script_config = {
|
||||
script.DOMAIN: {
|
||||
"test1": {"sequence": [{"service": "homeassistant.restart"}]},
|
||||
"test2": {
|
||||
"description": "test2",
|
||||
"fields": {
|
||||
"param": {
|
||||
"description": "param_description",
|
||||
"example": "param_example",
|
||||
}
|
||||
},
|
||||
"sequence": [{"service": "homeassistant.restart"}],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
await async_setup_component(hass, script.DOMAIN, script_config)
|
||||
descriptions = await hass.helpers.service.async_get_all_descriptions()
|
||||
|
||||
assert descriptions[script.DOMAIN]["test1"]["description"] == ""
|
||||
assert not descriptions[script.DOMAIN]["test1"]["fields"]
|
||||
|
||||
assert descriptions[script.DOMAIN]["test2"]["description"] == "test2"
|
||||
assert (
|
||||
descriptions[script.DOMAIN]["test2"]["fields"]["param"]["description"]
|
||||
== "param_description"
|
||||
)
|
||||
assert (
|
||||
descriptions[script.DOMAIN]["test2"]["fields"]["param"]["example"]
|
||||
== "param_example"
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue