##// END OF EJS Templates
update inprocess kernel to new layout...
MinRK -
Show More
@@ -0,0 +1,194 b''
1 """ A kernel client for in-process kernels. """
2
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2012 The IPython Development Team
5 #
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
9
10 #-----------------------------------------------------------------------------
11 # Imports
12 #-----------------------------------------------------------------------------
13
14 # IPython imports
15 from IPython.kernel.channelabc import (
16 ShellChannelABC, IOPubChannelABC,
17 HBChannelABC, StdInChannelABC,
18 )
19
20 # Local imports
21 from .socket import DummySocket
22
23 #-----------------------------------------------------------------------------
24 # Channel classes
25 #-----------------------------------------------------------------------------
26
27 class InProcessChannel(object):
28 """Base class for in-process channels."""
29 proxy_methods = []
30
31 def __init__(self, client):
32 super(InProcessChannel, self).__init__()
33 self.client = client
34 self._is_alive = False
35
36 #--------------------------------------------------------------------------
37 # Channel interface
38 #--------------------------------------------------------------------------
39
40 def is_alive(self):
41 return self._is_alive
42
43 def start(self):
44 self._is_alive = True
45
46 def stop(self):
47 self._is_alive = False
48
49 def call_handlers(self, msg):
50 """ This method is called in the main thread when a message arrives.
51
52 Subclasses should override this method to handle incoming messages.
53 """
54 raise NotImplementedError('call_handlers must be defined in a subclass.')
55
56 #--------------------------------------------------------------------------
57 # InProcessChannel interface
58 #--------------------------------------------------------------------------
59
60 def call_handlers_later(self, *args, **kwds):
61 """ Call the message handlers later.
62
63 The default implementation just calls the handlers immediately, but this
64 method exists so that GUI toolkits can defer calling the handlers until
65 after the event loop has run, as expected by GUI frontends.
66 """
67 self.call_handlers(*args, **kwds)
68
69 def process_events(self):
70 """ Process any pending GUI events.
71
72 This method will be never be called from a frontend without an event
73 loop (e.g., a terminal frontend).
74 """
75 raise NotImplementedError
76
77
78 class InProcessShellChannel(InProcessChannel):
79 """See `IPython.kernel.channels.ShellChannel` for docstrings."""
80
81 # flag for whether execute requests should be allowed to call raw_input
82 allow_stdin = True
83 proxy_methods = [
84 'execute',
85 'complete',
86 'object_info',
87 'history',
88 'shutdown',
89 ]
90
91 #--------------------------------------------------------------------------
92 # ShellChannel interface
93 #--------------------------------------------------------------------------
94
95 def execute(self, code, silent=False, store_history=True,
96 user_variables=[], user_expressions={}, allow_stdin=None):
97 if allow_stdin is None:
98 allow_stdin = self.allow_stdin
99 content = dict(code=code, silent=silent, store_history=store_history,
100 user_variables=user_variables,
101 user_expressions=user_expressions,
102 allow_stdin=allow_stdin)
103 msg = self.client.session.msg('execute_request', content)
104 self._dispatch_to_kernel(msg)
105 return msg['header']['msg_id']
106
107 def complete(self, text, line, cursor_pos, block=None):
108 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
109 msg = self.client.session.msg('complete_request', content)
110 self._dispatch_to_kernel(msg)
111 return msg['header']['msg_id']
112
113 def object_info(self, oname, detail_level=0):
114 content = dict(oname=oname, detail_level=detail_level)
115 msg = self.client.session.msg('object_info_request', content)
116 self._dispatch_to_kernel(msg)
117 return msg['header']['msg_id']
118
119 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
120 content = dict(raw=raw, output=output,
121 hist_access_type=hist_access_type, **kwds)
122 msg = self.client.session.msg('history_request', content)
123 self._dispatch_to_kernel(msg)
124 return msg['header']['msg_id']
125
126 def shutdown(self, restart=False):
127 # FIXME: What to do here?
128 raise NotImplementedError('Cannot shutdown in-process kernel')
129
130 #--------------------------------------------------------------------------
131 # Protected interface
132 #--------------------------------------------------------------------------
133
134 def _dispatch_to_kernel(self, msg):
135 """ Send a message to the kernel and handle a reply.
136 """
137 kernel = self.client.kernel
138 if kernel is None:
139 raise RuntimeError('Cannot send request. No kernel exists.')
140
141 stream = DummySocket()
142 self.client.session.send(stream, msg)
143 msg_parts = stream.recv_multipart()
144 kernel.dispatch_shell(stream, msg_parts)
145
146 idents, reply_msg = self.client.session.recv(stream, copy=False)
147 self.call_handlers_later(reply_msg)
148
149
150 class InProcessIOPubChannel(InProcessChannel):
151 """See `IPython.kernel.channels.IOPubChannel` for docstrings."""
152
153 def flush(self, timeout=1.0):
154 pass
155
156
157 class InProcessStdInChannel(InProcessChannel):
158 """See `IPython.kernel.channels.StdInChannel` for docstrings."""
159
160 proxy_methods = ['input']
161
162 def input(self, string):
163 kernel = self.client.kernel
164 if kernel is None:
165 raise RuntimeError('Cannot send input reply. No kernel exists.')
166 kernel.raw_input_str = string
167
168
169 class InProcessHBChannel(InProcessChannel):
170 """See `IPython.kernel.channels.HBChannel` for docstrings."""
171
172 time_to_dead = 3.0
173
174 def __init__(self, *args, **kwds):
175 super(InProcessHBChannel, self).__init__(*args, **kwds)
176 self._pause = True
177
178 def pause(self):
179 self._pause = True
180
181 def unpause(self):
182 self._pause = False
183
184 def is_beating(self):
185 return not self._pause
186
187 #-----------------------------------------------------------------------------
188 # ABC Registration
189 #-----------------------------------------------------------------------------
190
191 ShellChannelABC.register(InProcessShellChannel)
192 IOPubChannelABC.register(InProcessIOPubChannel)
193 HBChannelABC.register(InProcessHBChannel)
194 StdInChannelABC.register(InProcessStdInChannel)
@@ -2,12 +2,14 b''
2 """
2 """
3
3
4 # Local imports.
4 # Local imports.
5 from IPython.kernel.inprocess.kernelmanager import \
5 from IPython.kernel.inprocess import (
6 InProcessShellChannel, InProcessIOPubChannel, InProcessStdInChannel, \
6 InProcessShellChannel, InProcessIOPubChannel, InProcessStdInChannel,
7 InProcessHBChannel, InProcessKernelManager
7 InProcessHBChannel, InProcessKernelClient
8 )
9
8 from IPython.utils.traitlets import Type
10 from IPython.utils.traitlets import Type
9 from base_kernelmanager import QtShellChannelMixin, QtIOPubChannelMixin, \
11 from kernel_mixins import QtShellChannelMixin, QtIOPubChannelMixin, \
10 QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
12 QtStdInChannelMixin, QtHBChannelMixin, QtKernelClientMixin
11
13
12
14
13 class QtInProcessShellChannel(QtShellChannelMixin, InProcessShellChannel):
15 class QtInProcessShellChannel(QtShellChannelMixin, InProcessShellChannel):
@@ -22,8 +24,7 b' class QtInProcessStdInChannel(QtStdInChannelMixin, InProcessStdInChannel):'
22 class QtInProcessHBChannel(QtHBChannelMixin, InProcessHBChannel):
24 class QtInProcessHBChannel(QtHBChannelMixin, InProcessHBChannel):
23 pass
25 pass
24
26
25
27 class QtInProcessKernelClient(QtKernelClientMixin, InProcessKernelClient):
26 class QtInProcessKernelManager(QtKernelManagerMixin, InProcessKernelManager):
27 """ An in-process KernelManager with signals and slots.
28 """ An in-process KernelManager with signals and slots.
28 """
29 """
29
30
@@ -0,0 +1,8 b''
1 from .channels import (
2 InProcessShellChannel,
3 InProcessIOPubChannel,
4 InProcessStdInChannel,
5 InProcessHBChannel,
6 )
7 from .client import InProcessKernelClient
8 from .manager import InProcessKernelManager No newline at end of file
@@ -1,4 +1,4 b''
1 """ Implements a fully blocking kernel manager.
1 """ Implements a fully blocking kernel client.
2
2
3 Useful for test suites and blocking terminal interfaces.
3 Useful for test suites and blocking terminal interfaces.
4 """
4 """
@@ -12,15 +12,19 b' Useful for test suites and blocking terminal interfaces.'
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 from __future__ import print_function
16
15
17 # Local imports.
16 # IPython imports
18 from IPython.utils.io import raw_print
17 from IPython.utils.io import raw_print
19 from IPython.utils.traitlets import Type
18 from IPython.utils.traitlets import Type
20 from kernelmanager import InProcessKernelManager, InProcessShellChannel, \
19 from IPython.kernel.blocking.channels import BlockingChannelMixin
21 InProcessIOPubChannel, InProcessStdInChannel
22 from IPython.kernel.blockingkernelmanager import BlockingChannelMixin
23
20
21 # Local imports
22 from .channels import (
23 InProcessShellChannel,
24 InProcessIOPubChannel,
25 InProcessStdInChannel,
26 )
27 from .client import InProcessKernelClient
24
28
25 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
26 # Blocking kernel manager
30 # Blocking kernel manager
@@ -33,7 +37,7 b' class BlockingInProcessIOPubChannel(BlockingChannelMixin, InProcessIOPubChannel)'
33 pass
37 pass
34
38
35 class BlockingInProcessStdInChannel(BlockingChannelMixin, InProcessStdInChannel):
39 class BlockingInProcessStdInChannel(BlockingChannelMixin, InProcessStdInChannel):
36
40
37 def call_handlers(self, msg):
41 def call_handlers(self, msg):
38 """ Overridden for the in-process channel.
42 """ Overridden for the in-process channel.
39
43
@@ -41,12 +45,12 b' class BlockingInProcessStdInChannel(BlockingChannelMixin, InProcessStdInChannel)'
41 """
45 """
42 msg_type = msg['header']['msg_type']
46 msg_type = msg['header']['msg_type']
43 if msg_type == 'input_request':
47 if msg_type == 'input_request':
44 _raw_input = self.manager.kernel._sys_raw_input
48 _raw_input = self.client.kernel._sys_raw_input
45 prompt = msg['content']['prompt']
49 prompt = msg['content']['prompt']
46 raw_print(prompt, end='')
50 raw_print(prompt, end='')
47 self.input(_raw_input())
51 self.input(_raw_input())
48
52
49 class BlockingInProcessKernelManager(InProcessKernelManager):
53 class BlockingInProcessKernelClient(InProcessKernelClient):
50
54
51 # The classes to use for the various channels.
55 # The classes to use for the various channels.
52 shell_channel_class = Type(BlockingInProcessShellChannel)
56 shell_channel_class = Type(BlockingInProcessShellChannel)
@@ -1,4 +1,4 b''
1 """ A kernel manager 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
@@ -11,238 +11,49 b''
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 # Local imports.
14 # IPython imports
15 from IPython.config.configurable import Configurable
15 from IPython.utils.traitlets import Type, Instance
16 from IPython.utils.traitlets import Any, Instance, Type
16 from IPython.kernel.clientabc import KernelClientABC
17 from IPython.kernel.kernelmanagerabc import (
17 from IPython.kernel.client import KernelClient
18 ShellChannelABC, IOPubChannelABC,
19 HBChannelABC, StdInChannelABC,
20 KernelManagerABC
21 )
22
23 from .socket import DummySocket
24
25 #-----------------------------------------------------------------------------
26 # Channel classes
27 #-----------------------------------------------------------------------------
28
29 class InProcessChannel(object):
30 """Base class for in-process channels."""
31
32 def __init__(self, manager):
33 super(InProcessChannel, self).__init__()
34 self.manager = manager
35 self._is_alive = False
36
37 #--------------------------------------------------------------------------
38 # Channel interface
39 #--------------------------------------------------------------------------
40
41 def is_alive(self):
42 return self._is_alive
43
44 def start(self):
45 self._is_alive = True
46
47 def stop(self):
48 self._is_alive = False
49
50 def call_handlers(self, msg):
51 """ This method is called in the main thread when a message arrives.
52
53 Subclasses should override this method to handle incoming messages.
54 """
55 raise NotImplementedError('call_handlers must be defined in a subclass.')
56
57 #--------------------------------------------------------------------------
58 # InProcessChannel interface
59 #--------------------------------------------------------------------------
60
61 def call_handlers_later(self, *args, **kwds):
62 """ Call the message handlers later.
63
64 The default implementation just calls the handlers immediately, but this
65 method exists so that GUI toolkits can defer calling the handlers until
66 after the event loop has run, as expected by GUI frontends.
67 """
68 self.call_handlers(*args, **kwds)
69
70 def process_events(self):
71 """ Process any pending GUI events.
72
73 This method will be never be called from a frontend without an event
74 loop (e.g., a terminal frontend).
75 """
76 raise NotImplementedError
77
78
79 class InProcessShellChannel(InProcessChannel):
80 """See `IPython.kernel.kernelmanager.ShellChannel` for docstrings."""
81
82 # flag for whether execute requests should be allowed to call raw_input
83 allow_stdin = True
84
85 #--------------------------------------------------------------------------
86 # ShellChannel interface
87 #--------------------------------------------------------------------------
88
89 def execute(self, code, silent=False, store_history=True,
90 user_variables=[], user_expressions={}, allow_stdin=None):
91 if allow_stdin is None:
92 allow_stdin = self.allow_stdin
93 content = dict(code=code, silent=silent, store_history=store_history,
94 user_variables=user_variables,
95 user_expressions=user_expressions,
96 allow_stdin=allow_stdin)
97 msg = self.manager.session.msg('execute_request', content)
98 self._dispatch_to_kernel(msg)
99 return msg['header']['msg_id']
100
101 def complete(self, text, line, cursor_pos, block=None):
102 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
103 msg = self.manager.session.msg('complete_request', content)
104 self._dispatch_to_kernel(msg)
105 return msg['header']['msg_id']
106
107 def object_info(self, oname, detail_level=0):
108 content = dict(oname=oname, detail_level=detail_level)
109 msg = self.manager.session.msg('object_info_request', content)
110 self._dispatch_to_kernel(msg)
111 return msg['header']['msg_id']
112
113 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
114 content = dict(raw=raw, output=output,
115 hist_access_type=hist_access_type, **kwds)
116 msg = self.manager.session.msg('history_request', content)
117 self._dispatch_to_kernel(msg)
118 return msg['header']['msg_id']
119
120 def shutdown(self, restart=False):
121 # FIXME: What to do here?
122 raise NotImplementedError('Cannot shutdown in-process kernel')
123
124 #--------------------------------------------------------------------------
125 # Protected interface
126 #--------------------------------------------------------------------------
127
18
128 def _dispatch_to_kernel(self, msg):
19 # Local imports
129 """ Send a message to the kernel and handle a reply.
20 from .channels import (
130 """
21 InProcessShellChannel,
131 kernel = self.manager.kernel
22 InProcessIOPubChannel,
132 if kernel is None:
23 InProcessHBChannel,
133 raise RuntimeError('Cannot send request. No kernel exists.')
24 InProcessStdInChannel,
134
135 stream = DummySocket()
136 self.manager.session.send(stream, msg)
137 msg_parts = stream.recv_multipart()
138 kernel.dispatch_shell(stream, msg_parts)
139
140 idents, reply_msg = self.manager.session.recv(stream, copy=False)
141 self.call_handlers_later(reply_msg)
142
143
144 class InProcessIOPubChannel(InProcessChannel):
145 """See `IPython.kernel.kernelmanager.IOPubChannel` for docstrings."""
146
147 def flush(self, timeout=1.0):
148 pass
149
150
151 class InProcessStdInChannel(InProcessChannel):
152 """See `IPython.kernel.kernelmanager.StdInChannel` for docstrings."""
153
154 def input(self, string):
155 kernel = self.manager.kernel
156 if kernel is None:
157 raise RuntimeError('Cannot send input reply. No kernel exists.')
158 kernel.raw_input_str = string
159
160
161 class InProcessHBChannel(InProcessChannel):
162 """See `IPython.kernel.kernelmanager.HBChannel` for docstrings."""
163
164 time_to_dead = 3.0
165
166 def __init__(self, *args, **kwds):
167 super(InProcessHBChannel, self).__init__(*args, **kwds)
168 self._pause = True
169
170 def pause(self):
171 self._pause = True
172
173 def unpause(self):
174 self._pause = False
175
176 def is_beating(self):
177 return not self._pause
178
25
26 )
179
27
180 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
181 # Main kernel manager class
29 # Main kernel Client class
182 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
183
31
184 class InProcessKernelManager(KernelManager):
32 class InProcessKernelClient(KernelClient):
185 """A manager for an in-process kernel.
33 """A client for an in-process kernel.
186
34
187 This class implements the interface of
35 This class implements the interface of
188 `IPython.kernel.kernelmanagerabc.KernelManagerABC` and allows
36 `IPython.kernel.clientabc.KernelClientABC` and allows
189 (asynchronous) frontends to be used seamlessly with an in-process kernel.
37 (asynchronous) frontends to be used seamlessly with an in-process kernel.
190
38
191 See `IPython.kernel.kernelmanager.KernelManager` for docstrings.
39 See `IPython.kernel.client.KernelClient` for docstrings.
192 """
40 """
193
41
194 # The Session to use for building messages.
195 session = Instance('IPython.kernel.zmq.session.Session')
196 def _session_default(self):
197 from IPython.kernel.zmq.session import Session
198 return Session(config=self.config)
199
200 # The kernel process with which the KernelManager is communicating.
201 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
202
203 # The classes to use for the various channels.
42 # The classes to use for the various channels.
204 shell_channel_class = Type(InProcessShellChannel)
43 shell_channel_class = Type(InProcessShellChannel)
205 iopub_channel_class = Type(InProcessIOPubChannel)
44 iopub_channel_class = Type(InProcessIOPubChannel)
206 stdin_channel_class = Type(InProcessStdInChannel)
45 stdin_channel_class = Type(InProcessStdInChannel)
207 hb_channel_class = Type(InProcessHBChannel)
46 hb_channel_class = Type(InProcessHBChannel)
208
47
209 # Protected traits.
48 kernel = Instance('IPython.kernel.inprocess.ipkernel.Kernel')
210 _shell_channel = Any
211 _iopub_channel = Any
212 _stdin_channel = Any
213 _hb_channel = Any
214
49
215 #--------------------------------------------------------------------------
50 #--------------------------------------------------------------------------
216 # Channel management methods.
51 # Channel management methods
217 #--------------------------------------------------------------------------
52 #--------------------------------------------------------------------------
218
53
219 def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):
54 def start_channels(self, *args, **kwargs):
220 if shell:
55 super(InProcessKernelClient, self).start_channels(self)
221 self.shell_channel.start()
56 self.kernel.frontends.append(self)
222 if iopub:
223 self.iopub_channel.start()
224 if stdin:
225 self.stdin_channel.start()
226 self.shell_channel.allow_stdin = True
227 else:
228 self.shell_channel.allow_stdin = False
229 if hb:
230 self.hb_channel.start()
231
232 def stop_channels(self):
233 if self.shell_channel.is_alive():
234 self.shell_channel.stop()
235 if self.iopub_channel.is_alive():
236 self.iopub_channel.stop()
237 if self.stdin_channel.is_alive():
238 self.stdin_channel.stop()
239 if self.hb_channel.is_alive():
240 self.hb_channel.stop()
241
242 @property
243 def channels_running(self):
244 return (self.shell_channel.is_alive() or self.iopub_channel.is_alive() or
245 self.stdin_channel.is_alive() or self.hb_channel.is_alive())
246
57
247 @property
58 @property
248 def shell_channel(self):
59 def shell_channel(self):
@@ -268,46 +79,9 b' class InProcessKernelManager(KernelManager):'
268 self._hb_channel = self.hb_channel_class(self)
79 self._hb_channel = self.hb_channel_class(self)
269 return self._hb_channel
80 return self._hb_channel
270
81
271 #--------------------------------------------------------------------------
272 # Kernel management methods:
273 #--------------------------------------------------------------------------
274
275 def start_kernel(self, **kwds):
276 from IPython.kernel.inprocess.ipkernel import InProcessKernel
277 self.kernel = InProcessKernel()
278 self.kernel.frontends.append(self)
279
280 def shutdown_kernel(self):
281 self._kill_kernel()
282
283 def restart_kernel(self, now=False, **kwds):
284 self.shutdown_kernel()
285 self.start_kernel(**kwds)
286
287 @property
288 def has_kernel(self):
289 return self.kernel is not None
290
291 def _kill_kernel(self):
292 self.kernel.frontends.remove(self)
293 self.kernel = None
294
295 def interrupt_kernel(self):
296 raise NotImplementedError("Cannot interrupt in-process kernel.")
297
298 def signal_kernel(self, signum):
299 raise NotImplementedError("Cannot signal in-process kernel.")
300
301 def is_alive(self):
302 return True
303
304
82
305 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
306 # ABC Registration
84 # ABC Registration
307 #-----------------------------------------------------------------------------
85 #-----------------------------------------------------------------------------
308
86
309 ShellChannelABC.register(InProcessShellChannel)
87 KernelClientABC.register(InProcessKernelClient)
310 IOPubChannelABC.register(InProcessIOPubChannel)
311 HBChannelABC.register(InProcessHBChannel)
312 StdInChannelABC.register(InProcessStdInChannel)
313 KernelManagerABC.register(InProcessKernelManager)
@@ -37,7 +37,8 b' class InProcessKernel(Kernel):'
37
37
38 # The frontends connected to this kernel.
38 # The frontends connected to this kernel.
39 frontends = List(
39 frontends = List(
40 Instance('IPython.kernel.inprocess.kernelmanager.InProcessKernelManager'))
40 Instance('IPython.kernel.inprocess.client.InProcessKernelClient')
41 )
41
42
42 # The GUI environment that the kernel is running under. This need not be
43 # The GUI environment that the kernel is running under. This need not be
43 # specified for the normal operation for the kernel, but is required for
44 # specified for the normal operation for the kernel, but is required for
@@ -1,7 +1,7 b''
1 """ A kernel manager for in-process kernels. """
1 """A kernel manager for in-process kernels."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2012 The IPython Development Team
4 # Copyright (C) 2013 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.
@@ -11,177 +11,15 b''
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 # Local imports.
14 from IPython.utils.traitlets import Instance
15 from IPython.config.configurable import Configurable
15 from IPython.kernel.managerabc import KernelManagerABC
16 from IPython.utils.traitlets import Any, Instance, Type
16 from IPython.kernel.manager import KernelManager
17 from IPython.kernel.kernelmanagerabc import (
18 ShellChannelABC, IOPubChannelABC,
19 HBChannelABC, StdInChannelABC,
20 KernelManagerABC
21 )
22
23 from .socket import DummySocket
24
25 #-----------------------------------------------------------------------------
26 # Channel classes
27 #-----------------------------------------------------------------------------
28
29 class InProcessChannel(object):
30 """Base class for in-process channels."""
31
32 def __init__(self, manager):
33 super(InProcessChannel, self).__init__()
34 self.manager = manager
35 self._is_alive = False
36
37 #--------------------------------------------------------------------------
38 # Channel interface
39 #--------------------------------------------------------------------------
40
41 def is_alive(self):
42 return self._is_alive
43
44 def start(self):
45 self._is_alive = True
46
47 def stop(self):
48 self._is_alive = False
49
50 def call_handlers(self, msg):
51 """ This method is called in the main thread when a message arrives.
52
53 Subclasses should override this method to handle incoming messages.
54 """
55 raise NotImplementedError('call_handlers must be defined in a subclass.')
56
57 #--------------------------------------------------------------------------
58 # InProcessChannel interface
59 #--------------------------------------------------------------------------
60
61 def call_handlers_later(self, *args, **kwds):
62 """ Call the message handlers later.
63
64 The default implementation just calls the handlers immediately, but this
65 method exists so that GUI toolkits can defer calling the handlers until
66 after the event loop has run, as expected by GUI frontends.
67 """
68 self.call_handlers(*args, **kwds)
69
70 def process_events(self):
71 """ Process any pending GUI events.
72
73 This method will be never be called from a frontend without an event
74 loop (e.g., a terminal frontend).
75 """
76 raise NotImplementedError
77
78
79 class InProcessShellChannel(InProcessChannel):
80 """See `IPython.kernel.kernelmanager.ShellChannel` for docstrings."""
81
82 # flag for whether execute requests should be allowed to call raw_input
83 allow_stdin = True
84
85 #--------------------------------------------------------------------------
86 # ShellChannel interface
87 #--------------------------------------------------------------------------
88
89 def execute(self, code, silent=False, store_history=True,
90 user_variables=[], user_expressions={}, allow_stdin=None):
91 if allow_stdin is None:
92 allow_stdin = self.allow_stdin
93 content = dict(code=code, silent=silent, store_history=store_history,
94 user_variables=user_variables,
95 user_expressions=user_expressions,
96 allow_stdin=allow_stdin)
97 msg = self.manager.session.msg('execute_request', content)
98 self._dispatch_to_kernel(msg)
99 return msg['header']['msg_id']
100
101 def complete(self, text, line, cursor_pos, block=None):
102 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
103 msg = self.manager.session.msg('complete_request', content)
104 self._dispatch_to_kernel(msg)
105 return msg['header']['msg_id']
106
107 def object_info(self, oname, detail_level=0):
108 content = dict(oname=oname, detail_level=detail_level)
109 msg = self.manager.session.msg('object_info_request', content)
110 self._dispatch_to_kernel(msg)
111 return msg['header']['msg_id']
112
113 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
114 content = dict(raw=raw, output=output,
115 hist_access_type=hist_access_type, **kwds)
116 msg = self.manager.session.msg('history_request', content)
117 self._dispatch_to_kernel(msg)
118 return msg['header']['msg_id']
119
120 def shutdown(self, restart=False):
121 # FIXME: What to do here?
122 raise NotImplementedError('Cannot shutdown in-process kernel')
123
124 #--------------------------------------------------------------------------
125 # Protected interface
126 #--------------------------------------------------------------------------
127
128 def _dispatch_to_kernel(self, msg):
129 """ Send a message to the kernel and handle a reply.
130 """
131 kernel = self.manager.kernel
132 if kernel is None:
133 raise RuntimeError('Cannot send request. No kernel exists.')
134
135 stream = DummySocket()
136 self.manager.session.send(stream, msg)
137 msg_parts = stream.recv_multipart()
138 kernel.dispatch_shell(stream, msg_parts)
139
140 idents, reply_msg = self.manager.session.recv(stream, copy=False)
141 self.call_handlers_later(reply_msg)
142
143
144 class InProcessIOPubChannel(InProcessChannel):
145 """See `IPython.kernel.kernelmanager.IOPubChannel` for docstrings."""
146
147 def flush(self, timeout=1.0):
148 pass
149
150
151 class InProcessStdInChannel(InProcessChannel):
152 """See `IPython.kernel.kernelmanager.StdInChannel` for docstrings."""
153
154 def input(self, string):
155 kernel = self.manager.kernel
156 if kernel is None:
157 raise RuntimeError('Cannot send input reply. No kernel exists.')
158 kernel.raw_input_str = string
159
160
161 class InProcessHBChannel(InProcessChannel):
162 """See `IPython.kernel.kernelmanager.HBChannel` for docstrings."""
163
164 time_to_dead = 3.0
165
166 def __init__(self, *args, **kwds):
167 super(InProcessHBChannel, self).__init__(*args, **kwds)
168 self._pause = True
169
170 def pause(self):
171 self._pause = True
172
173 def unpause(self):
174 self._pause = False
175
176 def is_beating(self):
177 return not self._pause
178
179
17
180 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
181 # Main kernel manager class
19 # Main kernel manager class
182 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
183
21
184 class InProcessKernelManager(Configurable):
22 class InProcessKernelManager(KernelManager):
185 """A manager for an in-process kernel.
23 """A manager for an in-process kernel.
186
24
187 This class implements the interface of
25 This class implements the interface of
@@ -191,91 +29,16 b' class InProcessKernelManager(Configurable):'
191 See `IPython.kernel.kernelmanager.KernelManager` for docstrings.
29 See `IPython.kernel.kernelmanager.KernelManager` for docstrings.
192 """
30 """
193
31
194 # The Session to use for building messages.
195 session = Instance('IPython.kernel.zmq.session.Session')
196 def _session_default(self):
197 from IPython.kernel.zmq.session import Session
198 return Session(config=self.config)
199
200 # The kernel process with which the KernelManager is communicating.
32 # The kernel process with which the KernelManager is communicating.
201 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
33 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
202
34
203 # The classes to use for the various channels.
204 shell_channel_class = Type(InProcessShellChannel)
205 iopub_channel_class = Type(InProcessIOPubChannel)
206 stdin_channel_class = Type(InProcessStdInChannel)
207 hb_channel_class = Type(InProcessHBChannel)
208
209 # Protected traits.
210 _shell_channel = Any
211 _iopub_channel = Any
212 _stdin_channel = Any
213 _hb_channel = Any
214
215 #--------------------------------------------------------------------------
216 # Channel management methods.
217 #--------------------------------------------------------------------------
218
219 def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):
220 if shell:
221 self.shell_channel.start()
222 if iopub:
223 self.iopub_channel.start()
224 if stdin:
225 self.stdin_channel.start()
226 self.shell_channel.allow_stdin = True
227 else:
228 self.shell_channel.allow_stdin = False
229 if hb:
230 self.hb_channel.start()
231
232 def stop_channels(self):
233 if self.shell_channel.is_alive():
234 self.shell_channel.stop()
235 if self.iopub_channel.is_alive():
236 self.iopub_channel.stop()
237 if self.stdin_channel.is_alive():
238 self.stdin_channel.stop()
239 if self.hb_channel.is_alive():
240 self.hb_channel.stop()
241
242 @property
243 def channels_running(self):
244 return (self.shell_channel.is_alive() or self.iopub_channel.is_alive() or
245 self.stdin_channel.is_alive() or self.hb_channel.is_alive())
246
247 @property
248 def shell_channel(self):
249 if self._shell_channel is None:
250 self._shell_channel = self.shell_channel_class(self)
251 return self._shell_channel
252
253 @property
254 def iopub_channel(self):
255 if self._iopub_channel is None:
256 self._iopub_channel = self.iopub_channel_class(self)
257 return self._iopub_channel
258
259 @property
260 def stdin_channel(self):
261 if self._stdin_channel is None:
262 self._stdin_channel = self.stdin_channel_class(self)
263 return self._stdin_channel
264
265 @property
266 def hb_channel(self):
267 if self._hb_channel is None:
268 self._hb_channel = self.hb_channel_class(self)
269 return self._hb_channel
270
271 #--------------------------------------------------------------------------
35 #--------------------------------------------------------------------------
272 # Kernel management methods:
36 # Kernel management methods
273 #--------------------------------------------------------------------------
37 #--------------------------------------------------------------------------
274
38
275 def start_kernel(self, **kwds):
39 def start_kernel(self, **kwds):
276 from IPython.kernel.inprocess.ipkernel import InProcessKernel
40 from IPython.kernel.inprocess.ipkernel import InProcessKernel
277 self.kernel = InProcessKernel()
41 self.kernel = InProcessKernel()
278 self.kernel.frontends.append(self)
279
42
280 def shutdown_kernel(self):
43 def shutdown_kernel(self):
281 self._kill_kernel()
44 self._kill_kernel()
@@ -289,7 +52,6 b' class InProcessKernelManager(Configurable):'
289 return self.kernel is not None
52 return self.kernel is not None
290
53
291 def _kill_kernel(self):
54 def _kill_kernel(self):
292 self.kernel.frontends.remove(self)
293 self.kernel = None
55 self.kernel = None
294
56
295 def interrupt_kernel(self):
57 def interrupt_kernel(self):
@@ -306,8 +68,4 b' class InProcessKernelManager(Configurable):'
306 # ABC Registration
68 # ABC Registration
307 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
308
70
309 ShellChannelABC.register(InProcessShellChannel)
310 IOPubChannelABC.register(InProcessIOPubChannel)
311 HBChannelABC.register(InProcessHBChannel)
312 StdInChannelABC.register(InProcessStdInChannel)
313 KernelManagerABC.register(InProcessKernelManager)
71 KernelManagerABC.register(InProcessKernelManager)
@@ -16,8 +16,8 b' import sys'
16 import unittest
16 import unittest
17
17
18 # Local imports
18 # Local imports
19 from IPython.kernel.inprocess.blockingkernelmanager import \
19 from IPython.kernel.inprocess.blocking import BlockingInProcessKernelClient
20 BlockingInProcessKernelManager
20 from IPython.kernel.inprocess.manager import InProcessKernelManager
21 from IPython.kernel.inprocess.ipkernel import InProcessKernel
21 from IPython.kernel.inprocess.ipkernel import InProcessKernel
22 from IPython.testing.decorators import skipif_not_matplotlib
22 from IPython.testing.decorators import skipif_not_matplotlib
23 from IPython.utils.io import capture_output
23 from IPython.utils.io import capture_output
@@ -29,33 +29,35 b' from IPython.utils import py3compat'
29
29
30 class InProcessKernelTestCase(unittest.TestCase):
30 class InProcessKernelTestCase(unittest.TestCase):
31
31
32 def setUp(self):
33 self.km = InProcessKernelManager()
34 self.km.start_kernel()
35 self.kc = BlockingInProcessKernelClient(kernel=self.km.kernel)
36 self.kc.start_channels()
37
32 @skipif_not_matplotlib
38 @skipif_not_matplotlib
33 def test_pylab(self):
39 def test_pylab(self):
34 """ Does pylab work in the in-process kernel?
40 """ Does pylab work in the in-process kernel?
35 """
41 """
36 km = BlockingInProcessKernelManager()
42 kc = self.kc
37 km.start_kernel()
43 kc.execute('%pylab')
38 km.shell_channel.execute('%pylab')
44 msg = get_stream_message(kc)
39 msg = get_stream_message(km)
40 self.assert_('Welcome to pylab' in msg['content']['data'])
45 self.assert_('Welcome to pylab' in msg['content']['data'])
41
46
42 def test_raw_input(self):
47 def test_raw_input(self):
43 """ Does the in-process kernel handle raw_input correctly?
48 """ Does the in-process kernel handle raw_input correctly?
44 """
49 """
45 km = BlockingInProcessKernelManager()
46 km.start_kernel()
47
48 io = StringIO('foobar\n')
50 io = StringIO('foobar\n')
49 sys_stdin = sys.stdin
51 sys_stdin = sys.stdin
50 sys.stdin = io
52 sys.stdin = io
51 try:
53 try:
52 if py3compat.PY3:
54 if py3compat.PY3:
53 km.shell_channel.execute('x = input()')
55 self.kc.execute('x = input()')
54 else:
56 else:
55 km.shell_channel.execute('x = raw_input()')
57 self.kc.execute('x = raw_input()')
56 finally:
58 finally:
57 sys.stdin = sys_stdin
59 sys.stdin = sys_stdin
58 self.assertEqual(km.kernel.shell.user_ns.get('x'), 'foobar')
60 self.assertEqual(self.km.kernel.shell.user_ns.get('x'), 'foobar')
59
61
60 def test_stdout(self):
62 def test_stdout(self):
61 """ Does the in-process kernel correctly capture IO?
63 """ Does the in-process kernel correctly capture IO?
@@ -66,21 +68,21 b' class InProcessKernelTestCase(unittest.TestCase):'
66 kernel.shell.run_cell('print("foo")')
68 kernel.shell.run_cell('print("foo")')
67 self.assertEqual(io.stdout, 'foo\n')
69 self.assertEqual(io.stdout, 'foo\n')
68
70
69 km = BlockingInProcessKernelManager(kernel=kernel)
71 kc = BlockingInProcessKernelClient(kernel=kernel)
70 kernel.frontends.append(km)
72 kernel.frontends.append(kc)
71 km.shell_channel.execute('print("bar")')
73 kc.shell_channel.execute('print("bar")')
72 msg = get_stream_message(km)
74 msg = get_stream_message(kc)
73 self.assertEqual(msg['content']['data'], 'bar\n')
75 self.assertEqual(msg['content']['data'], 'bar\n')
74
76
75 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
76 # Utility functions
78 # Utility functions
77 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
78
80
79 def get_stream_message(kernel_manager, timeout=5):
81 def get_stream_message(kernel_client, timeout=5):
80 """ Gets a single stream message synchronously from the sub channel.
82 """ Gets a single stream message synchronously from the sub channel.
81 """
83 """
82 while True:
84 while True:
83 msg = kernel_manager.iopub_channel.get_msg(timeout=timeout)
85 msg = kernel_client.get_iopub_msg(timeout=timeout)
84 if msg['header']['msg_type'] == 'stream':
86 if msg['header']['msg_type'] == 'stream':
85 return msg
87 return msg
86
88
@@ -14,9 +14,9 b' from __future__ import print_function'
14 import unittest
14 import unittest
15
15
16 # Local imports
16 # Local imports
17 from IPython.kernel.inprocess.blockingkernelmanager import \
17 from IPython.kernel.inprocess.blocking import BlockingInProcessKernelClient
18 BlockingInProcessKernelManager
19 from IPython.kernel.inprocess.ipkernel import InProcessKernel
18 from IPython.kernel.inprocess.ipkernel import InProcessKernel
19 from IPython.kernel.inprocess.manager import InProcessKernelManager
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Test case
22 # Test case
@@ -24,20 +24,22 b' from IPython.kernel.inprocess.ipkernel import InProcessKernel'
24
24
25 class InProcessKernelManagerTestCase(unittest.TestCase):
25 class InProcessKernelManagerTestCase(unittest.TestCase):
26
26
27 def test_inteface(self):
27 def test_interface(self):
28 """ Does the in-process kernel manager implement the basic KM interface?
28 """ Does the in-process kernel manager implement the basic KM interface?
29 """
29 """
30 km = BlockingInProcessKernelManager()
30 km = InProcessKernelManager()
31 self.assert_(not km.channels_running)
32 self.assert_(not km.has_kernel)
31 self.assert_(not km.has_kernel)
33
32
34 km.start_channels()
35 self.assert_(km.channels_running)
36
37 km.start_kernel()
33 km.start_kernel()
38 self.assert_(km.has_kernel)
34 self.assert_(km.has_kernel)
39 self.assert_(km.kernel is not None)
35 self.assert_(km.kernel is not None)
40
36
37 kc = BlockingInProcessKernelClient(kernel=km.kernel)
38 self.assert_(not kc.channels_running)
39
40 kc.start_channels()
41 self.assert_(kc.channels_running)
42
41 old_kernel = km.kernel
43 old_kernel = km.kernel
42 km.restart_kernel()
44 km.restart_kernel()
43 self.assert_(km.kernel is not None)
45 self.assert_(km.kernel is not None)
@@ -49,37 +51,43 b' class InProcessKernelManagerTestCase(unittest.TestCase):'
49 self.assertRaises(NotImplementedError, km.interrupt_kernel)
51 self.assertRaises(NotImplementedError, km.interrupt_kernel)
50 self.assertRaises(NotImplementedError, km.signal_kernel, 9)
52 self.assertRaises(NotImplementedError, km.signal_kernel, 9)
51
53
52 km.stop_channels()
54 kc.stop_channels()
53 self.assert_(not km.channels_running)
55 self.assert_(not kc.channels_running)
54
56
55 def test_execute(self):
57 def test_execute(self):
56 """ Does executing code in an in-process kernel work?
58 """ Does executing code in an in-process kernel work?
57 """
59 """
58 km = BlockingInProcessKernelManager()
60 km = InProcessKernelManager()
59 km.start_kernel()
61 km.start_kernel()
60 km.shell_channel.execute('foo = 1')
62 kc = BlockingInProcessKernelClient(kernel=km.kernel)
63 kc.start_channels()
64 kc.execute('foo = 1')
61 self.assertEquals(km.kernel.shell.user_ns['foo'], 1)
65 self.assertEquals(km.kernel.shell.user_ns['foo'], 1)
62
66
63 def test_complete(self):
67 def test_complete(self):
64 """ Does requesting completion from an in-process kernel work?
68 """ Does requesting completion from an in-process kernel work?
65 """
69 """
66 km = BlockingInProcessKernelManager()
70 km = InProcessKernelManager()
67 km.start_kernel()
71 km.start_kernel()
72 kc = BlockingInProcessKernelClient(kernel=km.kernel)
73 kc.start_channels()
68 km.kernel.shell.push({'my_bar': 0, 'my_baz': 1})
74 km.kernel.shell.push({'my_bar': 0, 'my_baz': 1})
69 km.shell_channel.complete('my_ba', 'my_ba', 5)
75 kc.complete('my_ba', 'my_ba', 5)
70 msg = km.shell_channel.get_msg()
76 msg = kc.get_shell_msg()
71 self.assertEquals(msg['header']['msg_type'], 'complete_reply')
77 self.assertEqual(msg['header']['msg_type'], 'complete_reply')
72 self.assertEquals(sorted(msg['content']['matches']),
78 self.assertEqual(sorted(msg['content']['matches']),
73 ['my_bar', 'my_baz'])
79 ['my_bar', 'my_baz'])
74
80
75 def test_object_info(self):
81 def test_object_info(self):
76 """ Does requesting object information from an in-process kernel work?
82 """ Does requesting object information from an in-process kernel work?
77 """
83 """
78 km = BlockingInProcessKernelManager()
84 km = InProcessKernelManager()
79 km.start_kernel()
85 km.start_kernel()
86 kc = BlockingInProcessKernelClient(kernel=km.kernel)
87 kc.start_channels()
80 km.kernel.shell.user_ns['foo'] = 1
88 km.kernel.shell.user_ns['foo'] = 1
81 km.shell_channel.object_info('foo')
89 kc.object_info('foo')
82 msg = km.shell_channel.get_msg()
90 msg = kc.get_shell_msg()
83 self.assertEquals(msg['header']['msg_type'], 'object_info_reply')
91 self.assertEquals(msg['header']['msg_type'], 'object_info_reply')
84 self.assertEquals(msg['content']['name'], 'foo')
92 self.assertEquals(msg['content']['name'], 'foo')
85 self.assertEquals(msg['content']['type_name'], 'int')
93 self.assertEquals(msg['content']['type_name'], 'int')
@@ -87,11 +95,13 b' class InProcessKernelManagerTestCase(unittest.TestCase):'
87 def test_history(self):
95 def test_history(self):
88 """ Does requesting history from an in-process kernel work?
96 """ Does requesting history from an in-process kernel work?
89 """
97 """
90 km = BlockingInProcessKernelManager()
98 km = InProcessKernelManager()
91 km.start_kernel()
99 km.start_kernel()
92 km.shell_channel.execute('%who')
100 kc = BlockingInProcessKernelClient(kernel=km.kernel)
93 km.shell_channel.history(hist_access_type='tail', n=1)
101 kc.start_channels()
94 msg = km.shell_channel.get_msgs()[-1]
102 kc.execute('%who')
103 kc.history(hist_access_type='tail', n=1)
104 msg = kc.shell_channel.get_msgs()[-1]
95 self.assertEquals(msg['header']['msg_type'], 'history_reply')
105 self.assertEquals(msg['header']['msg_type'], 'history_reply')
96 history = msg['content']['history']
106 history = msg['content']['history']
97 self.assertEquals(len(history), 1)
107 self.assertEquals(len(history), 1)
General Comments 0
You need to be logged in to leave comments. Login now