blob: 69649e9277cf2221b91d84c95b956a20c4c6c465 [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Java-like event module.
To use this simply decorate the callback method with @event.Event, subscribe
to the callbacks using method += callback, and call the event method to
send the events.
class Foo(object):
@event.Event
def on_event_raised_1(self):
# This is defined as a pass since this won't directly operate on the call.
# This event takes no args when called.
pass
@event.Event
def on_event_raised_2(self, arg):
# This event takes 1 arg
pass
def do_something(self):
# This method will raise an event on each handler
self.on_event_raised_1()
self.on_event_raised_2('foo')
To subscribe to events use the following code
def callback_1():
print 'In callback 1'
def callback_2(arg):
print 'In callback 2', arg
foo = Foo()
foo.on_event_raised_1 += callback_1
foo.on_event_raised_2 += callback_2
foo.do_something()
Each event can be associated with zero or more callback handlers, and each
callback handler can be associated with one or more events.
"""
import logging
import traceback
class Event(object):
""""A Java-like event class."""
def __init__(self, method):
self._method = method
self._callbacks = []
def __iadd__(self, callback):
"""Allow method += callback syntax."""
assert callback not in self._callbacks
self._callbacks.append(callback)
return self
def __isub__(self, callback):
"""Allow method -= callback syntax."""
self._callbacks.remove(callback)
return self
def __call__(self, *args, **kwargs):
"""Dispatches a method call to the appropriate callback handlers."""
for callback in self._callbacks:
try:
callback(*args, **kwargs)
except: # pylint: disable=bare-except
# Catch all exceptions here and log them. This way one exception won't
# stop the remaining callbacks from being executed.
logging.error(traceback.format_exc())