blob: c7ee0b3e458bbae7c1db9134f5b7a687a1a685f3 [file] [log] [blame]
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04001import io
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +00002import linecache
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04003import queue
4import sys
Georg Brandl2067bfd2008-05-25 13:05:15 +00005import _thread as thread
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +00006import threading
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04007import time
8import traceback
Andrew Svetlov753445a2012-03-26 21:56:44 +03009import tkinter
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000010
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -040011from idlelib import calltips
12from idlelib import autocomplete
Kurt B. Kaiserb1754452005-11-18 22:05:48 +000013
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -040014from idlelib import debugger_r
15from idlelib import debugobj_r
16from idlelib import stackviewer
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000017from idlelib import rpc
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -040018from idlelib import iomenu
Chui Tey5d2af632002-05-26 13:36:41 +000019
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000020import __main__
21
Terry Jan Reedyff1d5ab2016-07-16 18:26:32 -040022for mod in ('simpledialog', 'messagebox', 'font',
23 'dialog', 'filedialog', 'commondialog',
Terry Jan Reedy41bc0672016-07-16 18:27:11 -040024 'ttk'):
Terry Jan Reedyff1d5ab2016-07-16 18:26:32 -040025 delattr(tkinter, mod)
26 del sys.modules['tkinter.' + mod]
27
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000028LOCALHOST = '127.0.0.1'
29
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040030import warnings
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000031
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040032def idle_formatwarning(message, category, filename, lineno, line=None):
33 """Format warnings the IDLE way."""
34
35 s = "\nWarning (from warnings module):\n"
36 s += ' File \"%s\", line %s\n' % (filename, lineno)
37 if line is None:
38 line = linecache.getline(filename, lineno)
39 line = line.strip()
40 if line:
41 s += " %s\n" % line
42 s += "%s: %s\n" % (category.__name__, message)
43 return s
44
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040045def idle_showwarning_subproc(
46 message, category, filename, lineno, file=None, line=None):
47 """Show Idle-format warning after replacing warnings.showwarning.
Andrew Svetlova2251aa2012-03-13 18:36:13 -070048
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040049 The only difference is the formatter called.
50 """
51 if file is None:
52 file = sys.stderr
53 try:
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040054 file.write(idle_formatwarning(
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040055 message, category, filename, lineno, line))
56 except IOError:
57 pass # the file (probably stderr) is invalid - this warning gets lost.
58
59_warnings_showwarning = None
60
61def capture_warnings(capture):
62 "Replace warning.showwarning with idle_showwarning_subproc, or reverse."
63
64 global _warnings_showwarning
65 if capture:
66 if _warnings_showwarning is None:
67 _warnings_showwarning = warnings.showwarning
68 warnings.showwarning = idle_showwarning_subproc
69 else:
70 if _warnings_showwarning is not None:
71 warnings.showwarning = _warnings_showwarning
72 _warnings_showwarning = None
73
74capture_warnings(True)
Andrew Svetlov753445a2012-03-26 21:56:44 +030075tcl = tkinter.Tcl()
76
Andrew Svetlov753445a2012-03-26 21:56:44 +030077def handle_tk_events(tcl=tcl):
Andrew Svetlova2251aa2012-03-13 18:36:13 -070078 """Process any tk events that are ready to be dispatched if tkinter
79 has been imported, a tcl interpreter has been created and tk has been
80 loaded."""
Andrew Svetlov753445a2012-03-26 21:56:44 +030081 tcl.eval("update")
Andrew Svetlova2251aa2012-03-13 18:36:13 -070082
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000083# Thread shared globals: Establish a queue between a subthread (which handles
84# the socket) and the main thread (which runs user code), plus global
Guido van Rossum8ce8a782007-11-01 19:42:39 +000085# completion, exit and interruptable (the main thread) flags:
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000086
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000087exit_now = False
88quitting = False
Guido van Rossum8ce8a782007-11-01 19:42:39 +000089interruptable = False
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000090
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000091def main(del_exitfunc=False):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000092 """Start the Python execution server in a subprocess
93
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000094 In the Python subprocess, RPCServer is instantiated with handlerclass
95 MyHandler, which inherits register/unregister methods from RPCHandler via
96 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000097
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000098 When the RPCServer 'server' is instantiated, the TCPServer initialization
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000099 creates an instance of run.MyHandler and calls its handle() method.
100 handle() instantiates a run.Executive object, passing it a reference to the
101 MyHandler object. That reference is saved as attribute rpchandler of the
102 Executive instance. The Executive methods have access to the reference and
103 can pass it on to entities that they command
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400104 (e.g. debugger_r.Debugger.start_debugger()). The latter, in turn, can
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000105 call MyHandler(SocketIO) register/unregister methods via the reference to
106 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000107
108 """
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000109 global exit_now
110 global quitting
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000111 global no_exitfunc
112 no_exitfunc = del_exitfunc
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000113 #time.sleep(15) # test subprocess not responding
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000114 try:
115 assert(len(sys.argv) > 1)
116 port = int(sys.argv[-1])
117 except:
Kurt B. Kaiser8fc98c32009-04-04 20:20:29 +0000118 print("IDLE Subprocess: no IP port passed in sys.argv.",
119 file=sys.__stderr__)
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000120 return
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400121
122 capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000123 sys.argv[:] = [""]
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000124 sockthread = threading.Thread(target=manage_socket,
125 name='SockThread',
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000126 args=((LOCALHOST, port),))
Benjamin Peterson71088cc2008-09-19 21:49:37 +0000127 sockthread.daemon = True
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000128 sockthread.start()
129 while 1:
130 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000131 if exit_now:
132 try:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000133 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000134 except KeyboardInterrupt:
135 # exiting but got an extra KBI? Try again!
136 continue
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000137 try:
Kurt B. Kaiser20345fb2005-05-05 23:29:54 +0000138 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
Alexandre Vassalottif260e442008-05-11 19:59:59 +0000139 except queue.Empty:
Andrew Svetlova2251aa2012-03-13 18:36:13 -0700140 handle_tk_events()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000141 continue
142 method, args, kwargs = request
143 ret = method(*args, **kwargs)
144 rpc.response_queue.put((seq, ret))
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000145 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000146 if quitting:
147 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000148 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000149 except SystemExit:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400150 capture_warnings(False)
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000151 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000152 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000153 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000154 try:
155 print_exception()
156 rpc.response_queue.put((seq, None))
157 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000158 # Link didn't work, print same exception to __stderr__
159 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000160 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000161 else:
162 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000163
164def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000165 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000166 time.sleep(i)
167 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000168 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000169 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200170 except OSError as err:
171 print("IDLE Subprocess: OSError: " + err.args[1] +
Georg Brandl6464d472007-10-22 16:16:13 +0000172 ", retrying....", file=sys.__stderr__)
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000173 socket_error = err
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000174 else:
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000175 print("IDLE Subprocess: Connection to "
176 "IDLE GUI failed, exiting.", file=sys.__stderr__)
177 show_socket_error(socket_error, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000178 global exit_now
179 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000180 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000181 server.handle_request() # A single request only
182
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000183def show_socket_error(err, address):
Georg Brandl14fc4272008-05-17 18:39:55 +0000184 import tkinter
185 import tkinter.messagebox as tkMessageBox
186 root = tkinter.Tk()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000187 root.withdraw()
Georg Brandl6464d472007-10-22 16:16:13 +0000188 if err.args[0] == 61: # connection refused
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000189 msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\
190 "to your personal firewall configuration. It is safe to "\
191 "allow this internal connection because no data is visible on "\
192 "external ports." % address
193 tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
194 else:
Georg Brandl6464d472007-10-22 16:16:13 +0000195 tkMessageBox.showerror("IDLE Subprocess Error",
Terry Jan Reedy3be2e542015-09-25 22:22:55 -0400196 "Socket Error: %s" % err.args[1], parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000197 root.destroy()
198
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000199def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000200 import linecache
201 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000202 flush_stdout()
203 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000204 typ, val, tb = excinfo = sys.exc_info()
205 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200206 seen = set()
207
208 def print_exc(typ, exc, tb):
209 seen.add(exc)
210 context = exc.__context__
211 cause = exc.__cause__
212 if cause is not None and cause not in seen:
213 print_exc(type(cause), cause, cause.__traceback__)
214 print("\nThe above exception was the direct cause "
215 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200216 elif (context is not None and
217 not exc.__suppress_context__ and
218 context not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200219 print_exc(type(context), context, context.__traceback__)
220 print("\nDuring handling of the above exception, "
221 "another exception occurred:\n", file=efile)
222 if tb:
223 tbe = traceback.extract_tb(tb)
224 print('Traceback (most recent call last):', file=efile)
225 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400226 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200227 cleanup_traceback(tbe, exclude)
228 traceback.print_list(tbe, file=efile)
229 lines = traceback.format_exception_only(typ, exc)
230 for line in lines:
231 print(line, end='', file=efile)
232
233 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000234
235def cleanup_traceback(tb, exclude):
236 "Remove excluded traces from beginning/end of tb; get cached lines"
237 orig_tb = tb[:]
238 while tb:
239 for rpcfile in exclude:
240 if tb[0][0].count(rpcfile):
241 break # found an exclude, break for: and delete tb[0]
242 else:
243 break # no excludes, have left RPC code, break while:
244 del tb[0]
245 while tb:
246 for rpcfile in exclude:
247 if tb[-1][0].count(rpcfile):
248 break
249 else:
250 break
251 del tb[-1]
252 if len(tb) == 0:
253 # exception was in IDLE internals, don't prune!
254 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000255 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000256 rpchandler = rpc.objecttable['exec'].rpchandler
257 for i in range(len(tb)):
258 fn, ln, nm, line = tb[i]
259 if nm == '?':
260 nm = "-toplevel-"
261 if not line and fn.startswith("<pyshell#"):
262 line = rpchandler.remotecall('linecache', 'getline',
263 (fn, ln), {})
264 tb[i] = fn, ln, nm, line
265
266def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000267 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000268
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000269def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000270 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000271
272 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000273 functions registered with atexit will be removed before exiting.
274 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000275
276 """
277 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000278 import atexit
279 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400280 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000281 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000282
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000283class MyRPCServer(rpc.RPCServer):
284
285 def handle_error(self, request, client_address):
286 """Override RPCServer method for IDLE
287
288 Interrupt the MainThread and exit server if link is dropped.
289
290 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000291 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000292 try:
293 raise
294 except SystemExit:
295 raise
296 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000297 global exit_now
298 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000299 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000300 except:
301 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000302 print('\n' + '-'*40, file=erf)
303 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000304 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000305 print('Client Address: ', client_address, file=erf)
306 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000307 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000308 print('\n*** Unrecoverable, server exiting!', file=erf)
309 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000310 quitting = True
311 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000312
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400313
314# Pseudofiles for shell-remote communication (also used in pyshell)
315
316class PseudoFile(io.TextIOBase):
317
318 def __init__(self, shell, tags, encoding=None):
319 self.shell = shell
320 self.tags = tags
321 self._encoding = encoding
322
323 @property
324 def encoding(self):
325 return self._encoding
326
327 @property
328 def name(self):
329 return '<%s>' % self.tags
330
331 def isatty(self):
332 return True
333
334
335class PseudoOutputFile(PseudoFile):
336
337 def writable(self):
338 return True
339
340 def write(self, s):
341 if self.closed:
342 raise ValueError("write to closed file")
343 if type(s) is not str:
344 if not isinstance(s, str):
345 raise TypeError('must be str, not ' + type(s).__name__)
346 # See issue #19481
347 s = str.__str__(s)
348 return self.shell.write(s, self.tags)
349
350
351class PseudoInputFile(PseudoFile):
352
353 def __init__(self, shell, tags, encoding=None):
354 PseudoFile.__init__(self, shell, tags, encoding)
355 self._line_buffer = ''
356
357 def readable(self):
358 return True
359
360 def read(self, size=-1):
361 if self.closed:
362 raise ValueError("read from closed file")
363 if size is None:
364 size = -1
365 elif not isinstance(size, int):
366 raise TypeError('must be int, not ' + type(size).__name__)
367 result = self._line_buffer
368 self._line_buffer = ''
369 if size < 0:
370 while True:
371 line = self.shell.readline()
372 if not line: break
373 result += line
374 else:
375 while len(result) < size:
376 line = self.shell.readline()
377 if not line: break
378 result += line
379 self._line_buffer = result[size:]
380 result = result[:size]
381 return result
382
383 def readline(self, size=-1):
384 if self.closed:
385 raise ValueError("read from closed file")
386 if size is None:
387 size = -1
388 elif not isinstance(size, int):
389 raise TypeError('must be int, not ' + type(size).__name__)
390 line = self._line_buffer or self.shell.readline()
391 if size < 0:
392 size = len(line)
393 eol = line.find('\n', 0, size)
394 if eol >= 0:
395 size = eol + 1
396 self._line_buffer = line[size:]
397 return line[:size]
398
399 def close(self):
400 self.shell.close()
401
402
Chui Tey5d2af632002-05-26 13:36:41 +0000403class MyHandler(rpc.RPCHandler):
404
405 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000406 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000407 executive = Executive(self)
408 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200409 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400410 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400411 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400412 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400413 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400414 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400415 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200416
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300417 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000418 # page help() text to shell.
419 import pydoc # import must be done here to capture i/o binding
420 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500421
422 # Keep a reference to stdin so that it won't try to exit IDLE if
423 # sys.stdin gets changed from within IDLE's shell. See issue17838.
424 self._keep_stdin = sys.stdin
425
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000426 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000427 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
428
429 def exithook(self):
430 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000431 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000432
433 def EOFhook(self):
434 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000435 global quitting
436 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000437 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000438
439 def decode_interrupthook(self):
440 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000441 global quitting
442 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000443 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000444
Chui Tey5d2af632002-05-26 13:36:41 +0000445
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000446class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000447
448 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000449 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000450 self.locals = __main__.__dict__
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400451 self.calltip = calltips.CallTips()
452 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000453
454 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000455 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000456 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000457 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000458 interruptable = True
459 try:
460 exec(code, self.locals)
461 finally:
462 interruptable = False
Roger Serwyf4675212013-06-11 22:25:14 -0500463 except SystemExit:
464 # Scripts that raise SystemExit should just
465 # return to the interactive prompt
466 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000467 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000468 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000469 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000470 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000471 # even print a user code SystemExit exception, continue
472 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000473 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
474 if jit:
475 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000476 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000477 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000478
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000479 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000480 if interruptable:
481 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000482
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000483 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400484 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000485
486 def stop_the_debugger(self, idb_adap_oid):
487 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
488 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000489
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000490 def get_the_calltip(self, name):
491 return self.calltip.fetch_tip(name)
492
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000493 def get_the_completion_list(self, what, mode):
494 return self.autocomplete.fetch_completions(what, mode)
495
Chui Tey5d2af632002-05-26 13:36:41 +0000496 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000497 if self.usr_exc_info:
498 typ, val, tb = self.usr_exc_info
499 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000500 return None
501 flist = None
502 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000503 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000504 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
505 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000506 sys.last_type = typ
507 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400508 item = stackviewer.StackTreeItem(flist, tb)
509 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400510
511capture_warnings(False) # Make sure turned off; see issue 18081