blob: acae3aea7ad1781e707ed4e5bf073584bb8f73a8 [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)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000267 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000268 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
269
270 def exithook(self):
271 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000272 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000273
274 def EOFhook(self):
275 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000276 global quitting
277 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000278 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000279
280 def decode_interrupthook(self):
281 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000282 global quitting
283 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000284 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000285
Chui Tey5d2af632002-05-26 13:36:41 +0000286
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000287class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000288
289 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000290 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000291 self.locals = __main__.__dict__
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000292 self.calltip = CallTips.CallTips()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000293 self.autocomplete = AutoComplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000294
295 def runcode(self, code):
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000296 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000297 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000298 self.usr_exc_info = None
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000299 interruptable = True
300 try:
301 exec code in self.locals
302 finally:
303 interruptable = False
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000304 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000305 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000306 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000307 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000308 # even print a user code SystemExit exception, continue
309 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000310 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
311 if jit:
312 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000313 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000314 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000315
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000316 def interrupt_the_server(self):
Kurt B. Kaiserc8f65e62007-10-09 19:31:30 +0000317 if interruptable:
318 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000319
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000320 def start_the_debugger(self, gui_adap_oid):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000321 return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
322
323 def stop_the_debugger(self, idb_adap_oid):
324 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
325 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000326
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000327 def get_the_calltip(self, name):
328 return self.calltip.fetch_tip(name)
329
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000330 def get_the_completion_list(self, what, mode):
331 return self.autocomplete.fetch_completions(what, mode)
332
Chui Tey5d2af632002-05-26 13:36:41 +0000333 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000334 if self.usr_exc_info:
335 typ, val, tb = self.usr_exc_info
336 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000337 return None
338 flist = None
339 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000340 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000341 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
342 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000343 sys.last_type = typ
344 sys.last_value = val
Chui Tey5d2af632002-05-26 13:36:41 +0000345 item = StackViewer.StackTreeItem(flist, tb)
346 return RemoteObjectBrowser.remote_object_tree_item(item)