1414import inspect
1515import types
1616from collections import deque
17+ import os
18+ import warnings
1719
1820try :
1921 import thread
4244 # BaseException not defined until Python 2.5
4345 BaseException = Exception
4446
47+ try :
48+ from Queue import Empty # Python 2
49+ except ImportError :
50+ from queue import Empty # Python 3
51+
52+ # The great "support IPython 2, 3, 4" strat begins
53+ try :
54+ import jupyter
55+ except ImportError :
56+ jupyter_era = False
57+ else :
58+ jupyter_era = True
59+
60+ if jupyter_era :
61+ # Jupyter / IPython 4.x
62+ from jupyter_client import KernelManager
63+ else :
64+ from IPython .kernel import KernelManager
65+
66+ # End of the great "support IPython 2, 3, 4" strat
67+
68+
4569DEBUG = os .environ .get ('DEBUG_DJAYAMANNE_IPYTHON' ) is not None
4670
71+
4772def _debug_write (out ):
4873 if DEBUG :
4974 sys .__stdout__ .write (out )
75+ sys .__stdout__ .write ("\n " )
5076 sys .__stdout__ .flush ()
5177
52- class IPythonExitException (Exception ): pass
78+
79+ class IPythonExitException (Exception ):
80+ pass
81+
5382
5483class SafeSendLock (object ):
5584 """a lock which ensures we're released if we take a KeyboardInterrupt exception acquiring it"""
85+
5686 def __init__ (self ):
5787 self .lock = thread .allocate_lock ()
5888
@@ -75,64 +105,52 @@ def acquire(self):
75105 def release (self ):
76106 self .lock .release ()
77107
108+
78109class iPythonSocketServer (object ):
79110 """back end for executing REPL code. This base class handles all of the
80111communication with the remote process while derived classes implement the
81112actual inspection and introspection."""
82- _MRES = to_bytes ('MRES' )
83- _SRES = to_bytes ('SRES' )
84- _MODS = to_bytes ('MODS' )
85- _IMGD = to_bytes ('IMGD' )
86- _PRPC = to_bytes ('PRPC' )
87- _RDLN = to_bytes ('RDLN' )
88- _STDO = to_bytes ('STDO' )
89- _STDE = to_bytes ('STDE' )
90- _DBGA = to_bytes ('DBGA' )
91- _DETC = to_bytes ('DETC' )
92- _DPNG = to_bytes ('DPNG' )
93- _DXAM = to_bytes ('DXAM' )
94-
95- _MERR = to_bytes ('MERR' )
96- _SERR = to_bytes ('SERR' )
97- _ERRE = to_bytes ('ERRE' )
98- _EXIT = to_bytes ('EXIT' )
99- _DONE = to_bytes ('DONE' )
100- _MODC = to_bytes ('MODC' )
101113
102114 """Messages sent back as responses"""
103115 _PONG = to_bytes ('PONG' )
116+ _EXIT = to_bytes ('EXIT' )
104117
105118 def __init__ (self ):
106119 import threading
107120 self .conn = None
108121 self .send_lock = SafeSendLock ()
109122 self .input_event = threading .Lock ()
110- self .input_event .acquire () # lock starts acquired (we use it like a manual reset event)
123+ # lock starts acquired (we use it like a manual reset event)
124+ self .input_event .acquire ()
111125 self .input_string = None
112126 self .exit_requested = False
113127 self .execute_item = None
114128 self .execute_item_lock = threading .Lock ()
115- self . execute_item_lock . acquire () # lock starts acquired (we use it like manual reset event)
116- self .exit_socket_loop = False
129+ # lock starts acquired (we use it like manual reset event)
130+ self .execute_item_lock . acquire ()
117131
118132 def connect (self , port ):
133+ # start a new thread for communicating w/ the remote process
134+ _debug_write ('Connecting to socket port: ' + str (port ))
119135 self .conn = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
120136 self .conn .connect (('127.0.0.1' , port ))
137+ _debug_write ('Connected to socket port: ' + str (port ))
121138
122139 # perform the handshake
123140 with self .send_lock :
124141 write_string (self .conn , "Some Guid" )
125142 write_int (self .conn , os .getpid ())
126143
127- # start a new thread for communicating w/ the remote process
144+ _debug_write ('Handshake information sent' )
145+
128146 thread .start_new_thread (self .start_processing , ())
129147
130148 def start_processing (self ):
131149 """loop on created thread which processes communicates with the REPL window"""
132- print ('start processing' )
150+
151+ _debug_write ('Started processing thread' )
133152 try :
134153 while True :
135- print ('one' )
136154 if self .check_for_exit_socket_loop ():
137155 break
138156
@@ -142,31 +160,45 @@ def start_processing(self):
142160 self .flush ()
143161 self .conn .settimeout (10 )
144162 print ('check bytes' )
145- inp = read_bytes (self .conn , 4 )
146- self .conn .settimeout (None )
147- if inp == '' :
148- print ('unknown command' , inp )
149- break
163+ _debug_write ('Read command bytes' )
164+ try :
165+ inp = read_bytes (self .conn , 4 )
166+
167+ #self.conn.settimeout(None)
168+ _debug_write ('Command bytes received: ' )
169+ _debug_write ('Command bytes received: ' + str (inp ))
170+
171+ 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
179+ except socket .timeout :
180+ pass
150181
151- self .flush ()
152- cmd = iPythonSocketServer ._COMMANDS .get (inp )
153- if cmd is not None :
154- cmd (self )
155182 except IPythonExitException :
183+ _debug_write ('IPythonExitException' )
184+ _debug_write (traceback .format_exc ())
156185 pass
157186 except socket .error :
187+ _debug_write ('socket error' )
188+ _debug_write (traceback .format_exc ())
158189 pass
159190 except :
160191 print ('crap' )
161192 _debug_write ('error in repl loop' )
162193 _debug_write (traceback .format_exc ())
163194
164- time .sleep (2 ) # try and exit gracefully, then interrupt main if necessary
195+ # try and exit gracefully, then interrupt main if necessary
196+ time .sleep (2 )
165197 traceback .print_exc ()
166198 self .exit_process ()
167199
168200 def check_for_exit_socket_loop (self ):
169- return self .exit_socket_loop
201+ return self .exit_requested
170202
171203 def _cmd_run (self ):
172204 """runs the received snippet of code"""
@@ -185,8 +217,10 @@ def _cmd_exit(self):
185217
186218 def _cmd_ping (self ):
187219 """ping"""
220+ _debug_write ('Ping received' )
188221 message = read_string (self .conn )
189222 with self .send_lock :
223+ _debug_write ('Pong response being sent out' )
190224 write_bytes (self .conn , iPythonSocketServer ._PONG )
191225 write_string (self .conn , "pong received with message" + message )
192226
@@ -195,7 +229,7 @@ def _cmd_inpl(self):
195229 self .input_string = read_string (self .conn )
196230 self .input_event .release ()
197231
198- def send_prompt (self , ps1 , ps2 , update_all = True ):
232+ def send_prompt (self , ps1 , ps2 , update_all = True ):
199233 """sends the current prompt to the interactive window"""
200234 # with self.send_lock:
201235 # write_bytes(self.conn, iPythonSocketServer._PRPC)
@@ -257,7 +291,8 @@ def interrupt_main(self):
257291
258292 def exit_process (self ):
259293 """exits the REPL process"""
260- pass
294+ # TODO: Probably should cleanly shutdown the kernels
295+ sys .exit (0 )
261296
262297 def flush (self ):
263298 """flushes the stdout/stderr buffers"""
@@ -271,10 +306,13 @@ def flush(self):
271306 to_bytes ('inpl' ): _cmd_inpl ,
272307 }
273308
309+
274310def exit_work_item ():
275311 sys .exit (0 )
276312
313+
277314class iPythonReadLine (object ):
315+
278316 def __init__ (self ):
279317 self ._input = io .open (sys .stdin .fileno (), encoding = 'utf-8' )
280318
@@ -317,8 +355,10 @@ def _write_response(self, response):
317355 sys .stdout .flush ()
318356
319357 def watch (self ):
358+ port = int (sys .argv [1 ])
359+ _debug_write ('Socket port received: ' + str (port ))
320360 server = iPythonSocketServer ()
321- server .connect (3000 )
361+ server .connect (port )
322362 while True :
323363 try :
324364 self ._process_request (self ._input .readline ())
0 commit comments