Add restrictions for listening to event_reported events (#114183)

* Add restrictions for listening to event_reported events

* Update homeassistant/core.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
pull/114198/head
Erik Montnemery 2024-03-25 19:16:50 +01:00 committed by GitHub
parent c3f4aca4e3
commit e2ee623d23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 1 deletions

View File

@ -1511,6 +1511,15 @@ class EventBus:
"""
if event_filter is not None and not is_callback_check_partial(event_filter):
raise HomeAssistantError(f"Event filter {event_filter} is not a callback")
if event_type == EVENT_STATE_REPORTED:
if not event_filter:
raise HomeAssistantError(
f"Event filter is required for event {event_type}"
)
if not run_immediately:
raise HomeAssistantError(
f"Run immediately must be set to True for event {event_type}"
)
return self._async_listen_filterable_job(
event_type,
(

View File

@ -3262,9 +3262,22 @@ async def test_eventbus_lazy_object_creation(hass: HomeAssistant) -> None:
async def test_statemachine_report_state(hass: HomeAssistant) -> None:
"""Test report state event."""
@ha.callback
def filter(event_data):
"""Mock filter."""
return True
@callback
def listener(event: ha.Event) -> None:
state_reported_events.append(event)
hass.states.async_set("light.bowl", "on", {})
state_changed_events = async_capture_events(hass, EVENT_STATE_CHANGED)
state_reported_events = async_capture_events(hass, EVENT_STATE_REPORTED)
state_reported_events = []
hass.bus.async_listen(
EVENT_STATE_REPORTED, listener, event_filter=filter, run_immediately=True
)
hass.states.async_set("light.bowl", "on")
await hass.async_block_till_done()
@ -3285,3 +3298,29 @@ async def test_statemachine_report_state(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert len(state_changed_events) == 3
assert len(state_reported_events) == 4
async def test_report_state_listener_restrictions(hass: HomeAssistant) -> None:
"""Test we enforce requirements for EVENT_STATE_REPORTED listeners."""
@ha.callback
def listener(event):
"""Mock listener."""
@ha.callback
def filter(event_data):
"""Mock filter."""
return False
# run_immediately not set
with pytest.raises(HomeAssistantError):
hass.bus.async_listen(EVENT_STATE_REPORTED, listener, event_filter=filter)
# no filter
with pytest.raises(HomeAssistantError):
hass.bus.async_listen(EVENT_STATE_REPORTED, listener, run_immediately=True)
# Both filter and run_immediately
hass.bus.async_listen(
EVENT_STATE_REPORTED, listener, event_filter=filter, run_immediately=True
)