blob: 9f6604bb0acc58bdde771f65e635f6afabb69395 [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
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04005import time
6import traceback
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -04007import _thread as thread
8import threading
9import warnings
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000010
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040011import tkinter # Tcl, deletions, messagebox if startup fails
Kurt B. Kaiserb1754452005-11-18 22:05:48 +000012
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040013from idlelib import autocomplete # AutoComplete, fetch_encodings
14from idlelib import calltips # CallTips
15from idlelib import debugger_r # start_debugger
16from idlelib import debugobj_r # remote_object_tree_item
17from idlelib import iomenu # encoding
18from idlelib import rpc # multiple objects
19from idlelib import stackviewer # StackTreeItem
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
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000030
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040031def idle_formatwarning(message, category, filename, lineno, line=None):
32 """Format warnings the IDLE way."""
33
34 s = "\nWarning (from warnings module):\n"
35 s += ' File \"%s\", line %s\n' % (filename, lineno)
36 if line is None:
37 line = linecache.getline(filename, lineno)
38 line = line.strip()
39 if line:
40 s += " %s\n" % line
41 s += "%s: %s\n" % (category.__name__, message)
42 return s
43
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040044def idle_showwarning_subproc(
45 message, category, filename, lineno, file=None, line=None):
46 """Show Idle-format warning after replacing warnings.showwarning.
Andrew Svetlova2251aa2012-03-13 18:36:13 -070047
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040048 The only difference is the formatter called.
49 """
50 if file is None:
51 file = sys.stderr
52 try:
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040053 file.write(idle_formatwarning(
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040054 message, category, filename, lineno, line))
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +030055 except OSError:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040056 pass # the file (probably stderr) is invalid - this warning gets lost.
57
58_warnings_showwarning = None
59
60def capture_warnings(capture):
61 "Replace warning.showwarning with idle_showwarning_subproc, or reverse."
62
63 global _warnings_showwarning
64 if capture:
65 if _warnings_showwarning is None:
66 _warnings_showwarning = warnings.showwarning
67 warnings.showwarning = idle_showwarning_subproc
68 else:
69 if _warnings_showwarning is not None:
70 warnings.showwarning = _warnings_showwarning
71 _warnings_showwarning = None
72
73capture_warnings(True)
Andrew Svetlov753445a2012-03-26 21:56:44 +030074tcl = tkinter.Tcl()
75
Andrew Svetlov753445a2012-03-26 21:56:44 +030076def handle_tk_events(tcl=tcl):
Andrew Svetlova2251aa2012-03-13 18:36:13 -070077 """Process any tk events that are ready to be dispatched if tkinter
78 has been imported, a tcl interpreter has been created and tk has been
79 loaded."""
Andrew Svetlov753445a2012-03-26 21:56:44 +030080 tcl.eval("update")
Andrew Svetlova2251aa2012-03-13 18:36:13 -070081
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000082# Thread shared globals: Establish a queue between a subthread (which handles
83# the socket) and the main thread (which runs user code), plus global
Guido van Rossum8ce8a782007-11-01 19:42:39 +000084# completion, exit and interruptable (the main thread) flags:
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000085
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000086exit_now = False
87quitting = False
Guido van Rossum8ce8a782007-11-01 19:42:39 +000088interruptable = False
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000089
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000090def main(del_exitfunc=False):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000091 """Start the Python execution server in a subprocess
92
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000093 In the Python subprocess, RPCServer is instantiated with handlerclass
94 MyHandler, which inherits register/unregister methods from RPCHandler via
95 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000096
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000097 When the RPCServer 'server' is instantiated, the TCPServer initialization
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000098 creates an instance of run.MyHandler and calls its handle() method.
99 handle() instantiates a run.Executive object, passing it a reference to the
100 MyHandler object. That reference is saved as attribute rpchandler of the
101 Executive instance. The Executive methods have access to the reference and
102 can pass it on to entities that they command
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400103 (e.g. debugger_r.Debugger.start_debugger()). The latter, in turn, can
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000104 call MyHandler(SocketIO) register/unregister methods via the reference to
105 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000106
107 """
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000108 global exit_now
109 global quitting
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000110 global no_exitfunc
111 no_exitfunc = del_exitfunc
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000112 #time.sleep(15) # test subprocess not responding
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000113 try:
114 assert(len(sys.argv) > 1)
115 port = int(sys.argv[-1])
116 except:
Kurt B. Kaiser8fc98c32009-04-04 20:20:29 +0000117 print("IDLE Subprocess: no IP port passed in sys.argv.",
118 file=sys.__stderr__)
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000119 return
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400120
121 capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000122 sys.argv[:] = [""]
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000123 sockthread = threading.Thread(target=manage_socket,
124 name='SockThread',
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000125 args=((LOCALHOST, port),))
Benjamin Peterson71088cc2008-09-19 21:49:37 +0000126 sockthread.daemon = True
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000127 sockthread.start()
128 while 1:
129 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000130 if exit_now:
131 try:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000132 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000133 except KeyboardInterrupt:
134 # exiting but got an extra KBI? Try again!
135 continue
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000136 try:
Kurt B. Kaiser20345fb2005-05-05 23:29:54 +0000137 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
Alexandre Vassalottif260e442008-05-11 19:59:59 +0000138 except queue.Empty:
Andrew Svetlova2251aa2012-03-13 18:36:13 -0700139 handle_tk_events()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000140 continue
141 method, args, kwargs = request
142 ret = method(*args, **kwargs)
143 rpc.response_queue.put((seq, ret))
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000144 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000145 if quitting:
146 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000147 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000148 except SystemExit:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400149 capture_warnings(False)
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000150 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000151 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000152 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000153 try:
154 print_exception()
155 rpc.response_queue.put((seq, None))
156 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000157 # Link didn't work, print same exception to __stderr__
158 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000159 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000160 else:
161 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000162
163def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000164 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000165 time.sleep(i)
166 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000167 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000168 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200169 except OSError as err:
170 print("IDLE Subprocess: OSError: " + err.args[1] +
Georg Brandl6464d472007-10-22 16:16:13 +0000171 ", retrying....", file=sys.__stderr__)
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000172 socket_error = err
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000173 else:
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000174 print("IDLE Subprocess: Connection to "
175 "IDLE GUI failed, exiting.", file=sys.__stderr__)
176 show_socket_error(socket_error, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000177 global exit_now
178 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000179 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000180 server.handle_request() # A single request only
181
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000182def show_socket_error(err, address):
terryjreedy188aedf2017-06-13 21:32:16 -0400183 "Display socket error from manage_socket."
Georg Brandl14fc4272008-05-17 18:39:55 +0000184 import tkinter
terryjreedy188aedf2017-06-13 21:32:16 -0400185 from tkinter.messagebox import showerror
Georg Brandl14fc4272008-05-17 18:39:55 +0000186 root = tkinter.Tk()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000187 root.withdraw()
terryjreedy188aedf2017-06-13 21:32:16 -0400188 msg = f"IDLE's subprocess can't connect to {address[0]}:{address[1]}.\n"\
189 f"Fatal OSError #{err.errno}: {err.strerror}.\n"\
190 f"See the 'Startup failure' section of the IDLE doc, online at\n"\
191 f"https://docs.python.org/3/library/idle.html#startup-failure"
192 showerror("IDLE Subprocess Error", msg, parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000193 root.destroy()
194
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000195def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000196 import linecache
197 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000198 flush_stdout()
199 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000200 typ, val, tb = excinfo = sys.exc_info()
201 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200202 seen = set()
203
204 def print_exc(typ, exc, tb):
205 seen.add(exc)
206 context = exc.__context__
207 cause = exc.__cause__
208 if cause is not None and cause not in seen:
209 print_exc(type(cause), cause, cause.__traceback__)
210 print("\nThe above exception was the direct cause "
211 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200212 elif (context is not None and
213 not exc.__suppress_context__ and
214 context not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200215 print_exc(type(context), context, context.__traceback__)
216 print("\nDuring handling of the above exception, "
217 "another exception occurred:\n", file=efile)
218 if tb:
219 tbe = traceback.extract_tb(tb)
220 print('Traceback (most recent call last):', file=efile)
221 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400222 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200223 cleanup_traceback(tbe, exclude)
224 traceback.print_list(tbe, file=efile)
225 lines = traceback.format_exception_only(typ, exc)
226 for line in lines:
227 print(line, end='', file=efile)
228
229 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000230
231def cleanup_traceback(tb, exclude):
232 "Remove excluded traces from beginning/end of tb; get cached lines"
233 orig_tb = tb[:]
234 while tb:
235 for rpcfile in exclude:
236 if tb[0][0].count(rpcfile):
237 break # found an exclude, break for: and delete tb[0]
238 else:
239 break # no excludes, have left RPC code, break while:
240 del tb[0]
241 while tb:
242 for rpcfile in exclude:
243 if tb[-1][0].count(rpcfile):
244 break
245 else:
246 break
247 del tb[-1]
248 if len(tb) == 0:
249 # exception was in IDLE internals, don't prune!
250 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000251 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000252 rpchandler = rpc.objecttable['exec'].rpchandler
253 for i in range(len(tb)):
254 fn, ln, nm, line = tb[i]
255 if nm == '?':
256 nm = "-toplevel-"
257 if not line and fn.startswith("<pyshell#"):
258 line = rpchandler.remotecall('linecache', 'getline',
259 (fn, ln), {})
260 tb[i] = fn, ln, nm, line
261
262def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000263 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000264
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000265def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000266 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000267
268 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000269 functions registered with atexit will be removed before exiting.
270 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000271
272 """
273 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000274 import atexit
275 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400276 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000277 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000278
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -0400279
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000280class MyRPCServer(rpc.RPCServer):
281
282 def handle_error(self, request, client_address):
283 """Override RPCServer method for IDLE
284
285 Interrupt the MainThread and exit server if link is dropped.
286
287 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000288 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000289 try:
290 raise
291 except SystemExit:
292 raise
293 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000294 global exit_now
295 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000296 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000297 except:
298 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000299 print('\n' + '-'*40, file=erf)
300 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000301 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000302 print('Client Address: ', client_address, file=erf)
303 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000304 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000305 print('\n*** Unrecoverable, server exiting!', file=erf)
306 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000307 quitting = True
308 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000309
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400310
311# Pseudofiles for shell-remote communication (also used in pyshell)
312
313class PseudoFile(io.TextIOBase):
314
315 def __init__(self, shell, tags, encoding=None):
316 self.shell = shell
317 self.tags = tags
318 self._encoding = encoding
319
320 @property
321 def encoding(self):
322 return self._encoding
323
324 @property
325 def name(self):
326 return '<%s>' % self.tags
327
328 def isatty(self):
329 return True
330
331
332class PseudoOutputFile(PseudoFile):
333
334 def writable(self):
335 return True
336
337 def write(self, s):
338 if self.closed:
339 raise ValueError("write to closed file")
340 if type(s) is not str:
341 if not isinstance(s, str):
342 raise TypeError('must be str, not ' + type(s).__name__)
343 # See issue #19481
344 s = str.__str__(s)
345 return self.shell.write(s, self.tags)
346
347
348class PseudoInputFile(PseudoFile):
349
350 def __init__(self, shell, tags, encoding=None):
351 PseudoFile.__init__(self, shell, tags, encoding)
352 self._line_buffer = ''
353
354 def readable(self):
355 return True
356
357 def read(self, size=-1):
358 if self.closed:
359 raise ValueError("read from closed file")
360 if size is None:
361 size = -1
362 elif not isinstance(size, int):
363 raise TypeError('must be int, not ' + type(size).__name__)
364 result = self._line_buffer
365 self._line_buffer = ''
366 if size < 0:
367 while True:
368 line = self.shell.readline()
369 if not line: break
370 result += line
371 else:
372 while len(result) < size:
373 line = self.shell.readline()
374 if not line: break
375 result += line
376 self._line_buffer = result[size:]
377 result = result[:size]
378 return result
379
380 def readline(self, size=-1):
381 if self.closed:
382 raise ValueError("read from closed file")
383 if size is None:
384 size = -1
385 elif not isinstance(size, int):
386 raise TypeError('must be int, not ' + type(size).__name__)
387 line = self._line_buffer or self.shell.readline()
388 if size < 0:
389 size = len(line)
390 eol = line.find('\n', 0, size)
391 if eol >= 0:
392 size = eol + 1
393 self._line_buffer = line[size:]
394 return line[:size]
395
396 def close(self):
397 self.shell.close()
398
399
Chui Tey5d2af632002-05-26 13:36:41 +0000400class MyHandler(rpc.RPCHandler):
401
402 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000403 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000404 executive = Executive(self)
405 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200406 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400407 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400408 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400409 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400410 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400411 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400412 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200413
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300414 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000415 # page help() text to shell.
416 import pydoc # import must be done here to capture i/o binding
417 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500418
419 # Keep a reference to stdin so that it won't try to exit IDLE if
420 # sys.stdin gets changed from within IDLE's shell. See issue17838.
421 self._keep_stdin = sys.stdin
422
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000423 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000424 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
425
426 def exithook(self):
427 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000428 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000429
430 def EOFhook(self):
431 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000432 global quitting
433 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000434 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000435
436 def decode_interrupthook(self):
437 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000438 global quitting
439 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000440 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000441
Chui Tey5d2af632002-05-26 13:36:41 +0000442
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000443class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000444
445 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000446 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000447 self.locals = __main__.__dict__
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400448 self.calltip = calltips.CallTips()
449 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000450
451 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000452 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000453 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000454 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000455 interruptable = True
456 try:
457 exec(code, self.locals)
458 finally:
459 interruptable = False
Roger Serwyf4675212013-06-11 22:25:14 -0500460 except SystemExit:
461 # Scripts that raise SystemExit should just
462 # return to the interactive prompt
463 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000464 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000465 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000466 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000467 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000468 # even print a user code SystemExit exception, continue
469 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000470 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
471 if jit:
472 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000473 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000474 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000475
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000476 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000477 if interruptable:
478 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000479
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000480 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400481 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000482
483 def stop_the_debugger(self, idb_adap_oid):
484 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
485 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000486
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000487 def get_the_calltip(self, name):
488 return self.calltip.fetch_tip(name)
489
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000490 def get_the_completion_list(self, what, mode):
491 return self.autocomplete.fetch_completions(what, mode)
492
Chui Tey5d2af632002-05-26 13:36:41 +0000493 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000494 if self.usr_exc_info:
495 typ, val, tb = self.usr_exc_info
496 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000497 return None
498 flist = None
499 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000500 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000501 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
502 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000503 sys.last_type = typ
504 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400505 item = stackviewer.StackTreeItem(flist, tb)
506 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400507
508capture_warnings(False) # Make sure turned off; see issue 18081