mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
EventBus can now report overview of events that have listeners.
This commit is contained in:
parent
63a1dfc64f
commit
a60f6754aa
@ -124,9 +124,16 @@ class EventBus(object):
|
||||
""" Class that allows code to listen for- and fire events. """
|
||||
|
||||
def __init__(self):
|
||||
self.listeners = defaultdict(list)
|
||||
self._listeners = defaultdict(list)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
@property
|
||||
def listeners(self):
|
||||
""" List of events that is being listened for. """
|
||||
return { key: len(self._listeners[key])
|
||||
for key in self._listeners.keys()
|
||||
if len(self._listeners[key]) > 0 }
|
||||
|
||||
def fire(self, event_type, event_data=None):
|
||||
""" Fire an event. """
|
||||
|
||||
@ -142,8 +149,8 @@ class EventBus(object):
|
||||
|
||||
# We do not use itertools.chain() because some listeners might
|
||||
# choose to remove themselves as a listener while being executed
|
||||
for listener in self.listeners[ALL_EVENTS] + \
|
||||
self.listeners[event.event_type]:
|
||||
for listener in self._listeners[ALL_EVENTS] + \
|
||||
self._listeners[event.event_type]:
|
||||
try:
|
||||
listener(event)
|
||||
|
||||
@ -159,7 +166,7 @@ class EventBus(object):
|
||||
To listen to all events specify the constant ``ALL_EVENTS``
|
||||
as event_type.
|
||||
"""
|
||||
self.listeners[event_type].append(listener)
|
||||
self._listeners[event_type].append(listener)
|
||||
|
||||
def listen_once(self, event_type, listener):
|
||||
""" Listen once for event of a specific type.
|
||||
@ -181,10 +188,10 @@ class EventBus(object):
|
||||
def remove_listener(self, event_type, listener):
|
||||
""" Removes a listener of a specific event_type. """
|
||||
try:
|
||||
self.listeners[event_type].remove(listener)
|
||||
self._listeners[event_type].remove(listener)
|
||||
|
||||
if len(self.listeners[event_type]) == 0:
|
||||
del self.listeners[event_type]
|
||||
if len(self._listeners[event_type]) == 0:
|
||||
del self._listeners[event_type]
|
||||
|
||||
except ValueError:
|
||||
pass
|
||||
|
@ -144,6 +144,7 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||
'_handle_post_states_category'),
|
||||
|
||||
# /events
|
||||
('GET', '/events', '_handle_get_events'),
|
||||
('POST', re.compile(r'/events/(?P<event_type>\w+)'),
|
||||
'_handle_post_events_event_type')
|
||||
]
|
||||
@ -300,11 +301,8 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||
# Describe event bus:
|
||||
write(("<table><tr><th>Event</th><th>Listeners</th></tr>"))
|
||||
|
||||
for category in sorted(self.server.eventbus.listeners,
|
||||
key=lambda key: key.lower()):
|
||||
write("<tr><td>{}</td><td>{}</td></tr>".
|
||||
format(category,
|
||||
len(self.server.eventbus.listeners[category])))
|
||||
for event_type, count in sorted(self.server.eventbus.listeners.items()):
|
||||
write("<tr><td>{}</td><td>{}</td></tr>".format(event_type, count))
|
||||
|
||||
# Form to allow firing events
|
||||
write("</table>")
|
||||
@ -368,6 +366,10 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||
self._message("Invalid JSON for attributes",
|
||||
HTTP_UNPROCESSABLE_ENTITY)
|
||||
|
||||
def _handle_get_events(self, path_match, data):
|
||||
""" Handles getting overview of event listeners. """
|
||||
self._write_json({'listeners': self.server.eventbus.listeners})
|
||||
|
||||
def _handle_post_events_event_type(self, path_match, data):
|
||||
""" Handles firing of an event. """
|
||||
event_type = path_match.group('event_type')
|
||||
|
@ -55,6 +55,35 @@ class EventBus(ha.EventBus):
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
@property
|
||||
def listeners(self):
|
||||
""" List of events that is being listened for. """
|
||||
try:
|
||||
req = self._call_api(METHOD_GET, hah.URL_API_EVENTS)
|
||||
|
||||
if req.status_code == 200:
|
||||
data = req.json()
|
||||
|
||||
return data['listeners']
|
||||
|
||||
else:
|
||||
raise ha.HomeAssistantException(
|
||||
"Got unexpected result (3): {}.".format(req.text))
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
self.logger.exception("EventBus:Error connecting to server")
|
||||
raise ha.HomeAssistantException("Error connecting to server")
|
||||
|
||||
except ValueError: # If req.json() can't parse the json
|
||||
self.logger.exception("EventBus:Got unexpected result")
|
||||
raise ha.HomeAssistantException(
|
||||
"Got unexpected result: {}".format(req.text))
|
||||
|
||||
except KeyError: # If not all expected keys are in the returned JSON
|
||||
self.logger.exception("EventBus:Got unexpected result (2)")
|
||||
raise ha.HomeAssistantException(
|
||||
"Got unexpected result (2): {}".format(req.text))
|
||||
|
||||
def fire(self, event_type, event_data=None):
|
||||
""" Fire an event. """
|
||||
|
||||
|
@ -34,6 +34,7 @@ def ensure_homeassistant_started():
|
||||
core = {'eventbus': ha.EventBus()}
|
||||
core['statemachine'] = ha.StateMachine(core['eventbus'])
|
||||
|
||||
core['eventbus'].listen('test_event', len)
|
||||
core['statemachine'].set_state('test','a_state')
|
||||
|
||||
hah.HTTPInterface(core['eventbus'], core['statemachine'],
|
||||
@ -83,14 +84,14 @@ class TestHTTPInterface(unittest.TestCase):
|
||||
def test_api_password(self):
|
||||
""" Test if we get access denied if we omit or provide
|
||||
a wrong api password. """
|
||||
req = requests.post(
|
||||
req = requests.get(
|
||||
_url(hah.URL_API_STATES_CATEGORY.format("test")))
|
||||
|
||||
self.assertEqual(req.status_code, 401)
|
||||
|
||||
req = requests.post(
|
||||
req = requests.get(
|
||||
_url(hah.URL_API_STATES_CATEGORY.format("test")),
|
||||
data={"api_password":"not the password"})
|
||||
params={"api_password":"not the password"})
|
||||
|
||||
self.assertEqual(req.status_code, 401)
|
||||
|
||||
@ -125,7 +126,7 @@ class TestHTTPInterface(unittest.TestCase):
|
||||
""" Test if the debug interface allows us to get a state. """
|
||||
req = requests.get(
|
||||
_url(hah.URL_API_STATES_CATEGORY.format("does_not_exist")),
|
||||
data={"api_password":API_PASSWORD})
|
||||
params={"api_password":API_PASSWORD})
|
||||
|
||||
self.assertEqual(req.status_code, 422)
|
||||
|
||||
@ -227,6 +228,15 @@ class TestHTTPInterface(unittest.TestCase):
|
||||
self.assertEqual(req.status_code, 422)
|
||||
self.assertEqual(len(test_value), 0)
|
||||
|
||||
def test_api_get_event_listeners(self):
|
||||
""" Test if we can get the list of events being listened for. """
|
||||
req = requests.get(_url(hah.URL_API_EVENTS),
|
||||
params={"api_password":API_PASSWORD})
|
||||
|
||||
data = req.json()
|
||||
|
||||
self.assertEqual(data['listeners'], self.eventbus.listeners)
|
||||
|
||||
class TestRemote(unittest.TestCase):
|
||||
""" Test the homeassistant.remote module. """
|
||||
|
||||
@ -273,6 +283,9 @@ class TestRemote(unittest.TestCase):
|
||||
self.assertEqual(state['state'], "set_remotely")
|
||||
self.assertEqual(state['attributes']['test'], 1)
|
||||
|
||||
def test_remote_eb_listening_for_same(self):
|
||||
""" Test if remote EB correctly reports listener overview. """
|
||||
self.assertEqual(self.eventbus.listeners, self.remote_eb.listeners)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def test_remote_eb_fire_event_with_no_data(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user