fix remove listener (#3196)

This commit is contained in:
Paulus Schoutsen 2016-09-07 06:59:59 -07:00 committed by GitHub
parent 35b388edce
commit 5995f2438e
6 changed files with 54 additions and 44 deletions

View file

@ -98,11 +98,12 @@ class APIEventStream(HomeAssistantView):
def stream(): def stream():
"""Stream events to response.""" """Stream events to response."""
self.hass.bus.listen(MATCH_ALL, forward_events) unsub_stream = self.hass.bus.listen(MATCH_ALL, forward_events)
try:
_LOGGER.debug('STREAM %s ATTACHED', id(stop_obj)) _LOGGER.debug('STREAM %s ATTACHED', id(stop_obj))
# Fire off one message right away to have browsers fire open event # Fire off one message so browsers fire open event right away
to_write.put(STREAM_PING_PAYLOAD) to_write.put(STREAM_PING_PAYLOAD)
while True: while True:
@ -120,9 +121,9 @@ class APIEventStream(HomeAssistantView):
to_write.put(STREAM_PING_PAYLOAD) to_write.put(STREAM_PING_PAYLOAD)
except GeneratorExit: except GeneratorExit:
break break
finally:
_LOGGER.debug('STREAM %s RESPONSE CLOSED', id(stop_obj)) _LOGGER.debug('STREAM %s RESPONSE CLOSED', id(stop_obj))
self.hass.bus.remove_listener(MATCH_ALL, forward_events) unsub_stream()
return self.Response(stream(), mimetype='text/event-stream') return self.Response(stream(), mimetype='text/event-stream')

View file

@ -13,7 +13,7 @@ import voluptuous as vol
from homeassistant.components.light import is_on, turn_on from homeassistant.components.light import is_on, turn_on
from homeassistant.components.sun import next_setting, next_rising from homeassistant.components.sun import next_setting, next_rising
from homeassistant.components.switch import DOMAIN, SwitchDevice from homeassistant.components.switch import DOMAIN, SwitchDevice
from homeassistant.const import CONF_NAME, CONF_PLATFORM, EVENT_TIME_CHANGED from homeassistant.const import CONF_NAME, CONF_PLATFORM
from homeassistant.helpers.event import track_utc_time_change from homeassistant.helpers.event import track_utc_time_change
from homeassistant.util.color import color_temperature_to_rgb as temp_to_rgb from homeassistant.util.color import color_temperature_to_rgb as temp_to_rgb
from homeassistant.util.color import color_RGB_to_xy from homeassistant.util.color import color_RGB_to_xy
@ -124,7 +124,7 @@ class FluxSwitch(SwitchDevice):
self._stop_colortemp = stop_colortemp self._stop_colortemp = stop_colortemp
self._brightness = brightness self._brightness = brightness
self._mode = mode self._mode = mode
self.tracker = None self.unsub_tracker = None
@property @property
def name(self): def name(self):
@ -139,15 +139,17 @@ class FluxSwitch(SwitchDevice):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn on flux.""" """Turn on flux."""
self._state = True self._state = True
self.tracker = track_utc_time_change(self.hass, self.unsub_tracker = track_utc_time_change(self.hass, self.flux_update,
self.flux_update,
second=[0, 30]) second=[0, 30])
self.update_ha_state() self.update_ha_state()
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn off flux.""" """Turn off flux."""
if self.unsub_tracker is not None:
self.unsub_tracker()
self.unsub_tracker = None
self._state = False self._state = False
self.hass.bus.remove_listener(EVENT_TIME_CHANGED, self.tracker)
self.update_ha_state() self.update_ha_state()
# pylint: disable=too-many-locals # pylint: disable=too-many-locals

View file

@ -299,7 +299,7 @@ class EventBus(object):
def remove_listener(): def remove_listener():
"""Remove the listener.""" """Remove the listener."""
self.remove_listener(event_type, listener) self._remove_listener(event_type, listener)
return remove_listener return remove_listener
@ -309,7 +309,7 @@ class EventBus(object):
To listen to all events specify the constant ``MATCH_ALL`` To listen to all events specify the constant ``MATCH_ALL``
as event_type. as event_type.
Returns registered listener that can be used with remove_listener. Returns function to unsubscribe the listener.
""" """
@ft.wraps(listener) @ft.wraps(listener)
def onetime_listener(event): def onetime_listener(event):
@ -323,15 +323,21 @@ class EventBus(object):
# This will make sure the second time it does nothing. # This will make sure the second time it does nothing.
setattr(onetime_listener, 'run', True) setattr(onetime_listener, 'run', True)
self.remove_listener(event_type, onetime_listener) remove_listener()
listener(event) listener(event)
self.listen(event_type, onetime_listener) remove_listener = self.listen(event_type, onetime_listener)
return onetime_listener return remove_listener
def remove_listener(self, event_type, listener): def remove_listener(self, event_type, listener):
"""Remove a listener of a specific event_type. (DEPRECATED 0.28)."""
_LOGGER.warning('bus.remove_listener has been deprecated. Please use '
'the function returned from calling listen.')
self._remove_listener(event_type, listener)
def _remove_listener(self, event_type, listener):
"""Remove a listener of a specific event_type.""" """Remove a listener of a specific event_type."""
with self._lock: with self._lock:
try: try:
@ -344,7 +350,8 @@ class EventBus(object):
except (KeyError, ValueError): except (KeyError, ValueError):
# KeyError is key event_type listener did not exist # KeyError is key event_type listener did not exist
# ValueError if listener did not exist within event_type # ValueError if listener did not exist within event_type
pass _LOGGER.warning('Unable to remove unknown listener %s',
listener)
class State(object): class State(object):
@ -688,14 +695,13 @@ class ServiceRegistry(object):
if call.data[ATTR_SERVICE_CALL_ID] == call_id: if call.data[ATTR_SERVICE_CALL_ID] == call_id:
executed_event.set() executed_event.set()
self._bus.listen(EVENT_SERVICE_EXECUTED, service_executed) unsub = self._bus.listen(EVENT_SERVICE_EXECUTED, service_executed)
self._bus.fire(EVENT_CALL_SERVICE, event_data) self._bus.fire(EVENT_CALL_SERVICE, event_data)
if blocking: if blocking:
success = executed_event.wait(SERVICE_CALL_LIMIT) success = executed_event.wait(SERVICE_CALL_LIMIT)
self._bus.remove_listener( unsub()
EVENT_SERVICE_EXECUTED, service_executed)
return success return success
def _event_to_service_call(self, event): def _event_to_service_call(self, event):

View file

@ -211,6 +211,7 @@ class EventForwarder(object):
self._targets = {} self._targets = {}
self._lock = threading.Lock() self._lock = threading.Lock()
self._unsub_listener = None
def connect(self, api): def connect(self, api):
"""Attach to a Home Assistant instance and forward events. """Attach to a Home Assistant instance and forward events.
@ -218,9 +219,9 @@ class EventForwarder(object):
Will overwrite old target if one exists with same host/port. Will overwrite old target if one exists with same host/port.
""" """
with self._lock: with self._lock:
if len(self._targets) == 0: if self._unsub_listener is None:
# First target we get, setup listener for events self._unsub_listener = self.hass.bus.listen(
self.hass.bus.listen(ha.MATCH_ALL, self._event_listener) ha.MATCH_ALL, self._event_listener)
key = (api.host, api.port) key = (api.host, api.port)
@ -235,8 +236,8 @@ class EventForwarder(object):
if len(self._targets) == 0: if len(self._targets) == 0:
# Remove event listener if no forwarding targets present # Remove event listener if no forwarding targets present
self.hass.bus.remove_listener(ha.MATCH_ALL, self._unsub_listener()
self._event_listener) self._unsub_listener = None
return did_remove return did_remove

View file

@ -280,7 +280,7 @@ class TestBootstrap:
loader.set_component( loader.set_component(
'switch.platform_a', 'switch.platform_a',
MockPlatform('comp_b', platform_schema=platform_schema)) MockPlatform(platform_schema=platform_schema))
assert not bootstrap.setup_component(self.hass, 'switch', { assert not bootstrap.setup_component(self.hass, 'switch', {
'switch': { 'switch': {

View file

@ -166,14 +166,14 @@ class TestEventBus(unittest.TestCase):
self.assertEqual(old_count + 1, len(self.bus.listeners)) self.assertEqual(old_count + 1, len(self.bus.listeners))
# Try deleting a non registered listener, nothing should happen # Try deleting a non registered listener, nothing should happen
self.bus.remove_listener('test', lambda x: len) self.bus._remove_listener('test', lambda x: len)
# Remove listener # Remove listener
self.bus.remove_listener('test', listener) self.bus._remove_listener('test', listener)
self.assertEqual(old_count, len(self.bus.listeners)) self.assertEqual(old_count, len(self.bus.listeners))
# Try deleting listener while category doesn't exist either # Try deleting listener while category doesn't exist either
self.bus.remove_listener('test', listener) self.bus._remove_listener('test', listener)
def test_unsubscribe_listener(self): def test_unsubscribe_listener(self):
"""Test unsubscribe listener from returned function.""" """Test unsubscribe listener from returned function."""