6060if jupyter_era :
6161 # Jupyter / IPython 4.x
6262 from jupyter_client import KernelManager
63+ from jupyter_client .kernelspec import KernelSpecManager
64+ kernelSpecManager = KernelSpecManager ()
6365else :
6466 from IPython .kernel import KernelManager
67+ from IPython .kernel .kernelspec import KernelSpecManager
68+ kernelSpecManager = KernelSpecManager ()
6569
6670# End of the great "support IPython 2, 3, 4" strat
6771
@@ -76,6 +80,11 @@ def _debug_write(out):
7680 sys .__stdout__ .flush ()
7781
7882
83+ def listKernelNames ():
84+ """Returns a dict mapping kernel names to resource directories."""
85+ return list (kernelSpecManager .find_kernel_specs ().keys ())
86+
87+
7988class IPythonExitException (Exception ):
8089 pass
8190
@@ -105,7 +114,6 @@ def acquire(self):
105114 def release (self ):
106115 self .lock .release ()
107116
108-
109117class iPythonSocketServer (object ):
110118 """back end for executing REPL code. This base class handles all of the
111119communication with the remote process while derived classes implement the
@@ -114,6 +122,8 @@ class iPythonSocketServer(object):
114122 """Messages sent back as responses"""
115123 _PONG = to_bytes ('PONG' )
116124 _EXIT = to_bytes ('EXIT' )
125+ _LSTK = to_bytes ('LSTK' )
126+ _EROR = to_bytes ('EROR' )
117127
118128 def __init__ (self ):
119129 import threading
@@ -164,18 +174,24 @@ def start_processing(self):
164174 try :
165175 inp = read_bytes (self .conn , 4 )
166176
167- #self.conn.settimeout(None)
177+ # self.conn.settimeout(None)
168178 _debug_write ('Command bytes received: ' )
169- _debug_write ('Command bytes received: ' + str (inp ))
170179
171180 cmd = iPythonSocketServer ._COMMANDS .get (inp )
172- if inp :
173- if cmd is not None :
174- cmd (self )
175- else :
176- if inp :
177- print ('unknown command' , inp )
178- break
181+ if inp and cmd is not None :
182+ id = ""
183+ try :
184+ if iPythonSocketServer ._COMMANDS_WITH_IDS .get (inp ) == True :
185+ id = read_string (self .conn )
186+ cmd (self , id )
187+ else :
188+ cmd (self )
189+ except :
190+ self .replyWithError (inp , id )
191+ else :
192+ if inp :
193+ print ('unknown command' , inp )
194+ break
179195 except socket .timeout :
180196 pass
181197
@@ -200,15 +216,13 @@ def start_processing(self):
200216 def check_for_exit_socket_loop (self ):
201217 return self .exit_requested
202218
203- def _cmd_run (self ):
204- """runs the received snippet of code"""
205- # self.run_command(read_string(self.conn))
206- pass
207-
208- def _cmd_abrt (self ):
209- """aborts the current running command"""
210- # abort command, interrupts execution of the main thread.
211- pass
219+ def replyWithError (self , cmd , id ):
220+ with self .send_lock :
221+ _debug_write ('Replying with error' )
222+ write_bytes (self .conn , iPythonSocketServer ._EROR )
223+ write_string (self .conn , cmd )
224+ write_string (self .conn , "" if id is None else id )
225+ write_string (self .conn , str (traceback .format_exc ()))
212226
213227 def _cmd_exit (self ):
214228 """exits the interactive process"""
@@ -224,6 +238,26 @@ def _cmd_ping(self):
224238 write_bytes (self .conn , iPythonSocketServer ._PONG )
225239 write_string (self .conn , "pong received with message" + message )
226240
241+ def _cmd_lstk (self , id ):
242+ """List kernel specs"""
243+ _debug_write ('Listing kernel specs' )
244+ kernelspecs = json .dumps (listKernelNames ())
245+ with self .send_lock :
246+ _debug_write ('Replying with kernels = ' + kernelspecs )
247+ write_bytes (self .conn , iPythonSocketServer ._LSTK )
248+ write_string (self .conn , id )
249+ write_string (self .conn , kernelspecs )
250+
251+ def _cmd_run (self ):
252+ """runs the received snippet of code"""
253+ # self.run_command(read_string(self.conn))
254+ pass
255+
256+ def _cmd_abrt (self ):
257+ """aborts the current running command"""
258+ # abort command, interrupts execution of the main thread.
259+ pass
260+
227261 def _cmd_inpl (self ):
228262 """handles the input command which returns a string of input"""
229263 self .input_string = read_string (self .conn )
@@ -304,6 +338,11 @@ def flush(self):
304338 to_bytes ('exit' ): _cmd_exit ,
305339 to_bytes ('ping' ): _cmd_ping ,
306340 to_bytes ('inpl' ): _cmd_inpl ,
341+ to_bytes ('lstk' ): _cmd_lstk ,
342+ }
343+
344+ _COMMANDS_WITH_IDS = {
345+ to_bytes ('lstk' ): True ,
307346 }
308347
309348
0 commit comments