[tests] adapt events tests to recent changes
[leap_pycommon.git] / src / leap / common / events / __init__.py
1 # -*- coding: utf-8 -*-
2 # __init__.py
3 # Copyright (C) 2013 LEAP
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 """
18 This is an events mechanism that uses a server to allow for emitting events
19 between clients.
20
21 Application components should use the interface available in this file to
22 register callbacks to be executed upon receiving specific events, and to send
23 events to other components.
24
25 To register a callback to be executed when a specific event is emitted, use
26 leap.common.events.register():
27
28 >>> from leap.common.events import register
29 >>> from leap.common.events import catalog
30 >>> register(catalog.CLIENT_UID, lambda sig, content: do_something(content))
31
32 To emit an event, use leap.common.events.emit():
33
34 >>> from leap.common.events import emit
35 >>> from leap.common.events import catalog
36 >>> emit(catalog.CLIENT_UID)
37 """
38 import logging
39 import argparse
40
41 from leap.common.events import client
42 from leap.common.events import txclient
43 from leap.common.events import server
44 from leap.common.events import flags
45 from leap.common.events.flags import set_events_enabled
46
47 from leap.common.events import catalog
48
49
50 __all__ = [
51     "register",
52     "unregister",
53     "emit",
54     "catalog",
55     "set_events_enabled"
56 ]
57
58
59 logger = logging.getLogger(__name__)
60
61
62 def register(event, callback, uid=None, replace=False):
63     """
64     Register a callback to be executed when an event is received.
65
66     :param event: The event that triggers the callback.
67     :type event: str
68     :param callback: The callback to be executed.
69     :type callback: callable(event, content)
70     :param uid: The callback uid.
71     :type uid: str
72     :param replace: Wether an eventual callback with same ID should be
73                     replaced.
74     :type replace: bool
75
76     :return: The callback uid.
77     :rtype: str
78
79     :raises CallbackAlreadyRegistered: when there's already a callback
80             identified by the given uid and replace is False.
81     """
82     if flags.EVENTS_ENABLED:
83         return client.register(event, callback, uid, replace)
84
85
86 def register_async(event, callback, uid=None, replace=False):
87     if flags.EVENTS_ENABLED:
88         return txclient.register(event, callback, uid, replace)
89
90
91 def unregister(event, uid=None):
92     """
93     Unregister callbacks for an event.
94
95     If uid is not None, then only the callback identified by the given uid is
96     removed. Otherwise, all callbacks for the event are removed.
97
98     :param event: The event that triggers the callback.
99     :type event: Event
100     :param uid: The callback uid.
101     :type uid: str
102     """
103     if flags.EVENTS_ENABLED:
104         return client.unregister(event, uid)
105
106
107 def unregister_async(event, uid=None):
108     if flags.EVENTS_ENABLED:
109         return txclient.unregister(event, uid)
110
111
112 def emit(event, *content):
113     """
114     Send an event.
115
116     :param event: The event to be sent.
117     :type event: Event
118     :param content: The content of the event.
119     :type content: list
120     """
121     if flags.EVENTS_ENABLED:
122         return client.emit(event, *content)
123
124
125 def emit_async(event, *content):
126     if flags.EVENTS_ENABLED:
127         return txclient.emit(event, *content)
128
129
130 if __name__ == "__main__":
131
132     def _echo(event, *content):
133         print "Received event: (%s, %s)" % (event, content)
134
135     def _parse_args():
136         parser = argparse.ArgumentParser()
137         parser.add_argument(
138             "--debug", "-d", action="store_true",
139             help="print debug information")
140
141         subparsers = parser.add_subparsers(dest="command")
142
143         # server options
144         server_parser = subparsers.add_parser(
145             "server", help="Run an events server.")
146         server_parser.add_argument(
147             "--emit-addr",
148             help="The address in which to listen for events",
149             default=server.EMIT_ADDR)
150         server_parser.add_argument(
151             "--reg-addr",
152             help="The address in which to listen for registration for events.",
153             default=server.REG_ADDR)
154
155         # client options
156         client_parser = subparsers.add_parser(
157             "client", help="Run an events client.")
158         client_parser.add_argument(
159             "--emit-addr",
160             help="The address in which to emit events.",
161             default=server.EMIT_ADDR)
162         client_parser.add_argument(
163             "--reg-addr",
164             help="The address in which to register for events.",
165             default=server.REG_ADDR)
166         group = client_parser.add_mutually_exclusive_group(required=True)
167         group.add_argument('--reg', help="register an event")
168         group.add_argument('--emit', help="send an event")
169         client_parser.add_argument(
170             '--content', help="the content of the event", default=None)
171
172         # txclient options
173         txclient_parser = subparsers.add_parser(
174             "txclient", help="Run an events twisted client.")
175         txclient_parser.add_argument(
176             "--emit-addr",
177             help="The address in which to emit events.",
178             default=server.EMIT_ADDR)
179         txclient_parser.add_argument(
180             "--reg-addr",
181             help="The address in which to register for events.",
182             default=server.REG_ADDR)
183         group = txclient_parser.add_mutually_exclusive_group(required=True)
184         group.add_argument('--reg', help="register an event")
185         group.add_argument('--emit', help="send an event")
186         txclient_parser.add_argument(
187             '--content', help="the content of the event", default=None)
188
189         return parser.parse_args()
190
191     args = _parse_args()
192
193     if args.debug:
194         logging.basicConfig(level=logging.DEBUG)
195
196     if args.command == "server":
197         # run server
198         server.ensure_server(emit_addr=args.emit_addr, reg_addr=args.reg_addr)
199         from twisted.internet import reactor
200         reactor.run()
201     elif args.command == "client":
202         if args.reg:
203             event = getattr(catalog, args.reg)
204             # run client and register to a signal
205             register(event, _echo)
206             # make sure we stop on CTRL+C
207             import signal
208             signal.signal(
209                 signal.SIGINT, lambda sig, frame: client.shutdown())
210             # wait until client thread dies
211             import time
212             while client.EventsClientThread.instance().is_alive():
213                 time.sleep(0.1)
214         if args.emit:
215             # run client and emit a signal
216             event = getattr(catalog, args.emit)
217             emit(event, args.content)
218             client.shutdown()
219     elif args.command == "txclient":
220         from leap.common.events import txclient
221         register = txclient.register
222         emit = txclient.emit
223         if args.reg:
224             event = getattr(catalog, args.reg)
225             # run client and register to a signal
226             register(event, _echo)
227             from twisted.internet import reactor
228             reactor.run()
229         if args.emit:
230             # run client and emit a signal
231             event = getattr(catalog, args.emit)
232             emit(event, args.content)