mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Refactor async_listen_once to remove nonlocal (#108627)
This commit is contained in:
parent
740209912c
commit
a3f9fc45e3
@ -1153,6 +1153,23 @@ _FilterableJobType = tuple[
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class _OneTimeListener:
|
||||||
|
hass: HomeAssistant
|
||||||
|
listener: Callable[[Event], Coroutine[Any, Any, None] | None]
|
||||||
|
remove: CALLBACK_TYPE | None = None
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_call(self, event: Event) -> None:
|
||||||
|
"""Remove listener from event bus and then fire listener."""
|
||||||
|
if not self.remove:
|
||||||
|
# If the listener was already removed, we don't need to do anything
|
||||||
|
return
|
||||||
|
self.remove()
|
||||||
|
self.remove = None
|
||||||
|
self.hass.async_run_job(self.listener, event)
|
||||||
|
|
||||||
|
|
||||||
class EventBus:
|
class EventBus:
|
||||||
"""Allow the firing of and listening for events."""
|
"""Allow the firing of and listening for events."""
|
||||||
|
|
||||||
@ -1344,39 +1361,21 @@ class EventBus:
|
|||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
filterable_job: _FilterableJobType | None = None
|
one_time_listener = _OneTimeListener(self._hass, listener)
|
||||||
|
remove = self._async_listen_filterable_job(
|
||||||
@callback
|
event_type,
|
||||||
def _onetime_listener(event: Event) -> None:
|
(
|
||||||
"""Remove listener from event bus and then fire listener."""
|
HassJob(
|
||||||
nonlocal filterable_job
|
one_time_listener.async_call,
|
||||||
if hasattr(_onetime_listener, "run"):
|
f"onetime listen {event_type} {listener}",
|
||||||
return
|
job_type=HassJobType.Callback,
|
||||||
# Set variable so that we will never run twice.
|
),
|
||||||
# Because the event bus loop might have async_fire queued multiple
|
None,
|
||||||
# times, its possible this listener may already be lined up
|
False,
|
||||||
# multiple times as well.
|
|
||||||
# This will make sure the second time it does nothing.
|
|
||||||
setattr(_onetime_listener, "run", True)
|
|
||||||
assert filterable_job is not None
|
|
||||||
self._async_remove_listener(event_type, filterable_job)
|
|
||||||
self._hass.async_run_job(listener, event)
|
|
||||||
|
|
||||||
functools.update_wrapper(
|
|
||||||
_onetime_listener, listener, ("__name__", "__qualname__", "__module__"), []
|
|
||||||
)
|
|
||||||
|
|
||||||
filterable_job = (
|
|
||||||
HassJob(
|
|
||||||
_onetime_listener,
|
|
||||||
f"onetime listen {event_type} {listener}",
|
|
||||||
job_type=HassJobType.Callback,
|
|
||||||
),
|
),
|
||||||
None,
|
|
||||||
False,
|
|
||||||
)
|
)
|
||||||
|
one_time_listener.remove = remove
|
||||||
return self._async_listen_filterable_job(event_type, filterable_job)
|
return remove
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_remove_listener(
|
def _async_remove_listener(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user