Remove dependency on vendored libjuju
[osm/N2VC.git] / modules / libjuju / juju / loop.py
1 import asyncio
2 import signal
3
4
5 def run(*steps):
6 """
7 Helper to run one or more async functions synchronously, with graceful
8 handling of SIGINT / Ctrl-C.
9
10 Returns the return value of the last function.
11 """
12 if not steps:
13 return
14
15 task = None
16 run._sigint = False # function attr to allow setting from closure
17 loop = asyncio.get_event_loop()
18
19 def abort():
20 task.cancel()
21 run._sigint = True
22
23 added = False
24 try:
25 loop.add_signal_handler(signal.SIGINT, abort)
26 added = True
27 except (ValueError, OSError, RuntimeError) as e:
28 # add_signal_handler doesn't work in a thread
29 if 'main thread' not in str(e):
30 raise
31 try:
32 for step in steps:
33 task = loop.create_task(step)
34 loop.run_until_complete(asyncio.wait([task], loop=loop))
35 if run._sigint:
36 raise KeyboardInterrupt()
37 if task.exception():
38 raise task.exception()
39 return task.result()
40 finally:
41 if added:
42 loop.remove_signal_handler(signal.SIGINT)