Show More
@@ -1,196 +1,111 b'' | |||||
1 | """A kernel client for in-process kernels.""" |
|
1 | """A kernel client for in-process kernels.""" | |
2 |
|
2 | |||
3 | # Copyright (c) IPython Development Team. |
|
3 | # Copyright (c) IPython Development Team. | |
4 | # Distributed under the terms of the Modified BSD License. |
|
4 | # Distributed under the terms of the Modified BSD License. | |
5 |
|
5 | |||
6 | from IPython.kernel.channelsabc import ( |
|
6 | from IPython.kernel.channelsabc import ( | |
7 | ShellChannelABC, IOPubChannelABC, |
|
7 | ShellChannelABC, IOPubChannelABC, | |
8 | HBChannelABC, StdInChannelABC, |
|
8 | HBChannelABC, StdInChannelABC, | |
9 | ) |
|
9 | ) | |
10 |
|
10 | |||
11 | from .socket import DummySocket |
|
11 | from .socket import DummySocket | |
12 |
|
12 | |||
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | # Channel classes |
|
14 | # Channel classes | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 | class InProcessChannel(object): |
|
17 | class InProcessChannel(object): | |
18 | """Base class for in-process channels.""" |
|
18 | """Base class for in-process channels.""" | |
19 | proxy_methods = [] |
|
19 | proxy_methods = [] | |
20 |
|
20 | |||
21 | def __init__(self, client=None): |
|
21 | def __init__(self, client=None): | |
22 | super(InProcessChannel, self).__init__() |
|
22 | super(InProcessChannel, self).__init__() | |
23 | self.client = client |
|
23 | self.client = client | |
24 | self._is_alive = False |
|
24 | self._is_alive = False | |
25 |
|
25 | |||
26 | #-------------------------------------------------------------------------- |
|
26 | #-------------------------------------------------------------------------- | |
27 | # Channel interface |
|
27 | # Channel interface | |
28 | #-------------------------------------------------------------------------- |
|
28 | #-------------------------------------------------------------------------- | |
29 |
|
29 | |||
30 | def is_alive(self): |
|
30 | def is_alive(self): | |
31 | return self._is_alive |
|
31 | return self._is_alive | |
32 |
|
32 | |||
33 | def start(self): |
|
33 | def start(self): | |
34 | self._is_alive = True |
|
34 | self._is_alive = True | |
35 |
|
35 | |||
36 | def stop(self): |
|
36 | def stop(self): | |
37 | self._is_alive = False |
|
37 | self._is_alive = False | |
38 |
|
38 | |||
39 | def call_handlers(self, msg): |
|
39 | def call_handlers(self, msg): | |
40 | """ This method is called in the main thread when a message arrives. |
|
40 | """ This method is called in the main thread when a message arrives. | |
41 |
|
41 | |||
42 | Subclasses should override this method to handle incoming messages. |
|
42 | Subclasses should override this method to handle incoming messages. | |
43 | """ |
|
43 | """ | |
44 | raise NotImplementedError('call_handlers must be defined in a subclass.') |
|
44 | raise NotImplementedError('call_handlers must be defined in a subclass.') | |
45 |
|
45 | |||
|
46 | def flush(self, timeout=1.0): | |||
|
47 | pass | |||
|
48 | ||||
46 | #-------------------------------------------------------------------------- |
|
49 | #-------------------------------------------------------------------------- | |
47 | # InProcessChannel interface |
|
50 | # InProcessChannel interface | |
48 | #-------------------------------------------------------------------------- |
|
51 | #-------------------------------------------------------------------------- | |
49 |
|
52 | |||
50 | def call_handlers_later(self, *args, **kwds): |
|
53 | def call_handlers_later(self, *args, **kwds): | |
51 | """ Call the message handlers later. |
|
54 | """ Call the message handlers later. | |
52 |
|
55 | |||
53 | The default implementation just calls the handlers immediately, but this |
|
56 | The default implementation just calls the handlers immediately, but this | |
54 | method exists so that GUI toolkits can defer calling the handlers until |
|
57 | method exists so that GUI toolkits can defer calling the handlers until | |
55 | after the event loop has run, as expected by GUI frontends. |
|
58 | after the event loop has run, as expected by GUI frontends. | |
56 | """ |
|
59 | """ | |
57 | self.call_handlers(*args, **kwds) |
|
60 | self.call_handlers(*args, **kwds) | |
58 |
|
61 | |||
59 | def process_events(self): |
|
62 | def process_events(self): | |
60 | """ Process any pending GUI events. |
|
63 | """ Process any pending GUI events. | |
61 |
|
64 | |||
62 | This method will be never be called from a frontend without an event |
|
65 | This method will be never be called from a frontend without an event | |
63 | loop (e.g., a terminal frontend). |
|
66 | loop (e.g., a terminal frontend). | |
64 | """ |
|
67 | """ | |
65 | raise NotImplementedError |
|
68 | raise NotImplementedError | |
66 |
|
69 | |||
67 |
|
70 | |||
68 | class InProcessShellChannel(InProcessChannel): |
|
71 | class InProcessShellChannel(InProcessChannel): | |
69 | """See `IPython.kernel.channels.ShellChannel` for docstrings.""" |
|
72 | """See `IPython.kernel.channels.ShellChannel` for docstrings.""" | |
70 |
|
73 | |||
71 | # flag for whether execute requests should be allowed to call raw_input |
|
74 | # flag for whether execute requests should be allowed to call raw_input | |
72 | allow_stdin = True |
|
75 | allow_stdin = True | |
73 | proxy_methods = [ |
|
|||
74 | 'execute', |
|
|||
75 | 'complete', |
|
|||
76 | 'inspect', |
|
|||
77 | 'history', |
|
|||
78 | 'shutdown', |
|
|||
79 | 'kernel_info', |
|
|||
80 | ] |
|
|||
81 |
|
||||
82 | #-------------------------------------------------------------------------- |
|
|||
83 | # ShellChannel interface |
|
|||
84 | #-------------------------------------------------------------------------- |
|
|||
85 |
|
||||
86 | def execute(self, code, silent=False, store_history=True, |
|
|||
87 | user_expressions={}, allow_stdin=None): |
|
|||
88 | if allow_stdin is None: |
|
|||
89 | allow_stdin = self.allow_stdin |
|
|||
90 | content = dict(code=code, silent=silent, store_history=store_history, |
|
|||
91 | user_expressions=user_expressions, |
|
|||
92 | allow_stdin=allow_stdin) |
|
|||
93 | msg = self.client.session.msg('execute_request', content) |
|
|||
94 | self._dispatch_to_kernel(msg) |
|
|||
95 | return msg['header']['msg_id'] |
|
|||
96 |
|
||||
97 | def complete(self, code, cursor_pos=None): |
|
|||
98 | if cursor_pos is None: |
|
|||
99 | cursor_pos = len(code) |
|
|||
100 | content = dict(code=code, cursor_pos=cursor_pos) |
|
|||
101 | msg = self.client.session.msg('complete_request', content) |
|
|||
102 | self._dispatch_to_kernel(msg) |
|
|||
103 | return msg['header']['msg_id'] |
|
|||
104 |
|
||||
105 | def inspect(self, code, cursor_pos=None, detail_level=0): |
|
|||
106 | if cursor_pos is None: |
|
|||
107 | cursor_pos = len(code) |
|
|||
108 | content = dict(code=code, cursor_pos=cursor_pos, |
|
|||
109 | detail_level=detail_level, |
|
|||
110 | ) |
|
|||
111 | msg = self.client.session.msg('inspect_request', content) |
|
|||
112 | self._dispatch_to_kernel(msg) |
|
|||
113 | return msg['header']['msg_id'] |
|
|||
114 |
|
||||
115 | def history(self, raw=True, output=False, hist_access_type='range', **kwds): |
|
|||
116 | content = dict(raw=raw, output=output, |
|
|||
117 | hist_access_type=hist_access_type, **kwds) |
|
|||
118 | msg = self.client.session.msg('history_request', content) |
|
|||
119 | self._dispatch_to_kernel(msg) |
|
|||
120 | return msg['header']['msg_id'] |
|
|||
121 |
|
||||
122 | def shutdown(self, restart=False): |
|
|||
123 | # FIXME: What to do here? |
|
|||
124 | raise NotImplementedError('Cannot shutdown in-process kernel') |
|
|||
125 |
|
||||
126 | def kernel_info(self): |
|
|||
127 | """Request kernel info.""" |
|
|||
128 | msg = self.client.session.msg('kernel_info_request') |
|
|||
129 | self._dispatch_to_kernel(msg) |
|
|||
130 | return msg['header']['msg_id'] |
|
|||
131 |
|
||||
132 | #-------------------------------------------------------------------------- |
|
|||
133 | # Protected interface |
|
|||
134 | #-------------------------------------------------------------------------- |
|
|||
135 |
|
||||
136 | def _dispatch_to_kernel(self, msg): |
|
|||
137 | """ Send a message to the kernel and handle a reply. |
|
|||
138 | """ |
|
|||
139 | kernel = self.client.kernel |
|
|||
140 | if kernel is None: |
|
|||
141 | raise RuntimeError('Cannot send request. No kernel exists.') |
|
|||
142 |
|
||||
143 | stream = DummySocket() |
|
|||
144 | self.client.session.send(stream, msg) |
|
|||
145 | msg_parts = stream.recv_multipart() |
|
|||
146 | kernel.dispatch_shell(stream, msg_parts) |
|
|||
147 |
|
||||
148 | idents, reply_msg = self.client.session.recv(stream, copy=False) |
|
|||
149 | self.call_handlers_later(reply_msg) |
|
|||
150 |
|
||||
151 |
|
76 | |||
152 | class InProcessIOPubChannel(InProcessChannel): |
|
77 | class InProcessIOPubChannel(InProcessChannel): | |
153 | """See `IPython.kernel.channels.IOPubChannel` for docstrings.""" |
|
78 | """See `IPython.kernel.channels.IOPubChannel` for docstrings.""" | |
154 |
|
79 | |||
155 | def flush(self, timeout=1.0): |
|
|||
156 | pass |
|
|||
157 |
|
||||
158 |
|
80 | |||
159 | class InProcessStdInChannel(InProcessChannel): |
|
81 | class InProcessStdInChannel(InProcessChannel): | |
160 | """See `IPython.kernel.channels.StdInChannel` for docstrings.""" |
|
82 | """See `IPython.kernel.channels.StdInChannel` for docstrings.""" | |
161 |
|
83 | |||
162 | proxy_methods = ['input'] |
|
|||
163 |
|
||||
164 | def input(self, string): |
|
|||
165 | kernel = self.client.kernel |
|
|||
166 | if kernel is None: |
|
|||
167 | raise RuntimeError('Cannot send input reply. No kernel exists.') |
|
|||
168 | kernel.raw_input_str = string |
|
|||
169 |
|
84 | |||
170 |
|
85 | |||
171 | class InProcessHBChannel(InProcessChannel): |
|
86 | class InProcessHBChannel(InProcessChannel): | |
172 | """See `IPython.kernel.channels.HBChannel` for docstrings.""" |
|
87 | """See `IPython.kernel.channels.HBChannel` for docstrings.""" | |
173 |
|
88 | |||
174 | time_to_dead = 3.0 |
|
89 | time_to_dead = 3.0 | |
175 |
|
90 | |||
176 | def __init__(self, *args, **kwds): |
|
91 | def __init__(self, *args, **kwds): | |
177 | super(InProcessHBChannel, self).__init__(*args, **kwds) |
|
92 | super(InProcessHBChannel, self).__init__(*args, **kwds) | |
178 | self._pause = True |
|
93 | self._pause = True | |
179 |
|
94 | |||
180 | def pause(self): |
|
95 | def pause(self): | |
181 | self._pause = True |
|
96 | self._pause = True | |
182 |
|
97 | |||
183 | def unpause(self): |
|
98 | def unpause(self): | |
184 | self._pause = False |
|
99 | self._pause = False | |
185 |
|
100 | |||
186 | def is_beating(self): |
|
101 | def is_beating(self): | |
187 | return not self._pause |
|
102 | return not self._pause | |
188 |
|
103 | |||
189 | #----------------------------------------------------------------------------- |
|
104 | #----------------------------------------------------------------------------- | |
190 | # ABC Registration |
|
105 | # ABC Registration | |
191 | #----------------------------------------------------------------------------- |
|
106 | #----------------------------------------------------------------------------- | |
192 |
|
107 | |||
193 | ShellChannelABC.register(InProcessShellChannel) |
|
108 | ShellChannelABC.register(InProcessShellChannel) | |
194 | IOPubChannelABC.register(InProcessIOPubChannel) |
|
109 | IOPubChannelABC.register(InProcessIOPubChannel) | |
195 | HBChannelABC.register(InProcessHBChannel) |
|
110 | HBChannelABC.register(InProcessHBChannel) | |
196 | StdInChannelABC.register(InProcessStdInChannel) |
|
111 | StdInChannelABC.register(InProcessStdInChannel) |
@@ -1,87 +1,158 b'' | |||||
1 | """A client for in-process kernels.""" |
|
1 | """A client for in-process kernels.""" | |
2 |
|
2 | |||
3 | #----------------------------------------------------------------------------- |
|
3 | #----------------------------------------------------------------------------- | |
4 | # Copyright (C) 2012 The IPython Development Team |
|
4 | # Copyright (C) 2012 The IPython Development Team | |
5 | # |
|
5 | # | |
6 | # Distributed under the terms of the BSD License. The full license is in |
|
6 | # Distributed under the terms of the BSD License. The full license is in | |
7 | # the file COPYING, distributed as part of this software. |
|
7 | # the file COPYING, distributed as part of this software. | |
8 | #----------------------------------------------------------------------------- |
|
8 | #----------------------------------------------------------------------------- | |
9 |
|
9 | |||
10 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
11 | # Imports |
|
11 | # Imports | |
12 | #----------------------------------------------------------------------------- |
|
12 | #----------------------------------------------------------------------------- | |
13 |
|
13 | |||
14 | # IPython imports |
|
14 | # IPython imports | |
|
15 | from IPython.kernel.inprocess.socket import DummySocket | |||
15 | from IPython.utils.traitlets import Type, Instance |
|
16 | from IPython.utils.traitlets import Type, Instance | |
16 | from IPython.kernel.clientabc import KernelClientABC |
|
17 | from IPython.kernel.clientabc import KernelClientABC | |
17 | from IPython.kernel.client import KernelClient |
|
18 | from IPython.kernel.client import KernelClient | |
18 |
|
19 | |||
19 | # Local imports |
|
20 | # Local imports | |
20 | from .channels import ( |
|
21 | from .channels import ( | |
21 | InProcessShellChannel, |
|
22 | InProcessShellChannel, | |
22 | InProcessIOPubChannel, |
|
23 | InProcessIOPubChannel, | |
23 | InProcessHBChannel, |
|
24 | InProcessHBChannel, | |
24 | InProcessStdInChannel, |
|
25 | InProcessStdInChannel, | |
25 |
|
26 | |||
26 | ) |
|
27 | ) | |
27 |
|
28 | |||
28 | #----------------------------------------------------------------------------- |
|
29 | #----------------------------------------------------------------------------- | |
29 | # Main kernel Client class |
|
30 | # Main kernel Client class | |
30 | #----------------------------------------------------------------------------- |
|
31 | #----------------------------------------------------------------------------- | |
31 |
|
32 | |||
32 | class InProcessKernelClient(KernelClient): |
|
33 | class InProcessKernelClient(KernelClient): | |
33 | """A client for an in-process kernel. |
|
34 | """A client for an in-process kernel. | |
34 |
|
35 | |||
35 | This class implements the interface of |
|
36 | This class implements the interface of | |
36 | `IPython.kernel.clientabc.KernelClientABC` and allows |
|
37 | `IPython.kernel.clientabc.KernelClientABC` and allows | |
37 | (asynchronous) frontends to be used seamlessly with an in-process kernel. |
|
38 | (asynchronous) frontends to be used seamlessly with an in-process kernel. | |
38 |
|
39 | |||
39 | See `IPython.kernel.client.KernelClient` for docstrings. |
|
40 | See `IPython.kernel.client.KernelClient` for docstrings. | |
40 | """ |
|
41 | """ | |
41 |
|
42 | |||
42 | # The classes to use for the various channels. |
|
43 | # The classes to use for the various channels. | |
43 | shell_channel_class = Type(InProcessShellChannel) |
|
44 | shell_channel_class = Type(InProcessShellChannel) | |
44 | iopub_channel_class = Type(InProcessIOPubChannel) |
|
45 | iopub_channel_class = Type(InProcessIOPubChannel) | |
45 | stdin_channel_class = Type(InProcessStdInChannel) |
|
46 | stdin_channel_class = Type(InProcessStdInChannel) | |
46 | hb_channel_class = Type(InProcessHBChannel) |
|
47 | hb_channel_class = Type(InProcessHBChannel) | |
47 |
|
48 | |||
48 | kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel') |
|
49 | kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel') | |
49 |
|
50 | |||
50 | #-------------------------------------------------------------------------- |
|
51 | #-------------------------------------------------------------------------- | |
51 | # Channel management methods |
|
52 | # Channel management methods | |
52 | #-------------------------------------------------------------------------- |
|
53 | #-------------------------------------------------------------------------- | |
53 |
|
54 | |||
54 | def start_channels(self, *args, **kwargs): |
|
55 | def start_channels(self, *args, **kwargs): | |
55 | super(InProcessKernelClient, self).start_channels(self) |
|
56 | super(InProcessKernelClient, self).start_channels(self) | |
56 | self.kernel.frontends.append(self) |
|
57 | self.kernel.frontends.append(self) | |
57 |
|
58 | |||
58 | @property |
|
59 | @property | |
59 | def shell_channel(self): |
|
60 | def shell_channel(self): | |
60 | if self._shell_channel is None: |
|
61 | if self._shell_channel is None: | |
61 | self._shell_channel = self.shell_channel_class(self) |
|
62 | self._shell_channel = self.shell_channel_class(self) | |
62 | return self._shell_channel |
|
63 | return self._shell_channel | |
63 |
|
64 | |||
64 | @property |
|
65 | @property | |
65 | def iopub_channel(self): |
|
66 | def iopub_channel(self): | |
66 | if self._iopub_channel is None: |
|
67 | if self._iopub_channel is None: | |
67 | self._iopub_channel = self.iopub_channel_class(self) |
|
68 | self._iopub_channel = self.iopub_channel_class(self) | |
68 | return self._iopub_channel |
|
69 | return self._iopub_channel | |
69 |
|
70 | |||
70 | @property |
|
71 | @property | |
71 | def stdin_channel(self): |
|
72 | def stdin_channel(self): | |
72 | if self._stdin_channel is None: |
|
73 | if self._stdin_channel is None: | |
73 | self._stdin_channel = self.stdin_channel_class(self) |
|
74 | self._stdin_channel = self.stdin_channel_class(self) | |
74 | return self._stdin_channel |
|
75 | return self._stdin_channel | |
75 |
|
76 | |||
76 | @property |
|
77 | @property | |
77 | def hb_channel(self): |
|
78 | def hb_channel(self): | |
78 | if self._hb_channel is None: |
|
79 | if self._hb_channel is None: | |
79 | self._hb_channel = self.hb_channel_class(self) |
|
80 | self._hb_channel = self.hb_channel_class(self) | |
80 | return self._hb_channel |
|
81 | return self._hb_channel | |
81 |
|
82 | |||
|
83 | # Methods for sending specific messages | |||
|
84 | # ------------------------------------- | |||
|
85 | ||||
|
86 | def execute(self, code, silent=False, store_history=True, | |||
|
87 | user_expressions={}, allow_stdin=None): | |||
|
88 | if allow_stdin is None: | |||
|
89 | allow_stdin = self.allow_stdin | |||
|
90 | content = dict(code=code, silent=silent, store_history=store_history, | |||
|
91 | user_expressions=user_expressions, | |||
|
92 | allow_stdin=allow_stdin) | |||
|
93 | msg = self.session.msg('execute_request', content) | |||
|
94 | self._dispatch_to_kernel(msg) | |||
|
95 | return msg['header']['msg_id'] | |||
|
96 | ||||
|
97 | def complete(self, code, cursor_pos=None): | |||
|
98 | if cursor_pos is None: | |||
|
99 | cursor_pos = len(code) | |||
|
100 | content = dict(code=code, cursor_pos=cursor_pos) | |||
|
101 | msg = self.session.msg('complete_request', content) | |||
|
102 | self._dispatch_to_kernel(msg) | |||
|
103 | return msg['header']['msg_id'] | |||
|
104 | ||||
|
105 | def inspect(self, code, cursor_pos=None, detail_level=0): | |||
|
106 | if cursor_pos is None: | |||
|
107 | cursor_pos = len(code) | |||
|
108 | content = dict(code=code, cursor_pos=cursor_pos, | |||
|
109 | detail_level=detail_level, | |||
|
110 | ) | |||
|
111 | msg = self.session.msg('inspect_request', content) | |||
|
112 | self._dispatch_to_kernel(msg) | |||
|
113 | return msg['header']['msg_id'] | |||
|
114 | ||||
|
115 | def history(self, raw=True, output=False, hist_access_type='range', **kwds): | |||
|
116 | content = dict(raw=raw, output=output, | |||
|
117 | hist_access_type=hist_access_type, **kwds) | |||
|
118 | msg = self.session.msg('history_request', content) | |||
|
119 | self._dispatch_to_kernel(msg) | |||
|
120 | return msg['header']['msg_id'] | |||
|
121 | ||||
|
122 | def shutdown(self, restart=False): | |||
|
123 | # FIXME: What to do here? | |||
|
124 | raise NotImplementedError('Cannot shutdown in-process kernel') | |||
|
125 | ||||
|
126 | def kernel_info(self): | |||
|
127 | """Request kernel info.""" | |||
|
128 | msg = self.session.msg('kernel_info_request') | |||
|
129 | self._dispatch_to_kernel(msg) | |||
|
130 | return msg['header']['msg_id'] | |||
|
131 | ||||
|
132 | def input(self, string): | |||
|
133 | if self.kernel is None: | |||
|
134 | raise RuntimeError('Cannot send input reply. No kernel exists.') | |||
|
135 | self.kernel.raw_input_str = string | |||
|
136 | ||||
|
137 | ||||
|
138 | def _dispatch_to_kernel(self, msg): | |||
|
139 | """ Send a message to the kernel and handle a reply. | |||
|
140 | """ | |||
|
141 | kernel = self.kernel | |||
|
142 | if kernel is None: | |||
|
143 | raise RuntimeError('Cannot send request. No kernel exists.') | |||
|
144 | ||||
|
145 | stream = DummySocket() | |||
|
146 | self.session.send(stream, msg) | |||
|
147 | msg_parts = stream.recv_multipart() | |||
|
148 | kernel.dispatch_shell(stream, msg_parts) | |||
|
149 | ||||
|
150 | idents, reply_msg = self.session.recv(stream, copy=False) | |||
|
151 | self.shell_channel.call_handlers_later(reply_msg) | |||
|
152 | ||||
82 |
|
153 | |||
83 | #----------------------------------------------------------------------------- |
|
154 | #----------------------------------------------------------------------------- | |
84 | # ABC Registration |
|
155 | # ABC Registration | |
85 | #----------------------------------------------------------------------------- |
|
156 | #----------------------------------------------------------------------------- | |
86 |
|
157 | |||
87 | KernelClientABC.register(InProcessKernelClient) |
|
158 | KernelClientABC.register(InProcessKernelClient) |
@@ -1,115 +1,33 b'' | |||||
1 | """ Defines an in-process KernelManager with signals and slots. |
|
1 | """ Defines an in-process KernelManager with signals and slots. | |
2 | """ |
|
2 | """ | |
3 |
|
3 | |||
4 | # Local imports. |
|
4 | # Local imports. | |
5 | from IPython.external.qt import QtCore |
|
5 | from IPython.external.qt import QtCore | |
6 | from IPython.kernel.inprocess import ( |
|
6 | from IPython.kernel.inprocess import ( | |
7 | InProcessShellChannel, InProcessIOPubChannel, InProcessStdInChannel, |
|
|||
8 | InProcessHBChannel, InProcessKernelClient, InProcessKernelManager, |
|
7 | InProcessHBChannel, InProcessKernelClient, InProcessKernelManager, | |
9 | ) |
|
8 | ) | |
|
9 | from IPython.kernel.inprocess.channels import InProcessChannel | |||
10 |
|
10 | |||
11 | from IPython.utils.traitlets import Type |
|
11 | from IPython.utils.traitlets import Type | |
12 | from .kernel_mixins import ( ChannelQObject, |
|
12 | from .kernel_mixins import ( ChannelQObject, | |
13 | QtHBChannelMixin, QtKernelClientMixin, |
|
13 | QtHBChannelMixin, QtKernelClientMixin, | |
14 | QtKernelManagerMixin, |
|
14 | QtKernelManagerMixin, | |
15 | ) |
|
15 | ) | |
16 |
|
16 | |||
17 |
|
17 | class QtInProcessChannel(ChannelQObject, InProcessChannel): | ||
18 | class QtInProcessShellChannel(ChannelQObject, InProcessShellChannel): |
|
18 | pass | |
19 | # Emitted when a reply has been received for the corresponding request type. |
|
|||
20 | execute_reply = QtCore.Signal(object) |
|
|||
21 | complete_reply = QtCore.Signal(object) |
|
|||
22 | inspect_reply = QtCore.Signal(object) |
|
|||
23 | history_reply = QtCore.Signal(object) |
|
|||
24 | kernel_info_reply = QtCore.Signal(object) |
|
|||
25 |
|
||||
26 | def call_handlers(self, msg): |
|
|||
27 | """ Reimplemented to emit signals instead of making callbacks. |
|
|||
28 | """ |
|
|||
29 | # Emit the generic signal. |
|
|||
30 | self.message_received.emit(msg) |
|
|||
31 |
|
||||
32 | # Emit signals for specialized message types. |
|
|||
33 | msg_type = msg['header']['msg_type'] |
|
|||
34 | if msg_type == 'kernel_info_reply': |
|
|||
35 | self._handle_kernel_info_reply(msg) |
|
|||
36 |
|
||||
37 | signal = getattr(self, msg_type, None) |
|
|||
38 | if signal: |
|
|||
39 | signal.emit(msg) |
|
|||
40 |
|
||||
41 | class QtInProcessIOPubChannel(ChannelQObject, InProcessIOPubChannel): |
|
|||
42 | # Emitted when a message of type 'stream' is received. |
|
|||
43 | stream_received = QtCore.Signal(object) |
|
|||
44 |
|
||||
45 | # Emitted when a message of type 'execute_input' is received. |
|
|||
46 | execute_input_received = QtCore.Signal(object) |
|
|||
47 |
|
||||
48 | # Emitted when a message of type 'execute_result' is received. |
|
|||
49 | execute_result_received = QtCore.Signal(object) |
|
|||
50 |
|
||||
51 | # Emitted when a message of type 'error' is received. |
|
|||
52 | error_received = QtCore.Signal(object) |
|
|||
53 |
|
||||
54 | # Emitted when a message of type 'display_data' is received |
|
|||
55 | display_data_received = QtCore.Signal(object) |
|
|||
56 |
|
||||
57 | # Emitted when a crash report message is received from the kernel's |
|
|||
58 | # last-resort sys.excepthook. |
|
|||
59 | crash_received = QtCore.Signal(object) |
|
|||
60 |
|
||||
61 | # Emitted when a shutdown is noticed. |
|
|||
62 | shutdown_reply_received = QtCore.Signal(object) |
|
|||
63 |
|
||||
64 | #--------------------------------------------------------------------------- |
|
|||
65 | # 'IOPubChannel' interface |
|
|||
66 | #--------------------------------------------------------------------------- |
|
|||
67 |
|
||||
68 | def call_handlers(self, msg): |
|
|||
69 | """ Reimplemented to emit signals instead of making callbacks. |
|
|||
70 | """ |
|
|||
71 | # Emit the generic signal. |
|
|||
72 | self.message_received.emit(msg) |
|
|||
73 | # Emit signals for specialized message types. |
|
|||
74 | msg_type = msg['header']['msg_type'] |
|
|||
75 | signal = getattr(self, msg_type + '_received', None) |
|
|||
76 | if signal: |
|
|||
77 | signal.emit(msg) |
|
|||
78 | elif msg_type in ('stdout', 'stderr'): |
|
|||
79 | self.stream_received.emit(msg) |
|
|||
80 |
|
||||
81 | def flush(self): |
|
|||
82 | """ Reimplemented to ensure that signals are dispatched immediately. |
|
|||
83 | """ |
|
|||
84 | super(QtInProcessIOPubChannel, self).flush() |
|
|||
85 | QtCore.QCoreApplication.instance().processEvents() |
|
|||
86 |
|
||||
87 | class QtInProcessStdInChannel(ChannelQObject, InProcessStdInChannel): |
|
|||
88 | # Emitted when an input request is received. |
|
|||
89 | input_requested = QtCore.Signal(object) |
|
|||
90 |
|
||||
91 | def call_handlers(self, msg): |
|
|||
92 | """ Reimplemented to emit signals instead of making callbacks. |
|
|||
93 | """ |
|
|||
94 | # Emit the generic signal. |
|
|||
95 | self.message_received.emit(msg) |
|
|||
96 |
|
||||
97 | # Emit signals for specialized message types. |
|
|||
98 | msg_type = msg['header']['msg_type'] |
|
|||
99 | if msg_type == 'input_request': |
|
|||
100 | self.input_requested.emit(msg) |
|
|||
101 |
|
19 | |||
102 | class QtInProcessHBChannel(QtHBChannelMixin, InProcessHBChannel): |
|
20 | class QtInProcessHBChannel(QtHBChannelMixin, InProcessHBChannel): | |
103 | pass |
|
21 | pass | |
104 |
|
22 | |||
105 | class QtInProcessKernelClient(QtKernelClientMixin, InProcessKernelClient): |
|
23 | class QtInProcessKernelClient(QtKernelClientMixin, InProcessKernelClient): | |
106 | """ An in-process KernelManager with signals and slots. |
|
24 | """ An in-process KernelManager with signals and slots. | |
107 | """ |
|
25 | """ | |
108 |
|
26 | |||
109 |
iopub_channel_class = Type(QtInProcess |
|
27 | iopub_channel_class = Type(QtInProcessChannel) | |
110 |
shell_channel_class = Type(QtInProcess |
|
28 | shell_channel_class = Type(QtInProcessChannel) | |
111 |
stdin_channel_class = Type(QtInProcess |
|
29 | stdin_channel_class = Type(QtInProcessChannel) | |
112 | hb_channel_class = Type(QtInProcessHBChannel) |
|
30 | hb_channel_class = Type(QtInProcessHBChannel) | |
113 |
|
31 | |||
114 | class QtInProcessKernelManager(QtKernelManagerMixin, InProcessKernelManager): |
|
32 | class QtInProcessKernelManager(QtKernelManagerMixin, InProcessKernelManager): | |
115 | client_class = __module__ + '.QtInProcessKernelClient' |
|
33 | client_class = __module__ + '.QtInProcessKernelClient' |
@@ -1,104 +1,105 b'' | |||||
1 | """Defines a KernelManager that provides signals and slots.""" |
|
1 | """Defines a KernelManager that provides signals and slots.""" | |
2 |
|
2 | |||
3 | # Copyright (c) IPython Development Team. |
|
3 | # Copyright (c) IPython Development Team. | |
4 | # Distributed under the terms of the Modified BSD License. |
|
4 | # Distributed under the terms of the Modified BSD License. | |
5 |
|
5 | |||
6 | from IPython.external.qt import QtCore |
|
6 | from IPython.external.qt import QtCore | |
7 |
|
7 | |||
8 | from IPython.utils.traitlets import HasTraits, Type |
|
8 | from IPython.utils.traitlets import HasTraits, Type | |
9 | from .util import MetaQObjectHasTraits, SuperQObject |
|
9 | from .util import MetaQObjectHasTraits, SuperQObject | |
10 |
|
10 | |||
11 |
|
11 | |||
12 | class ChannelQObject(SuperQObject): |
|
12 | class ChannelQObject(SuperQObject): | |
13 |
|
13 | |||
14 | # Emitted when the channel is started. |
|
14 | # Emitted when the channel is started. | |
15 | started = QtCore.Signal() |
|
15 | started = QtCore.Signal() | |
16 |
|
16 | |||
17 | # Emitted when the channel is stopped. |
|
17 | # Emitted when the channel is stopped. | |
18 | stopped = QtCore.Signal() |
|
18 | stopped = QtCore.Signal() | |
19 |
|
19 | |||
20 | # Emitted when any message is received. |
|
20 | # Emitted when any message is received. | |
21 | message_received = QtCore.Signal(object) |
|
21 | message_received = QtCore.Signal(object) | |
22 |
|
22 | |||
23 | #--------------------------------------------------------------------------- |
|
|||
24 | # Channel interface |
|
|||
25 | #--------------------------------------------------------------------------- |
|
|||
26 |
|
||||
27 | def start(self): |
|
23 | def start(self): | |
28 | """ Reimplemented to emit signal. |
|
24 | """ Reimplemented to emit signal. | |
29 | """ |
|
25 | """ | |
30 | super(ChannelQObject, self).start() |
|
26 | super(ChannelQObject, self).start() | |
31 | self.started.emit() |
|
27 | self.started.emit() | |
32 |
|
28 | |||
33 | def stop(self): |
|
29 | def stop(self): | |
34 | """ Reimplemented to emit signal. |
|
30 | """ Reimplemented to emit signal. | |
35 | """ |
|
31 | """ | |
36 | super(ChannelQObject, self).stop() |
|
32 | super(ChannelQObject, self).stop() | |
37 | self.stopped.emit() |
|
33 | self.stopped.emit() | |
38 |
|
34 | |||
39 | #--------------------------------------------------------------------------- |
|
|||
40 | # InProcessChannel interface |
|
|||
41 | #--------------------------------------------------------------------------- |
|
|||
42 |
|
||||
43 | def call_handlers_later(self, *args, **kwds): |
|
35 | def call_handlers_later(self, *args, **kwds): | |
44 | """ Call the message handlers later. |
|
36 | """ Call the message handlers later. | |
45 | """ |
|
37 | """ | |
46 | do_later = lambda: self.call_handlers(*args, **kwds) |
|
38 | do_later = lambda: self.call_handlers(*args, **kwds) | |
47 | QtCore.QTimer.singleShot(0, do_later) |
|
39 | QtCore.QTimer.singleShot(0, do_later) | |
48 |
|
40 | |||
|
41 | def call_handlers(self, msg): | |||
|
42 | self.message_received.emit(msg) | |||
|
43 | ||||
49 | def process_events(self): |
|
44 | def process_events(self): | |
50 | """ Process any pending GUI events. |
|
45 | """ Process any pending GUI events. | |
51 | """ |
|
46 | """ | |
52 | QtCore.QCoreApplication.instance().processEvents() |
|
47 | QtCore.QCoreApplication.instance().processEvents() | |
53 |
|
48 | |||
|
49 | def flush(self): | |||
|
50 | """ Reimplemented to ensure that signals are dispatched immediately. | |||
|
51 | """ | |||
|
52 | super(ChannelQObject, self).flush() | |||
|
53 | self.process_events() | |||
|
54 | ||||
54 |
|
55 | |||
55 | class QtHBChannelMixin(ChannelQObject): |
|
56 | class QtHBChannelMixin(ChannelQObject): | |
56 |
|
57 | |||
57 | # Emitted when the kernel has died. |
|
58 | # Emitted when the kernel has died. | |
58 | kernel_died = QtCore.Signal(object) |
|
59 | kernel_died = QtCore.Signal(object) | |
59 |
|
60 | |||
60 | def call_handlers(self, since_last_heartbeat): |
|
61 | def call_handlers(self, since_last_heartbeat): | |
61 | """ Reimplemented to emit signals instead of making callbacks. |
|
62 | """ Reimplemented to emit signals instead of making callbacks. | |
62 | """ |
|
63 | """ | |
63 | self.kernel_died.emit(since_last_heartbeat) |
|
64 | self.kernel_died.emit(since_last_heartbeat) | |
64 |
|
65 | |||
65 |
|
66 | |||
66 | class QtKernelRestarterMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): |
|
67 | class QtKernelRestarterMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): | |
67 |
|
68 | |||
68 | _timer = None |
|
69 | _timer = None | |
69 |
|
70 | |||
70 |
|
71 | |||
71 | class QtKernelManagerMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): |
|
72 | class QtKernelManagerMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): | |
72 | """ A KernelClient that provides signals and slots. |
|
73 | """ A KernelClient that provides signals and slots. | |
73 | """ |
|
74 | """ | |
74 |
|
75 | |||
75 | kernel_restarted = QtCore.Signal() |
|
76 | kernel_restarted = QtCore.Signal() | |
76 |
|
77 | |||
77 |
|
78 | |||
78 | class QtKernelClientMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): |
|
79 | class QtKernelClientMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})): | |
79 | """ A KernelClient that provides signals and slots. |
|
80 | """ A KernelClient that provides signals and slots. | |
80 | """ |
|
81 | """ | |
81 |
|
82 | |||
82 | # Emitted when the kernel client has started listening. |
|
83 | # Emitted when the kernel client has started listening. | |
83 | started_channels = QtCore.Signal() |
|
84 | started_channels = QtCore.Signal() | |
84 |
|
85 | |||
85 | # Emitted when the kernel client has stopped listening. |
|
86 | # Emitted when the kernel client has stopped listening. | |
86 | stopped_channels = QtCore.Signal() |
|
87 | stopped_channels = QtCore.Signal() | |
87 |
|
88 | |||
88 | #--------------------------------------------------------------------------- |
|
89 | #--------------------------------------------------------------------------- | |
89 | # 'KernelClient' interface |
|
90 | # 'KernelClient' interface | |
90 | #--------------------------------------------------------------------------- |
|
91 | #--------------------------------------------------------------------------- | |
91 |
|
92 | |||
92 | #------ Channel management ------------------------------------------------- |
|
93 | #------ Channel management ------------------------------------------------- | |
93 |
|
94 | |||
94 | def start_channels(self, *args, **kw): |
|
95 | def start_channels(self, *args, **kw): | |
95 | """ Reimplemented to emit signal. |
|
96 | """ Reimplemented to emit signal. | |
96 | """ |
|
97 | """ | |
97 | super(QtKernelClientMixin, self).start_channels(*args, **kw) |
|
98 | super(QtKernelClientMixin, self).start_channels(*args, **kw) | |
98 | self.started_channels.emit() |
|
99 | self.started_channels.emit() | |
99 |
|
100 | |||
100 | def stop_channels(self): |
|
101 | def stop_channels(self): | |
101 | """ Reimplemented to emit signal. |
|
102 | """ Reimplemented to emit signal. | |
102 | """ |
|
103 | """ | |
103 | super(QtKernelClientMixin, self).stop_channels() |
|
104 | super(QtKernelClientMixin, self).stop_channels() | |
104 | self.stopped_channels.emit() |
|
105 | self.stopped_channels.emit() |
General Comments 0
You need to be logged in to leave comments.
Login now