ironic-python-agent/teeth_agent/events.py

82 lines
2.2 KiB
Python

"""
Copyright 2013 Rackspace, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from collections import defaultdict
from twisted.internet.defer import maybeDeferred
__all__ = ['EventEmitter', 'EventEmitterUnhandledError']
class EventEmitterUnhandledError(RuntimeError):
"""
Error caused by no subscribers to an `error` event.
"""
pass
class EventEmitter(object):
"""
Extremely simple pubsub style things in-process.
Styled after the Node.js EventEmitter class
"""
__slots__ = ['_subs']
def __init__(self):
self._subs = defaultdict(list)
def emit(self, topic, *args):
"""
Emit an event to a specific topic with a payload.
"""
ds = []
if topic == "error":
if len(self._subs[topic]) == 0:
raise EventEmitterUnhandledError("No Subscribers to an error event found")
for s in self._subs[topic]:
ds.append(maybeDeferred(s, topic, *args))
return ds
def on(self, topic, callback):
"""
Add a handler for a specific topic.
"""
self.emit("newListener", topic, callback)
self._subs[topic].append(callback)
def once(self, topic, callback):
"""
Execute a specific handler just once.
"""
def oncecb(*args):
self.removeListener(topic, oncecb)
callback(*args)
self.on(topic, oncecb)
def removeListener(self, topic, callback):
"""
Remove a handler from a topic.
"""
self._subs[topic] = filter(lambda x: x != callback, self._subs[topic])
def removeAllListeners(self, topic):
"""
Remove all listeners from a specific topic.
"""
del self._subs[topic]