Add this variable for use by automation and script templates (#52774)

pull/53607/head^2
Richard T. Schaefer 2021-07-28 02:09:13 -05:00 committed by GitHub
parent 1aec069f3a
commit 9e219d9b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 7 deletions

View File

@ -445,15 +445,19 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
trigger_context,
self._trace_config,
) as automation_trace:
this = None
state = self.hass.states.get(self.entity_id)
if state:
this = state.as_dict()
variables = {"this": this, **(run_variables or {})}
if self._variables:
try:
variables = self._variables.async_render(self.hass, run_variables)
variables = self._variables.async_render(self.hass, variables)
except template.TemplateError as err:
self._logger.error("Error rendering variables: %s", err)
automation_trace.set_error(err)
return
else:
variables = run_variables
# Prepare tracing the automation
automation_trace.set_trace(trace_get())
@ -569,11 +573,18 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
def log_cb(level, msg, **kwargs):
self._logger.log(level, "%s %s", msg, self.name, **kwargs)
variables = None
this = None
self.async_write_ha_state()
state = self.hass.states.get(self.entity_id)
if state:
this = state.as_dict()
variables = {"this": this}
if self._trigger_variables:
try:
variables = self._trigger_variables.async_render(
self.hass, None, limited=True
self.hass,
variables,
limited=True,
)
except template.TemplateError as err:
self._logger.error("Error rendering trigger variables: %s", err)

View File

@ -401,7 +401,12 @@ class ScriptEntity(ToggleEntity):
# Prepare tracing the execution of the script's sequence
script_trace.set_trace(trace_get())
with trace_path("sequence"):
return await self.script.async_run(variables, context)
this = None
state = self.hass.states.get(self.entity_id)
if state:
this = state.as_dict()
script_vars = {"this": this, **(variables or {})}
return await self.script.async_run(script_vars, context)
async def async_turn_off(self, **kwargs):
"""Stop running the script.

View File

@ -1184,6 +1184,7 @@ async def test_automation_variables(hass, caplog):
"variables": {
"test_var": "defined_in_config",
"event_type": "{{ trigger.event.event_type }}",
"this_variables": "{{this.entity_id}}",
},
"trigger": {"platform": "event", "event_type": "test_event"},
"action": {
@ -1191,6 +1192,8 @@ async def test_automation_variables(hass, caplog):
"data": {
"value": "{{ test_var }}",
"event_type": "{{ event_type }}",
"this_template": "{{this.entity_id}}",
"this_variables": "{{this_variables}}",
},
},
},
@ -1224,6 +1227,11 @@ async def test_automation_variables(hass, caplog):
assert len(calls) == 1
assert calls[0].data["value"] == "defined_in_config"
assert calls[0].data["event_type"] == "test_event"
# Verify this available to all templates
assert calls[0].data.get("this_template") == "automation.automation_0"
# Verify this available during variables rendering
assert calls[0].data.get("this_variables") == "automation.automation_0"
assert "Error rendering variables" not in caplog.text
hass.bus.async_fire("test_event_2")
await hass.async_block_till_done()
@ -1276,6 +1284,7 @@ async def test_automation_trigger_variables(hass, caplog):
},
"trigger_variables": {
"test_var": "defined_in_config",
"this_trigger_variables": "{{this.entity_id}}",
},
"trigger": {"platform": "event", "event_type": "test_event_2"},
"action": {
@ -1283,6 +1292,8 @@ async def test_automation_trigger_variables(hass, caplog):
"data": {
"value": "{{ test_var }}",
"event_type": "{{ event_type }}",
"this_template": "{{this.entity_id}}",
"this_trigger_variables": "{{this_trigger_variables}}",
},
},
},
@ -1300,7 +1311,10 @@ async def test_automation_trigger_variables(hass, caplog):
assert len(calls) == 2
assert calls[1].data["value"] == "overridden_in_config"
assert calls[1].data["event_type"] == "test_event_2"
# Verify this available to all templates
assert calls[1].data.get("this_template") == "automation.automation_1"
# Verify this available during trigger variables rendering
assert calls[1].data.get("this_trigger_variables") == "automation.automation_1"
assert "Error rendering variables" not in caplog.text
@ -1332,6 +1346,35 @@ async def test_automation_bad_trigger_variables(hass, caplog):
assert len(calls) == 0
async def test_automation_this_var_always(hass, caplog):
"""Test automation always has reference to this, even with no variable or trigger variables configured."""
calls = async_mock_service(hass, "test", "automation")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event"},
"action": {
"service": "test.automation",
"data": {
"this_template": "{{this.entity_id}}",
},
},
},
]
},
)
hass.bus.async_fire("test_event")
await hass.async_block_till_done()
assert len(calls) == 1
# Verify this available to all templates
assert calls[0].data.get("this_template") == "automation.automation_0"
assert "Error rendering variables" not in caplog.text
async def test_blueprint_automation(hass, calls):
"""Test blueprint automation."""
assert await async_setup_component(

View File

@ -679,6 +679,7 @@ async def test_script_variables(hass, caplog):
"script": {
"script1": {
"variables": {
"this_variable": "{{this.entity_id}}",
"test_var": "from_config",
"templated_config_var": "{{ var_from_service | default('config-default') }}",
},
@ -688,6 +689,8 @@ async def test_script_variables(hass, caplog):
"data": {
"value": "{{ test_var }}",
"templated_config_var": "{{ templated_config_var }}",
"this_template": "{{this.entity_id}}",
"this_variable": "{{this_variable}}",
},
},
],
@ -731,6 +734,10 @@ async def test_script_variables(hass, caplog):
assert len(mock_calls) == 1
assert mock_calls[0].data["value"] == "from_config"
assert mock_calls[0].data["templated_config_var"] == "hello"
# Verify this available to all templates
assert mock_calls[0].data.get("this_template") == "script.script1"
# Verify this available during trigger variables rendering
assert mock_calls[0].data.get("this_variable") == "script.script1"
await hass.services.async_call(
"script", "script1", {"test_var": "from_service"}, blocking=True
@ -758,3 +765,34 @@ async def test_script_variables(hass, caplog):
assert len(mock_calls) == 4
assert mock_calls[3].data["value"] == 1
async def test_script_this_var_always(hass, caplog):
"""Test script always has reference to this, even with no variabls are configured."""
assert await async_setup_component(
hass,
"script",
{
"script": {
"script1": {
"sequence": [
{
"service": "test.script",
"data": {
"this_template": "{{this.entity_id}}",
},
},
],
},
},
},
)
mock_calls = async_mock_service(hass, "test", "script")
await hass.services.async_call("script", "script1", blocking=True)
assert len(mock_calls) == 1
# Verify this available to all templates
assert mock_calls[0].data.get("this_template") == "script.script1"
assert "Error rendering variables" not in caplog.text