Show More
@@ -15,6 +15,12 b' backends = [' | |||||
15 | 'osx', |
|
15 | 'osx', | |
16 | ] |
|
16 | ] | |
17 |
|
17 | |||
|
18 | registered = {} | |||
|
19 | ||||
|
20 | def register(name, inputhook): | |||
|
21 | """Register the function *inputhook* as an event loop integration.""" | |||
|
22 | registered[name] = inputhook | |||
|
23 | ||||
18 | class UnknownBackend(KeyError): |
|
24 | class UnknownBackend(KeyError): | |
19 | def __init__(self, name): |
|
25 | def __init__(self, name): | |
20 | self.name = name |
|
26 | self.name = name | |
@@ -22,9 +28,12 b' class UnknownBackend(KeyError):' | |||||
22 | def __str__(self): |
|
28 | def __str__(self): | |
23 | return ("No event loop integration for {!r}. " |
|
29 | return ("No event loop integration for {!r}. " | |
24 | "Supported event loops are: {}").format(self.name, |
|
30 | "Supported event loops are: {}").format(self.name, | |
25 | ', '.join(backends)) |
|
31 | ', '.join(backends + sorted(registered))) | |
26 |
|
32 | |||
27 | def get_inputhook_func(gui): |
|
33 | def get_inputhook_func(gui): | |
|
34 | if gui in registered: | |||
|
35 | return registered[gui] | |||
|
36 | ||||
28 | if gui not in backends: |
|
37 | if gui not in backends: | |
29 | raise UnknownBackend(gui) |
|
38 | raise UnknownBackend(gui) | |
30 |
|
39 |
@@ -13,47 +13,39 b' so different steps are needed to integrate with each.' | |||||
13 | Event loops in the terminal |
|
13 | Event loops in the terminal | |
14 | --------------------------- |
|
14 | --------------------------- | |
15 |
|
15 | |||
16 | In the terminal, IPython uses a blocking Python function to wait for user input. |
|
16 | .. versionchanged:: 5.0 | |
17 | However, the Python C API provides a hook, :c:func:`PyOS_InputHook`, which is |
|
17 | ||
18 | called frequently while waiting for input. This can be set to a function which |
|
18 | There is a new API for event loop integration using prompt_toolkit. | |
19 | briefly runs the event loop and then returns. |
|
19 | ||
20 |
|
20 | In the terminal, IPython uses prompt_toolkit to prompt the user for input. | ||
21 | IPython provides Python level wrappers for setting and resetting this hook. To |
|
21 | prompt_toolkit provides hooks to integrate with an external event loop. | |
22 | use them, subclass :class:`IPython.lib.inputhook.InputHookBase`, and define |
|
22 | ||
23 | an ``enable(app=None)`` method, which initialises the event loop and calls |
|
23 | To integrate an event loop, define a function which runs the GUI event loop | |
24 | ``self.manager.set_inputhook(f)`` with a function which will briefly run the |
|
24 | until there is input waiting for prompt_toolkit to process. There are two ways | |
25 | event loop before exiting. Decorate the class with a call to |
|
25 | to detect this condition:: | |
26 | :func:`IPython.lib.inputhook.register`:: |
|
26 | ||
27 |
|
27 | # Polling for input. | ||
28 | from IPython.lib.inputhook import register, InputHookBase |
|
28 | def inputhook(context): | |
29 |
|
29 | while not context.input_is_ready(): | ||
30 | @register('clutter') |
|
30 | # Replace this with the appropriate call for the event loop: | |
31 | class ClutterInputHook(InputHookBase): |
|
31 | iterate_loop_once() | |
32 | def enable(self, app=None): |
|
32 | ||
33 | self.manager.set_inputhook(inputhook_clutter) |
|
33 | # Using a file descriptor to notify the event loop to stop. | |
34 |
|
34 | def inputhook2(context): | ||
35 | You can also optionally define a ``disable()`` method, taking no arguments, if |
|
35 | fd = context.fileno() | |
36 | there are extra steps needed to clean up. IPython will take care of resetting |
|
36 | # Replace the functions below with those for the event loop. | |
37 | the hook, whether or not you provide a disable method. |
|
37 | add_file_reader(fd, callback=stop_the_loop) | |
38 |
|
38 | run_the_loop() | ||
39 | The simplest way to define the hook function is just to run one iteration of the |
|
39 | ||
40 | event loop, or to run until no events are pending. Most event loops provide some |
|
40 | Once you have defined this function, register it with IPython: | |
41 | mechanism to do one of these things. However, the GUI may lag slightly, |
|
41 | ||
42 | because the hook is only called every 0.1 seconds. Alternatively, the hook can |
|
42 | .. currentmodule:: IPython.terminal.pt_inputhooks | |
43 | keep running the event loop until there is input ready on stdin. IPython |
|
43 | ||
44 | provides a function to facilitate this: |
|
44 | .. function:: register(name, inputhook) | |
45 |
|
45 | |||
46 | .. currentmodule:: IPython.lib.inputhook |
|
46 | Register the function *inputhook* as the event loop integration for the | |
47 |
|
47 | GUI *name*. If ``name='foo'``, then the user can enable this integration | ||
48 | .. function:: stdin_ready() |
|
48 | by running ``%gui foo``. | |
49 |
|
||||
50 | Returns True if there is something ready to read on stdin. |
|
|||
51 |
|
||||
52 | If this is the case, the hook function should return immediately. |
|
|||
53 |
|
||||
54 | This is implemented for Windows and POSIX systems - on other platforms, it |
|
|||
55 | always returns True, so that the hook always gives Python a chance to check |
|
|||
56 | for input. |
|
|||
57 |
|
49 | |||
58 |
|
50 | |||
59 | Event loops in the kernel |
|
51 | Event loops in the kernel |
General Comments 0
You need to be logged in to leave comments.
Login now