blob: 9cc009fb7b848a430e6f9e007fe0b3095bdc74b8 [file] [log] [blame]
Chui Tey5d2af632002-05-26 13:36:41 +00001import sys
Martin v. Löwise8e4e142012-07-09 21:01:49 +02002import io
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +00003import linecache
Kurt B. Kaiserb4179362002-07-26 00:06:42 +00004import time
5import socket
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +00006import traceback
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +00007import thread
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +00008import threading
Georg Brandla6168f92008-05-25 07:20:14 +00009import Queue
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000010
Florent Xiclunad630c042010-04-02 07:24:52 +000011from idlelib import CallTips
12from idlelib import AutoComplete
Kurt B. Kaiserb1754452005-11-18 22:05:48 +000013
Florent Xiclunad630c042010-04-02 07:24:52 +000014from idlelib import RemoteDebugger
15from idlelib import RemoteObjectBrowser
16from idlelib import StackViewer
17from idlelib import rpc
Serhiy Storchaka9abc8302013-01-25 15:30:35 +020018from idlelib import PyShell
19from idlelib import IOBinding
Chui Tey5d2af632002-05-26 13:36:41 +000020
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000021import __main__
22
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000023LOCALHOST = '127.0.0.1'
24
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000025try:
26 import warnings
27except ImportError:
28 pass
29else:
Benjamin Peterson9dc0a632008-10-15 21:05:55 +000030 def idle_formatwarning_subproc(message, category, filename, lineno,
Guilherme Polof198ac22009-08-14 14:03:07 +000031 line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000032 """Format warnings the IDLE way"""
33 s = "\nWarning (from warnings module):\n"
34 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000035 if line is None:
36 line = linecache.getline(filename, lineno)
37 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000038 if line:
39 s += " %s\n" % line
40 s += "%s: %s\n" % (category.__name__, message)
41 return s
42 warnings.formatwarning = idle_formatwarning_subproc
43
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000044# Thread shared globals: Establish a queue between a subthread (which handles
45# the socket) and the main thread (which runs user code), plus global
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +000046# completion, exit and interruptable (the main thread) flags:
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000047
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000048exit_now = False
49quitting = False
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +000050interruptable = False
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000051
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000052def main(del_exitfunc=False):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000053 """Start the Python execution server in a subprocess
54
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000055 In the Python subprocess, RPCServer is instantiated with handlerclass
56 MyHandler, which inherits register/unregister methods from RPCHandler via
57 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000058
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000059 When the RPCServer 'server' is instantiated, the TCPServer initialization
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000060 creates an instance of run.MyHandler and calls its handle() method.
61 handle() instantiates a run.Executive object, passing it a reference to the
62 MyHandler object. That reference is saved as attribute rpchandler of the
63 Executive instance. The Executive methods have access to the reference and
64 can pass it on to entities that they command
65 (e.g. RemoteDebugger.Debugger.start_debugger()). The latter, in turn, can
66 call MyHandler(SocketIO) register/unregister methods via the reference to
67 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000068
69 """
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000070 global exit_now
71 global quitting
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000072 global no_exitfunc
73 no_exitfunc = del_exitfunc
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +000074 #time.sleep(15) # test subprocess not responding
Kurt B. Kaiser4724f402009-04-02 02:44:54 +000075 try:
76 assert(len(sys.argv) > 1)
77 port = int(sys.argv[-1])
78 except:
79 print>>sys.stderr, "IDLE Subprocess: no IP port passed in sys.argv."
80 return
Chui Tey5d2af632002-05-26 13:36:41 +000081 sys.argv[:] = [""]
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000082 sockthread = threading.Thread(target=manage_socket,
83 name='SockThread',
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000084 args=((LOCALHOST, port),))
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000085 sockthread.setDaemon(True)
86 sockthread.start()
87 while 1:
88 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000089 if exit_now:
90 try:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000091 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000092 except KeyboardInterrupt:
93 # exiting but got an extra KBI? Try again!
94 continue
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000095 try:
Kurt B. Kaiser20345fb2005-05-05 23:29:54 +000096 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
Georg Brandla6168f92008-05-25 07:20:14 +000097 except Queue.Empty:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000098 continue
99 method, args, kwargs = request
100 ret = method(*args, **kwargs)
101 rpc.response_queue.put((seq, ret))
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000102 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000103 if quitting:
104 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000105 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000106 except SystemExit:
107 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000108 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000109 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000110 try:
111 print_exception()
112 rpc.response_queue.put((seq, None))
113 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000114 # Link didn't work, print same exception to __stderr__
115 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000116 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000117 else:
118 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000119
120def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000121 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000122 time.sleep(i)
123 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000124 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000125 break
126 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000127 print>>sys.__stderr__,"IDLE Subprocess: socket error: "\
Florent Xiclunad630c042010-04-02 07:24:52 +0000128 + err.args[1] + ", retrying...."
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000129 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000130 print>>sys.__stderr__, "IDLE Subprocess: Connection to "\
131 "IDLE GUI failed, exiting."
132 show_socket_error(err, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000133 global exit_now
134 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000135 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000136 server.handle_request() # A single request only
137
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000138def show_socket_error(err, address):
Georg Brandl6634bf22008-05-20 07:13:37 +0000139 import Tkinter
140 import tkMessageBox
141 root = Tkinter.Tk()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000142 root.withdraw()
Florent Xiclunad630c042010-04-02 07:24:52 +0000143 if err.args[0] == 61: # connection refused
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000144 msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\
145 "to your personal firewall configuration. It is safe to "\
146 "allow this internal connection because no data is visible on "\
147 "external ports." % address
148 tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
149 else:
Florent Xiclunad630c042010-04-02 07:24:52 +0000150 tkMessageBox.showerror("IDLE Subprocess Error",
151 "Socket Error: %s" % err.args[1])
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000152 root.destroy()
153
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000154def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000155 import linecache
156 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000157 flush_stdout()
158 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000159 typ, val, tb = excinfo = sys.exc_info()
160 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000161 tbe = traceback.extract_tb(tb)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000162 print>>efile, '\nTraceback (most recent call last):'
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000163 exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
164 "RemoteDebugger.py", "bdb.py")
165 cleanup_traceback(tbe, exclude)
166 traceback.print_list(tbe, file=efile)
167 lines = traceback.format_exception_only(typ, val)
168 for line in lines:
169 print>>efile, line,
170
171def cleanup_traceback(tb, exclude):
172 "Remove excluded traces from beginning/end of tb; get cached lines"
173 orig_tb = tb[:]
174 while tb:
175 for rpcfile in exclude:
176 if tb[0][0].count(rpcfile):
177 break # found an exclude, break for: and delete tb[0]
178 else:
179 break # no excludes, have left RPC code, break while:
180 del tb[0]
181 while tb:
182 for rpcfile in exclude:
183 if tb[-1][0].count(rpcfile):
184 break
185 else:
186 break
187 del tb[-1]
188 if len(tb) == 0:
189 # exception was in IDLE internals, don't prune!
190 tb[:] = orig_tb[:]
191 print>>sys.stderr, "** IDLE Internal Exception: "
192 rpchandler = rpc.objecttable['exec'].rpchandler
193 for i in range(len(tb)):
194 fn, ln, nm, line = tb[i]
195 if nm == '?':
196 nm = "-toplevel-"
197 if not line and fn.startswith("<pyshell#"):
198 line = rpchandler.remotecall('linecache', 'getline',
199 (fn, ln), {})
200 tb[i] = fn, ln, nm, line
201
202def flush_stdout():
203 try:
204 if sys.stdout.softspace:
205 sys.stdout.softspace = 0
206 sys.stdout.write("\n")
207 except (AttributeError, EOFError):
208 pass
209
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000210def exit():
211 """Exit subprocess, possibly after first deleting sys.exitfunc
212
213 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
214 sys.exitfunc will be removed before exiting. (VPython support)
215
216 """
217 if no_exitfunc:
Kurt B. Kaiserf30ba3d2008-01-23 22:55:26 +0000218 try:
219 del sys.exitfunc
220 except AttributeError:
221 pass
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000222 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000223
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000224class MyRPCServer(rpc.RPCServer):
225
226 def handle_error(self, request, client_address):
227 """Override RPCServer method for IDLE
228
229 Interrupt the MainThread and exit server if link is dropped.
230
231 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000232 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000233 try:
234 raise
235 except SystemExit:
236 raise
237 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000238 global exit_now
239 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000240 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000241 except:
242 erf = sys.__stderr__
243 print>>erf, '\n' + '-'*40
244 print>>erf, 'Unhandled server exception!'
245 print>>erf, 'Thread: %s' % threading.currentThread().getName()
246 print>>erf, 'Client Address: ', client_address
247 print>>erf, 'Request: ', repr(request)
248 traceback.print_exc(file=erf)
249 print>>erf, '\n*** Unrecoverable, server exiting!'
250 print>>erf, '-'*40
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000251 quitting = True
252 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000253
Chui Tey5d2af632002-05-26 13:36:41 +0000254class MyHandler(rpc.RPCHandler):
255
256 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000257 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000258 executive = Executive(self)
259 self.register("exec", executive)
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200260 self.console = self.get_remote_proxy("console")
261 sys.stdin = PyShell.PseudoInputFile(self.console, "stdin",
262 IOBinding.encoding)
263 sys.stdout = PyShell.PseudoOutputFile(self.console, "stdout",
264 IOBinding.encoding)
265 sys.stderr = PyShell.PseudoOutputFile(self.console, "stderr",
266 IOBinding.encoding)
Benjamin Peterson5a271682013-05-11 22:24:28 -0500267
268 # Keep a reference to stdin so that it won't try to exit IDLE if
269 # sys.stdin gets changed from within IDLE's shell. See issue17838.
270 self._keep_stdin = sys.stdin
271
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000272 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000273 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
274
275 def exithook(self):
276 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000277 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000278
279 def EOFhook(self):
280 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000281 global quitting
282 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000283 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000284
285 def decode_interrupthook(self):
286 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000287 global quitting
288 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000289 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000290
Chui Tey5d2af632002-05-26 13:36:41 +0000291
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000292class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000293
294 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000295 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000296 self.locals = __main__.__dict__
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000297 self.calltip = CallTips.CallTips()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000298 self.autocomplete = AutoComplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000299
300 def runcode(self, code):
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000301 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000302 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000303 self.usr_exc_info = None
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000304 interruptable = True
305 try:
306 exec code in self.locals
307 finally:
308 interruptable = False
Raymond Hettinger42349922013-02-09 14:20:55 -0500309 except SystemExit:
310 # Scripts that raise SystemExit should just
311 # return to the interactive prompt
312 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000313 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000314 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000315 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000316 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000317 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000318 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
319 if jit:
320 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000321 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000322 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000323
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000324 def interrupt_the_server(self):
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000325 if interruptable:
326 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000327
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000328 def start_the_debugger(self, gui_adap_oid):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000329 return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
330
331 def stop_the_debugger(self, idb_adap_oid):
332 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
333 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000334
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000335 def get_the_calltip(self, name):
336 return self.calltip.fetch_tip(name)
337
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000338 def get_the_completion_list(self, what, mode):
339 return self.autocomplete.fetch_completions(what, mode)
340
Chui Tey5d2af632002-05-26 13:36:41 +0000341 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000342 if self.usr_exc_info:
343 typ, val, tb = self.usr_exc_info
344 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000345 return None
346 flist = None
347 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000348 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000349 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
350 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000351 sys.last_type = typ
352 sys.last_value = val
Chui Tey5d2af632002-05-26 13:36:41 +0000353 item = StackViewer.StackTreeItem(flist, tb)
354 return RemoteObjectBrowser.remote_object_tree_item(item)