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 | import importlib |
|
1 | import importlib | |
2 | import os |
|
2 | import os | |
3 |
|
3 | |||
4 | aliases = { |
|
4 | aliases = { | |
5 | 'qt4': 'qt', |
|
5 | 'qt4': 'qt', | |
6 | 'gtk2': 'gtk', |
|
6 | 'gtk2': 'gtk', | |
7 | } |
|
7 | } | |
8 |
|
8 | |||
9 | backends = [ |
|
9 | backends = [ | |
10 | 'qt', 'qt4', 'qt5', |
|
10 | 'qt', 'qt4', 'qt5', | |
11 | 'gtk', 'gtk2', 'gtk3', |
|
11 | 'gtk', 'gtk2', 'gtk3', | |
12 | 'tk', |
|
12 | 'tk', | |
13 | 'wx', |
|
13 | 'wx', | |
14 | 'pyglet', 'glut', |
|
14 | 'pyglet', 'glut', | |
15 | 'osx' |
|
15 | 'osx', | |
|
16 | 'asyncio' | |||
16 | ] |
|
17 | ] | |
17 |
|
18 | |||
18 | registered = {} |
|
19 | registered = {} | |
19 |
|
20 | |||
20 | def register(name, inputhook): |
|
21 | def register(name, inputhook): | |
21 | """Register the function *inputhook* as an event loop integration.""" |
|
22 | """Register the function *inputhook* as an event loop integration.""" | |
22 | registered[name] = inputhook |
|
23 | registered[name] = inputhook | |
23 |
|
24 | |||
24 | class UnknownBackend(KeyError): |
|
25 | class UnknownBackend(KeyError): | |
25 | def __init__(self, name): |
|
26 | def __init__(self, name): | |
26 | self.name = name |
|
27 | self.name = name | |
27 |
|
28 | |||
28 | def __str__(self): |
|
29 | def __str__(self): | |
29 | return ("No event loop integration for {!r}. " |
|
30 | return ("No event loop integration for {!r}. " | |
30 | "Supported event loops are: {}").format(self.name, |
|
31 | "Supported event loops are: {}").format(self.name, | |
31 | ', '.join(backends + sorted(registered))) |
|
32 | ', '.join(backends + sorted(registered))) | |
32 |
|
33 | |||
33 | def get_inputhook_name_and_func(gui): |
|
34 | def get_inputhook_name_and_func(gui): | |
34 | if gui in registered: |
|
35 | if gui in registered: | |
35 | return gui, registered[gui] |
|
36 | return gui, registered[gui] | |
36 |
|
37 | |||
37 | if gui not in backends: |
|
38 | if gui not in backends: | |
38 | raise UnknownBackend(gui) |
|
39 | raise UnknownBackend(gui) | |
39 |
|
40 | |||
40 | if gui in aliases: |
|
41 | if gui in aliases: | |
41 | return get_inputhook_name_and_func(aliases[gui]) |
|
42 | return get_inputhook_name_and_func(aliases[gui]) | |
42 |
|
43 | |||
43 | gui_mod = gui |
|
44 | gui_mod = gui | |
44 | if gui == 'qt5': |
|
45 | if gui == 'qt5': | |
45 | os.environ['QT_API'] = 'pyqt5' |
|
46 | os.environ['QT_API'] = 'pyqt5' | |
46 | gui_mod = 'qt' |
|
47 | gui_mod = 'qt' | |
47 |
|
48 | |||
48 | mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod) |
|
49 | mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod) | |
49 | return gui, mod.inputhook |
|
50 | return gui, mod.inputhook |
General Comments 0
You need to be logged in to leave comments.
Login now