| # 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()) |