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=4abedfcc38f708185f6f20221b5cbe1e70dd868a;hp=0000000000000000000000000000000000000000;hb=68858c1915122c2dbc8999a5cd3229694abf5f3a;hpb=032a71b2a6692b8b4e30f629a1f906d246f06736 diff --git a/modules/libjuju/juju/loop.py b/modules/libjuju/juju/loop.py new file mode 100644 index 0000000..4abedfc --- /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 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)