Skip to content

Commit 6991d99

Browse files
committed
incremental changes
1 parent 096c7a1 commit 6991d99

File tree

16 files changed

+635
-89
lines changed

16 files changed

+635
-89
lines changed
Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import inspect
1515
import types
1616
from collections import deque
17+
import os
18+
import warnings
1719

1820
try:
1921
import thread
@@ -42,17 +44,45 @@
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+
4569
DEBUG = os.environ.get('DEBUG_DJAYAMANNE_IPYTHON') is not None
4670

71+
4772
def _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

5483
class 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+
78109
class iPythonSocketServer(object):
79110
"""back end for executing REPL code. This base class handles all of the
80111
communication with the remote process while derived classes implement the
81112
actual 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+
274310
def exit_work_item():
275311
sys.exit(0)
276312

313+
277314
class 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

Comments
 (0)