1from __future__ import unicode_literals 2 3import threading 4 5from prompt_toolkit.utils import is_windows 6 7from .base import EventLoop 8 9__all__ = [ 10 'create_event_loop', 11 'create_asyncio_event_loop', 12 'use_asyncio_event_loop', 13 'get_event_loop', 14 'set_event_loop', 15 'run_in_executor', 16 'call_from_executor', 17 'run_until_complete', 18] 19 20 21def create_event_loop(recognize_win32_paste=True): 22 """ 23 Create and return an 24 :class:`~prompt_toolkit.eventloop.base.EventLoop` instance. 25 """ 26 if is_windows(): 27 from .win32 import Win32EventLoop 28 return Win32EventLoop(recognize_paste=recognize_win32_paste) 29 else: 30 from .posix import PosixEventLoop 31 return PosixEventLoop() 32 33 34def _get_asyncio_loop_cls(): 35 # Inline import, to make sure the rest doesn't break on Python 2. (Where 36 # asyncio is not available.) 37 if is_windows(): 38 from prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop 39 else: 40 from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop 41 return AsyncioEventLoop 42 43 44def create_asyncio_event_loop(loop=None): 45 """ 46 Returns an asyncio :class:`~prompt_toolkit.eventloop.EventLoop` instance 47 for usage in a :class:`~prompt_toolkit.application.Application`. It is a 48 wrapper around an asyncio loop. 49 50 :param loop: The asyncio eventloop (or `None` if the default asyncioloop 51 should be used.) 52 """ 53 AsyncioEventLoop = _get_asyncio_loop_cls() 54 return AsyncioEventLoop(loop) 55 56 57def use_asyncio_event_loop(loop=None): 58 """ 59 Use the asyncio event loop for prompt_toolkit applications. 60 """ 61 # Don't create a new loop if the current one uses asyncio already. 62 current_loop = get_event_loop() 63 if current_loop and isinstance(current_loop, _get_asyncio_loop_cls()): 64 return 65 66 set_event_loop(create_asyncio_event_loop(loop)) 67 68 69_loop = None 70_loop_lock = threading.RLock() 71 72 73def get_event_loop(): 74 """ 75 Return the current event loop. 76 This will create a new loop if no loop was set yet. 77 """ 78 # When this function is called for the first time, and no loop has been 79 # set: create one. 80 global _loop 81 82 with _loop_lock: 83 # The following two lines are not atomic. I ended up in a situation 84 # where two threads were calling `get_event_loop()` at the same time, 85 # and that way we had two event loop instances. On one of the 86 # instances, `call_from_executor` was called, but never executed 87 # because that loop was not running. 88 if _loop is None: 89 _loop = create_event_loop() 90 91 return _loop 92 93 94def set_event_loop(loop): 95 """ 96 Set the current event loop. 97 98 :param loop: `EventLoop` instance or None. (Pass `None` to clear the 99 current loop.) 100 """ 101 assert loop is None or isinstance(loop, EventLoop) 102 global _loop 103 _loop = loop 104 105 106def run_in_executor(callback, _daemon=False): 107 """ 108 Run a long running function in a background thread. 109 """ 110 return get_event_loop().run_in_executor(callback, _daemon=_daemon) 111 112 113def call_from_executor(callback, _max_postpone_until=None): 114 """ 115 Call this function in the main event loop. 116 """ 117 return get_event_loop().call_from_executor( 118 callback, _max_postpone_until=_max_postpone_until) 119 120 121def run_until_complete(future, inputhook=None): 122 """ 123 Keep running until this future has been set. 124 Return the Future's result, or raise its exception. 125 """ 126 return get_event_loop().run_until_complete(future, inputhook=inputhook) 127