X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=blobdiff_plain;f=modules%2Flibjuju%2Fjuju%2Floop.py;fp=modules%2Flibjuju%2Fjuju%2Floop.py;h=aca726b081d1baa06483e17213658c7f621a66bf;hp=0000000000000000000000000000000000000000;hb=e2051cca7dac12aa09f6ed33555dcc4548c4b52b;hpb=9d18c22a0dc9e295adda50601fc5e2f45d2c9b8a diff --git a/modules/libjuju/juju/loop.py b/modules/libjuju/juju/loop.py new file mode 100644 index 0000000..aca726b --- /dev/null +++ b/modules/libjuju/juju/loop.py @@ -0,0 +1,42 @@ +import asyncio +import signal + + +def run(*steps): + """ + Helper to run one or more async functions synchronously, with graceful + handling of SIGINT / Ctrl-C. + + Returns the return value of the last function. + """ + if not steps: + return + + task = None + run._sigint = False # function attr to allow setting from closure + loop = asyncio.get_event_loop() + + def abort(): + task.cancel() + run._sigint = True + + added = False + try: + loop.add_signal_handler(signal.SIGINT, abort) + added = True + except (ValueError, OSError, RuntimeError) as e: + # add_signal_handler doesn't work in a thread + if 'main thread' not in str(e): + raise + try: + for step in steps: + task = loop.create_task(step) + loop.run_until_complete(asyncio.wait([task], loop=loop)) + if run._sigint: + raise KeyboardInterrupt() + if task.exception(): + raise task.exception() + return task.result() + finally: + if added: + loop.remove_signal_handler(signal.SIGINT)