##// END OF EJS Templates
Merge pull request #5039 from takluyver/i5031...
Min RK -
r15161:b148375d merge
parent child Browse files
Show More
@@ -1,194 +1,201
1 """ A kernel client for in-process kernels. """
1 """ A kernel 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.channelsabc import (
15 from IPython.kernel.channelsabc import (
16 ShellChannelABC, IOPubChannelABC,
16 ShellChannelABC, IOPubChannelABC,
17 HBChannelABC, StdInChannelABC,
17 HBChannelABC, StdInChannelABC,
18 )
18 )
19
19
20 # Local imports
20 # Local imports
21 from .socket import DummySocket
21 from .socket import DummySocket
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Channel classes
24 # Channel classes
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 class InProcessChannel(object):
27 class InProcessChannel(object):
28 """Base class for in-process channels."""
28 """Base class for in-process channels."""
29 proxy_methods = []
29 proxy_methods = []
30
30
31 def __init__(self, client):
31 def __init__(self, client):
32 super(InProcessChannel, self).__init__()
32 super(InProcessChannel, self).__init__()
33 self.client = client
33 self.client = client
34 self._is_alive = False
34 self._is_alive = False
35
35
36 #--------------------------------------------------------------------------
36 #--------------------------------------------------------------------------
37 # Channel interface
37 # Channel interface
38 #--------------------------------------------------------------------------
38 #--------------------------------------------------------------------------
39
39
40 def is_alive(self):
40 def is_alive(self):
41 return self._is_alive
41 return self._is_alive
42
42
43 def start(self):
43 def start(self):
44 self._is_alive = True
44 self._is_alive = True
45
45
46 def stop(self):
46 def stop(self):
47 self._is_alive = False
47 self._is_alive = False
48
48
49 def call_handlers(self, msg):
49 def call_handlers(self, msg):
50 """ This method is called in the main thread when a message arrives.
50 """ This method is called in the main thread when a message arrives.
51
51
52 Subclasses should override this method to handle incoming messages.
52 Subclasses should override this method to handle incoming messages.
53 """
53 """
54 raise NotImplementedError('call_handlers must be defined in a subclass.')
54 raise NotImplementedError('call_handlers must be defined in a subclass.')
55
55
56 #--------------------------------------------------------------------------
56 #--------------------------------------------------------------------------
57 # InProcessChannel interface
57 # InProcessChannel interface
58 #--------------------------------------------------------------------------
58 #--------------------------------------------------------------------------
59
59
60 def call_handlers_later(self, *args, **kwds):
60 def call_handlers_later(self, *args, **kwds):
61 """ Call the message handlers later.
61 """ Call the message handlers later.
62
62
63 The default implementation just calls the handlers immediately, but this
63 The default implementation just calls the handlers immediately, but this
64 method exists so that GUI toolkits can defer calling the handlers until
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.
65 after the event loop has run, as expected by GUI frontends.
66 """
66 """
67 self.call_handlers(*args, **kwds)
67 self.call_handlers(*args, **kwds)
68
68
69 def process_events(self):
69 def process_events(self):
70 """ Process any pending GUI events.
70 """ Process any pending GUI events.
71
71
72 This method will be never be called from a frontend without an event
72 This method will be never be called from a frontend without an event
73 loop (e.g., a terminal frontend).
73 loop (e.g., a terminal frontend).
74 """
74 """
75 raise NotImplementedError
75 raise NotImplementedError
76
76
77
77
78 class InProcessShellChannel(InProcessChannel):
78 class InProcessShellChannel(InProcessChannel):
79 """See `IPython.kernel.channels.ShellChannel` for docstrings."""
79 """See `IPython.kernel.channels.ShellChannel` for docstrings."""
80
80
81 # flag for whether execute requests should be allowed to call raw_input
81 # flag for whether execute requests should be allowed to call raw_input
82 allow_stdin = True
82 allow_stdin = True
83 proxy_methods = [
83 proxy_methods = [
84 'execute',
84 'execute',
85 'complete',
85 'complete',
86 'object_info',
86 'object_info',
87 'history',
87 'history',
88 'shutdown',
88 'shutdown',
89 'kernel_info',
89 ]
90 ]
90
91
91 #--------------------------------------------------------------------------
92 #--------------------------------------------------------------------------
92 # ShellChannel interface
93 # ShellChannel interface
93 #--------------------------------------------------------------------------
94 #--------------------------------------------------------------------------
94
95
95 def execute(self, code, silent=False, store_history=True,
96 def execute(self, code, silent=False, store_history=True,
96 user_variables=[], user_expressions={}, allow_stdin=None):
97 user_variables=[], user_expressions={}, allow_stdin=None):
97 if allow_stdin is None:
98 if allow_stdin is None:
98 allow_stdin = self.allow_stdin
99 allow_stdin = self.allow_stdin
99 content = dict(code=code, silent=silent, store_history=store_history,
100 content = dict(code=code, silent=silent, store_history=store_history,
100 user_variables=user_variables,
101 user_variables=user_variables,
101 user_expressions=user_expressions,
102 user_expressions=user_expressions,
102 allow_stdin=allow_stdin)
103 allow_stdin=allow_stdin)
103 msg = self.client.session.msg('execute_request', content)
104 msg = self.client.session.msg('execute_request', content)
104 self._dispatch_to_kernel(msg)
105 self._dispatch_to_kernel(msg)
105 return msg['header']['msg_id']
106 return msg['header']['msg_id']
106
107
107 def complete(self, text, line, cursor_pos, block=None):
108 def complete(self, text, line, cursor_pos, block=None):
108 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
109 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
109 msg = self.client.session.msg('complete_request', content)
110 msg = self.client.session.msg('complete_request', content)
110 self._dispatch_to_kernel(msg)
111 self._dispatch_to_kernel(msg)
111 return msg['header']['msg_id']
112 return msg['header']['msg_id']
112
113
113 def object_info(self, oname, detail_level=0):
114 def object_info(self, oname, detail_level=0):
114 content = dict(oname=oname, detail_level=detail_level)
115 content = dict(oname=oname, detail_level=detail_level)
115 msg = self.client.session.msg('object_info_request', content)
116 msg = self.client.session.msg('object_info_request', content)
116 self._dispatch_to_kernel(msg)
117 self._dispatch_to_kernel(msg)
117 return msg['header']['msg_id']
118 return msg['header']['msg_id']
118
119
119 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
120 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
120 content = dict(raw=raw, output=output,
121 content = dict(raw=raw, output=output,
121 hist_access_type=hist_access_type, **kwds)
122 hist_access_type=hist_access_type, **kwds)
122 msg = self.client.session.msg('history_request', content)
123 msg = self.client.session.msg('history_request', content)
123 self._dispatch_to_kernel(msg)
124 self._dispatch_to_kernel(msg)
124 return msg['header']['msg_id']
125 return msg['header']['msg_id']
125
126
126 def shutdown(self, restart=False):
127 def shutdown(self, restart=False):
127 # FIXME: What to do here?
128 # FIXME: What to do here?
128 raise NotImplementedError('Cannot shutdown in-process kernel')
129 raise NotImplementedError('Cannot shutdown in-process kernel')
129
130
131 def kernel_info(self):
132 """Request kernel info."""
133 msg = self.client.session.msg('kernel_info_request')
134 self._dispatch_to_kernel(msg)
135 return msg['header']['msg_id']
136
130 #--------------------------------------------------------------------------
137 #--------------------------------------------------------------------------
131 # Protected interface
138 # Protected interface
132 #--------------------------------------------------------------------------
139 #--------------------------------------------------------------------------
133
140
134 def _dispatch_to_kernel(self, msg):
141 def _dispatch_to_kernel(self, msg):
135 """ Send a message to the kernel and handle a reply.
142 """ Send a message to the kernel and handle a reply.
136 """
143 """
137 kernel = self.client.kernel
144 kernel = self.client.kernel
138 if kernel is None:
145 if kernel is None:
139 raise RuntimeError('Cannot send request. No kernel exists.')
146 raise RuntimeError('Cannot send request. No kernel exists.')
140
147
141 stream = DummySocket()
148 stream = DummySocket()
142 self.client.session.send(stream, msg)
149 self.client.session.send(stream, msg)
143 msg_parts = stream.recv_multipart()
150 msg_parts = stream.recv_multipart()
144 kernel.dispatch_shell(stream, msg_parts)
151 kernel.dispatch_shell(stream, msg_parts)
145
152
146 idents, reply_msg = self.client.session.recv(stream, copy=False)
153 idents, reply_msg = self.client.session.recv(stream, copy=False)
147 self.call_handlers_later(reply_msg)
154 self.call_handlers_later(reply_msg)
148
155
149
156
150 class InProcessIOPubChannel(InProcessChannel):
157 class InProcessIOPubChannel(InProcessChannel):
151 """See `IPython.kernel.channels.IOPubChannel` for docstrings."""
158 """See `IPython.kernel.channels.IOPubChannel` for docstrings."""
152
159
153 def flush(self, timeout=1.0):
160 def flush(self, timeout=1.0):
154 pass
161 pass
155
162
156
163
157 class InProcessStdInChannel(InProcessChannel):
164 class InProcessStdInChannel(InProcessChannel):
158 """See `IPython.kernel.channels.StdInChannel` for docstrings."""
165 """See `IPython.kernel.channels.StdInChannel` for docstrings."""
159
166
160 proxy_methods = ['input']
167 proxy_methods = ['input']
161
168
162 def input(self, string):
169 def input(self, string):
163 kernel = self.client.kernel
170 kernel = self.client.kernel
164 if kernel is None:
171 if kernel is None:
165 raise RuntimeError('Cannot send input reply. No kernel exists.')
172 raise RuntimeError('Cannot send input reply. No kernel exists.')
166 kernel.raw_input_str = string
173 kernel.raw_input_str = string
167
174
168
175
169 class InProcessHBChannel(InProcessChannel):
176 class InProcessHBChannel(InProcessChannel):
170 """See `IPython.kernel.channels.HBChannel` for docstrings."""
177 """See `IPython.kernel.channels.HBChannel` for docstrings."""
171
178
172 time_to_dead = 3.0
179 time_to_dead = 3.0
173
180
174 def __init__(self, *args, **kwds):
181 def __init__(self, *args, **kwds):
175 super(InProcessHBChannel, self).__init__(*args, **kwds)
182 super(InProcessHBChannel, self).__init__(*args, **kwds)
176 self._pause = True
183 self._pause = True
177
184
178 def pause(self):
185 def pause(self):
179 self._pause = True
186 self._pause = True
180
187
181 def unpause(self):
188 def unpause(self):
182 self._pause = False
189 self._pause = False
183
190
184 def is_beating(self):
191 def is_beating(self):
185 return not self._pause
192 return not self._pause
186
193
187 #-----------------------------------------------------------------------------
194 #-----------------------------------------------------------------------------
188 # ABC Registration
195 # ABC Registration
189 #-----------------------------------------------------------------------------
196 #-----------------------------------------------------------------------------
190
197
191 ShellChannelABC.register(InProcessShellChannel)
198 ShellChannelABC.register(InProcessShellChannel)
192 IOPubChannelABC.register(InProcessIOPubChannel)
199 IOPubChannelABC.register(InProcessIOPubChannel)
193 HBChannelABC.register(InProcessHBChannel)
200 HBChannelABC.register(InProcessHBChannel)
194 StdInChannelABC.register(InProcessStdInChannel)
201 StdInChannelABC.register(InProcessStdInChannel)
General Comments 0
You need to be logged in to leave comments. Login now