Skip to content

Commit 97c50b2

Browse files
emontnemeryfrenck
authored andcommitted
Improve helpers.condition.async_subscribe_platform_events (home-assistant#157710)
1 parent ef4062a commit 97c50b2

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

homeassistant/helpers/condition.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,12 @@ def remove_subscription() -> None:
198198
async def _register_condition_platform(
199199
hass: HomeAssistant, integration_domain: str, platform: ConditionProtocol
200200
) -> None:
201-
"""Register a condition platform."""
201+
"""Register a condition platform and notify listeners.
202+
203+
If the condition platform does not provide any conditions, or it is disabled,
204+
listeners will not be notified.
205+
"""
206+
from homeassistant.components import automation # noqa: PLC0415
202207

203208
new_conditions: set[str] = set()
204209

@@ -209,13 +214,23 @@ async def _register_condition_platform(
209214
)
210215
hass.data[CONDITIONS][condition_key] = integration_domain
211216
new_conditions.add(condition_key)
217+
if not new_conditions:
218+
_LOGGER.debug(
219+
"Integration %s returned no conditions in async_get_conditions",
220+
integration_domain,
221+
)
222+
return
212223
else:
213224
_LOGGER.debug(
214225
"Integration %s does not provide condition support, skipping",
215226
integration_domain,
216227
)
217228
return
218229

230+
if automation.is_disabled_experimental_condition(hass, integration_domain):
231+
_LOGGER.debug("Conditions for integration %s are disabled", integration_domain)
232+
return
233+
219234
# We don't use gather here because gather adds additional overhead
220235
# when wrapping each coroutine in a task, and we expect our listeners
221236
# to call condition.async_get_all_descriptions which will only yield

tests/helpers/test_condition.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,3 +2878,122 @@ async def good_subscriber(new_conditions: set[str]):
28782878

28792879
assert condition_events == [{"sun"}]
28802880
assert "Error while notifying condition platform listener" in caplog.text
2881+
2882+
2883+
@patch("annotatedyaml.loader.load_yaml")
2884+
@patch.object(Integration, "has_conditions", return_value=True)
2885+
@pytest.mark.parametrize(
2886+
("new_triggers_conditions_enabled", "expected_events"),
2887+
[
2888+
(True, [{"light.is_off", "light.is_on"}]),
2889+
(False, []),
2890+
],
2891+
)
2892+
async def test_subscribe_conditions_experimental_conditions(
2893+
mock_has_conditions: Mock,
2894+
mock_load_yaml: Mock,
2895+
hass: HomeAssistant,
2896+
hass_ws_client: WebSocketGenerator,
2897+
caplog: pytest.LogCaptureFixture,
2898+
new_triggers_conditions_enabled: bool,
2899+
expected_events: list[set[str]],
2900+
) -> None:
2901+
"""Test condition.async_subscribe_platform_events doesn't send events for disabled conditions."""
2902+
# Return empty conditions.yaml for light integration, the actual condition
2903+
# descriptions are irrelevant for this test
2904+
light_condition_descriptions = ""
2905+
2906+
def _load_yaml(fname, secrets=None):
2907+
if fname.endswith("light/conditions.yaml"):
2908+
condition_descriptions = light_condition_descriptions
2909+
else:
2910+
raise FileNotFoundError
2911+
with io.StringIO(condition_descriptions) as file:
2912+
return parse_yaml(file)
2913+
2914+
mock_load_yaml.side_effect = _load_yaml
2915+
2916+
condition_events = []
2917+
2918+
async def good_subscriber(new_conditions: set[str]):
2919+
"""Simulate a working subscriber."""
2920+
condition_events.append(new_conditions)
2921+
2922+
ws_client = await hass_ws_client(hass)
2923+
2924+
assert await async_setup_component(hass, "labs", {})
2925+
await ws_client.send_json_auto_id(
2926+
{
2927+
"type": "labs/update",
2928+
"domain": "automation",
2929+
"preview_feature": "new_triggers_conditions",
2930+
"enabled": new_triggers_conditions_enabled,
2931+
}
2932+
)
2933+
2934+
msg = await ws_client.receive_json()
2935+
assert msg["success"]
2936+
await hass.async_block_till_done()
2937+
2938+
condition.async_subscribe_platform_events(hass, good_subscriber)
2939+
2940+
assert await async_setup_component(hass, "light", {})
2941+
await hass.async_block_till_done()
2942+
assert condition_events == expected_events
2943+
2944+
2945+
@patch("annotatedyaml.loader.load_yaml")
2946+
@patch.object(Integration, "has_conditions", return_value=True)
2947+
@patch(
2948+
"homeassistant.components.light.condition.async_get_conditions",
2949+
new=AsyncMock(return_value={}),
2950+
)
2951+
async def test_subscribe_conditions_no_conditions(
2952+
mock_has_conditions: Mock,
2953+
mock_load_yaml: Mock,
2954+
hass: HomeAssistant,
2955+
hass_ws_client: WebSocketGenerator,
2956+
caplog: pytest.LogCaptureFixture,
2957+
) -> None:
2958+
"""Test condition.async_subscribe_platform_events doesn't send events for platforms without conditions."""
2959+
# Return empty conditions.yaml for light integration, the actual condition
2960+
# descriptions are irrelevant for this test
2961+
light_condition_descriptions = ""
2962+
2963+
def _load_yaml(fname, secrets=None):
2964+
if fname.endswith("light/conditions.yaml"):
2965+
condition_descriptions = light_condition_descriptions
2966+
else:
2967+
raise FileNotFoundError
2968+
with io.StringIO(condition_descriptions) as file:
2969+
return parse_yaml(file)
2970+
2971+
mock_load_yaml.side_effect = _load_yaml
2972+
2973+
condition_events = []
2974+
2975+
async def good_subscriber(new_conditions: set[str]):
2976+
"""Simulate a working subscriber."""
2977+
condition_events.append(new_conditions)
2978+
2979+
ws_client = await hass_ws_client(hass)
2980+
2981+
assert await async_setup_component(hass, "labs", {})
2982+
await ws_client.send_json_auto_id(
2983+
{
2984+
"type": "labs/update",
2985+
"domain": "automation",
2986+
"preview_feature": "new_triggers_conditions",
2987+
"enabled": True,
2988+
}
2989+
)
2990+
2991+
msg = await ws_client.receive_json()
2992+
assert msg["success"]
2993+
await hass.async_block_till_done()
2994+
2995+
condition.async_subscribe_platform_events(hass, good_subscriber)
2996+
2997+
assert await async_setup_component(hass, "light", {})
2998+
await hass.async_block_till_done()
2999+
assert condition_events == []

0 commit comments

Comments
 (0)