Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search for areas, devices and entities in script choose actions #57554

Merged
merged 1 commit into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 38 additions & 12 deletions homeassistant/helpers/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -1063,9 +1063,13 @@ def referenced_areas(self):
if self._referenced_areas is not None:
return self._referenced_areas

referenced: set[str] = set()
self._referenced_areas: set[str] = set()
Script._find_referenced_areas(self._referenced_areas, self.sequence)
return self._referenced_areas

for step in self.sequence:
@staticmethod
def _find_referenced_areas(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step)

if action == cv.SCRIPT_ACTION_CALL_SERVICE:
Expand All @@ -1076,18 +1080,25 @@ def referenced_areas(self):
):
_referenced_extract_ids(data, ATTR_AREA_ID, referenced)

self._referenced_areas = referenced
return referenced
elif action == cv.SCRIPT_ACTION_CHOOSE:
for choice in step[CONF_CHOOSE]:
Script._find_referenced_areas(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_areas(referenced, step[CONF_DEFAULT])

@property
def referenced_devices(self):
"""Return a set of referenced devices."""
if self._referenced_devices is not None:
return self._referenced_devices

referenced: set[str] = set()
self._referenced_devices: set[str] = set()
Script._find_referenced_devices(self._referenced_devices, self.sequence)
return self._referenced_devices

for step in self.sequence:
@staticmethod
def _find_referenced_devices(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step)

if action == cv.SCRIPT_ACTION_CALL_SERVICE:
Expand All @@ -1104,18 +1115,27 @@ def referenced_devices(self):
elif action == cv.SCRIPT_ACTION_DEVICE_AUTOMATION:
referenced.add(step[CONF_DEVICE_ID])

self._referenced_devices = referenced
return referenced
elif action == cv.SCRIPT_ACTION_CHOOSE:
for choice in step[CONF_CHOOSE]:
for cond in choice[CONF_CONDITIONS]:
referenced |= condition.async_extract_devices(cond)
Script._find_referenced_devices(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_devices(referenced, step[CONF_DEFAULT])

@property
def referenced_entities(self):
"""Return a set of referenced entities."""
if self._referenced_entities is not None:
return self._referenced_entities

referenced: set[str] = set()
self._referenced_entities: set[str] = set()
Script._find_referenced_entities(self._referenced_entities, self.sequence)
return self._referenced_entities

for step in self.sequence:
@staticmethod
def _find_referenced_entities(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step)

if action == cv.SCRIPT_ACTION_CALL_SERVICE:
Expand All @@ -1133,8 +1153,14 @@ def referenced_entities(self):
elif action == cv.SCRIPT_ACTION_ACTIVATE_SCENE:
referenced.add(step[CONF_SCENE])

self._referenced_entities = referenced
return referenced
elif action == cv.SCRIPT_ACTION_CHOOSE:
for choice in step[CONF_CHOOSE]:
for cond in choice[CONF_CONDITIONS]:
_LOGGER.error("Extracting entities from: %s", cond)
referenced |= condition.async_extract_entities(cond)
Script._find_referenced_entities(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_entities(referenced, step[CONF_DEFAULT])

def run(
self, variables: _VarsType | None = None, context: Context | None = None
Expand Down
92 changes: 85 additions & 7 deletions tests/helpers/test_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -2282,6 +2282,38 @@ async def test_referenced_entities(hass):
},
{"service": "test.script", "data": {"without": "entity_id"}},
{"scene": "scene.hello"},
{
"choose": [
{
"conditions": "{{ states.light.choice_1_cond == 'on' }}",
"sequence": [
{
"service": "test.script",
"data": {"entity_id": "light.choice_1_seq"},
}
],
},
{
"conditions": {
"condition": "state",
"entity_id": "light.choice_2_cond",
"state": "on",
},
"sequence": [
{
"service": "test.script",
"data": {"entity_id": "light.choice_2_seq"},
}
],
},
],
"default": [
{
"service": "test.script",
"data": {"entity_id": "light.default_seq"},
}
],
},
{"event": "test_event"},
{"delay": "{{ delay_period }}"},
]
Expand All @@ -2290,13 +2322,18 @@ async def test_referenced_entities(hass):
"test_domain",
)
assert script_obj.referenced_entities == {
"light.service_not_list",
"light.service_list",
"sensor.condition",
"scene.hello",
# "light.choice_1_cond", # no entity extraction from template conditions
"light.choice_1_seq",
"light.choice_2_cond",
"light.choice_2_seq",
"light.default_seq",
"light.direct_entity_referenced",
"light.entity_in_target",
"light.entity_in_data_template",
"light.entity_in_target",
"light.service_list",
"light.service_not_list",
"scene.hello",
"sensor.condition",
}
# Test we cache results.
assert script_obj.referenced_entities is script_obj.referenced_entities
Expand Down Expand Up @@ -2330,19 +2367,60 @@ async def test_referenced_devices(hass):
"service": "test.script",
"target": {"device_id": ["target-list-id-1", "target-list-id-2"]},
},
{
"choose": [
{
"conditions": "{{ is_device_attr('choice-2-cond-dev-id', 'model', 'blah') }}",
"sequence": [
{
"service": "test.script",
"target": {
"device_id": "choice-1-seq-device-target"
},
}
],
},
{
"conditions": {
"condition": "device",
"device_id": "choice-2-cond-dev-id",
"domain": "switch",
},
"sequence": [
{
"service": "test.script",
"target": {
"device_id": "choice-2-seq-device-target"
},
}
],
},
],
"default": [
{
"service": "test.script",
"target": {"device_id": "default-device-target"},
}
],
},
]
),
"Test Name",
"test_domain",
)
assert script_obj.referenced_devices == {
"script-dev-id",
# 'choice-1-cond-dev-id', # no device extraction from template conditions
"choice-1-seq-device-target",
"choice-2-cond-dev-id",
"choice-2-seq-device-target",
"condition-dev-id",
"data-string-id",
"data-template-string-id",
"target-string-id",
"default-device-target",
"script-dev-id",
"target-list-id-1",
"target-list-id-2",
"target-string-id",
}
# Test we cache results.
assert script_obj.referenced_devices is script_obj.referenced_devices
Expand Down