##// END OF EJS Templates
Add asyncio input hook for event loop integration.
Jonathan Slenders -
Show More
@@ -0,0 +1,43 b''
1 """
2 Inputhook for running the original asyncio event loop while we're waiting for
3 input.
4
5 By default, in IPython, we run the prompt with a different asyncio event loop,
6 because otherwise we risk that people are freezing the prompt by scheduling bad
7 coroutines. E.g., a coroutine that does a while/true and never yield back
8 control to the loop. We can't cancel that.
9
10 However, sometimes we want the asyncio loop to keep running while waiting for
11 a prompt.
12
13 The following example will print the numbers from 1 to 10 above the prompt,
14 while we are waiting for input. (This works also because we use
15 prompt_toolkit`s `patch_stdout`)::
16
17 In [1]: import asyncio
18
19 In [2]: %gui asyncio
20
21 In [3]: async def f():
22 ...: for i in range(10):
23 ...: await asyncio.sleep(1)
24 ...: print(i)
25
26
27 In [4]: asyncio.ensure_future(f())
28
29 """
30 import asyncio
31
32 # Keep reference to the original asyncio loop, because getting the event loop
33 # within the input hook would return the other loop.
34 loop = asyncio.get_event_loop()
35
36
37 def inputhook(context):
38 def stop():
39 loop.stop()
40
41 loop.add_reader(context.fileno(), stop)
42 context.fileno()
43 loop.run_forever()
@@ -1,49 +1,50 b''
1 1 import importlib
2 2 import os
3 3
4 4 aliases = {
5 5 'qt4': 'qt',
6 6 'gtk2': 'gtk',
7 7 }
8 8
9 9 backends = [
10 10 'qt', 'qt4', 'qt5',
11 11 'gtk', 'gtk2', 'gtk3',
12 12 'tk',
13 13 'wx',
14 14 'pyglet', 'glut',
15 'osx'
15 'osx',
16 'asyncio'
16 17 ]
17 18
18 19 registered = {}
19 20
20 21 def register(name, inputhook):
21 22 """Register the function *inputhook* as an event loop integration."""
22 23 registered[name] = inputhook
23 24
24 25 class UnknownBackend(KeyError):
25 26 def __init__(self, name):
26 27 self.name = name
27 28
28 29 def __str__(self):
29 30 return ("No event loop integration for {!r}. "
30 31 "Supported event loops are: {}").format(self.name,
31 32 ', '.join(backends + sorted(registered)))
32 33
33 34 def get_inputhook_name_and_func(gui):
34 35 if gui in registered:
35 36 return gui, registered[gui]
36 37
37 38 if gui not in backends:
38 39 raise UnknownBackend(gui)
39 40
40 41 if gui in aliases:
41 42 return get_inputhook_name_and_func(aliases[gui])
42 43
43 44 gui_mod = gui
44 45 if gui == 'qt5':
45 46 os.environ['QT_API'] = 'pyqt5'
46 47 gui_mod = 'qt'
47 48
48 49 mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod)
49 50 return gui, mod.inputhook
General Comments 0
You need to be logged in to leave comments. Login now