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