blob: 39e0c116f9bc41d513020d14b4338b6415abffcd [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()
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300187 fix_scaling(root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000188 root.withdraw()
terryjreedy188aedf2017-06-13 21:32:16 -0400189 msg = f"IDLE's subprocess can't connect to {address[0]}:{address[1]}.\n"\
190 f"Fatal OSError #{err.errno}: {err.strerror}.\n"\
191 f"See the 'Startup failure' section of the IDLE doc, online at\n"\
192 f"https://docs.python.org/3/library/idle.html#startup-failure"
193 showerror("IDLE Subprocess Error", msg, parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000194 root.destroy()
195
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000196def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000197 import linecache
198 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000199 flush_stdout()
200 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000201 typ, val, tb = excinfo = sys.exc_info()
202 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200203 seen = set()
204
205 def print_exc(typ, exc, tb):
206 seen.add(exc)
207 context = exc.__context__
208 cause = exc.__cause__
209 if cause is not None and cause not in seen:
210 print_exc(type(cause), cause, cause.__traceback__)
211 print("\nThe above exception was the direct cause "
212 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200213 elif (context is not None and
214 not exc.__suppress_context__ and
215 context not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200216 print_exc(type(context), context, context.__traceback__)
217 print("\nDuring handling of the above exception, "
218 "another exception occurred:\n", file=efile)
219 if tb:
220 tbe = traceback.extract_tb(tb)
221 print('Traceback (most recent call last):', file=efile)
222 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400223 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200224 cleanup_traceback(tbe, exclude)
225 traceback.print_list(tbe, file=efile)
226 lines = traceback.format_exception_only(typ, exc)
227 for line in lines:
228 print(line, end='', file=efile)
229
230 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000231
232def cleanup_traceback(tb, exclude):
233 "Remove excluded traces from beginning/end of tb; get cached lines"
234 orig_tb = tb[:]
235 while tb:
236 for rpcfile in exclude:
237 if tb[0][0].count(rpcfile):
238 break # found an exclude, break for: and delete tb[0]
239 else:
240 break # no excludes, have left RPC code, break while:
241 del tb[0]
242 while tb:
243 for rpcfile in exclude:
244 if tb[-1][0].count(rpcfile):
245 break
246 else:
247 break
248 del tb[-1]
249 if len(tb) == 0:
250 # exception was in IDLE internals, don't prune!
251 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000252 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000253 rpchandler = rpc.objecttable['exec'].rpchandler
254 for i in range(len(tb)):
255 fn, ln, nm, line = tb[i]
256 if nm == '?':
257 nm = "-toplevel-"
258 if not line and fn.startswith("<pyshell#"):
259 line = rpchandler.remotecall('linecache', 'getline',
260 (fn, ln), {})
261 tb[i] = fn, ln, nm, line
262
263def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000264 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000265
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000266def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000267 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000268
269 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000270 functions registered with atexit will be removed before exiting.
271 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000272
273 """
274 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000275 import atexit
276 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400277 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000278 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000279
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -0400280
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300281def fix_scaling(root):
282 """Scale fonts on HiDPI displays."""
283 import tkinter.font
284 scaling = float(root.tk.call('tk', 'scaling'))
285 if scaling > 1.4:
286 for name in tkinter.font.names(root):
287 font = tkinter.font.Font(root=root, name=name, exists=True)
288 size = int(font['size'])
289 if size < 0:
290 font['size'] = round(-0.75*size)
291
292
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000293class MyRPCServer(rpc.RPCServer):
294
295 def handle_error(self, request, client_address):
296 """Override RPCServer method for IDLE
297
298 Interrupt the MainThread and exit server if link is dropped.
299
300 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000301 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000302 try:
303 raise
304 except SystemExit:
305 raise
306 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000307 global exit_now
308 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000309 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000310 except:
311 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000312 print('\n' + '-'*40, file=erf)
313 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000314 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000315 print('Client Address: ', client_address, file=erf)
316 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000317 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000318 print('\n*** Unrecoverable, server exiting!', file=erf)
319 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000320 quitting = True
321 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000322
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400323
324# Pseudofiles for shell-remote communication (also used in pyshell)
325
326class PseudoFile(io.TextIOBase):
327
328 def __init__(self, shell, tags, encoding=None):
329 self.shell = shell
330 self.tags = tags
331 self._encoding = encoding
332
333 @property
334 def encoding(self):
335 return self._encoding
336
337 @property
338 def name(self):
339 return '<%s>' % self.tags
340
341 def isatty(self):
342 return True
343
344
345class PseudoOutputFile(PseudoFile):
346
347 def writable(self):
348 return True
349
350 def write(self, s):
351 if self.closed:
352 raise ValueError("write to closed file")
353 if type(s) is not str:
354 if not isinstance(s, str):
355 raise TypeError('must be str, not ' + type(s).__name__)
356 # See issue #19481
357 s = str.__str__(s)
358 return self.shell.write(s, self.tags)
359
360
361class PseudoInputFile(PseudoFile):
362
363 def __init__(self, shell, tags, encoding=None):
364 PseudoFile.__init__(self, shell, tags, encoding)
365 self._line_buffer = ''
366
367 def readable(self):
368 return True
369
370 def read(self, size=-1):
371 if self.closed:
372 raise ValueError("read from closed file")
373 if size is None:
374 size = -1
375 elif not isinstance(size, int):
376 raise TypeError('must be int, not ' + type(size).__name__)
377 result = self._line_buffer
378 self._line_buffer = ''
379 if size < 0:
380 while True:
381 line = self.shell.readline()
382 if not line: break
383 result += line
384 else:
385 while len(result) < size:
386 line = self.shell.readline()
387 if not line: break
388 result += line
389 self._line_buffer = result[size:]
390 result = result[:size]
391 return result
392
393 def readline(self, size=-1):
394 if self.closed:
395 raise ValueError("read from closed file")
396 if size is None:
397 size = -1
398 elif not isinstance(size, int):
399 raise TypeError('must be int, not ' + type(size).__name__)
400 line = self._line_buffer or self.shell.readline()
401 if size < 0:
402 size = len(line)
403 eol = line.find('\n', 0, size)
404 if eol >= 0:
405 size = eol + 1
406 self._line_buffer = line[size:]
407 return line[:size]
408
409 def close(self):
410 self.shell.close()
411
412
Chui Tey5d2af632002-05-26 13:36:41 +0000413class MyHandler(rpc.RPCHandler):
414
415 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000416 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000417 executive = Executive(self)
418 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200419 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400420 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400421 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400422 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400423 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400424 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400425 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200426
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300427 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000428 # page help() text to shell.
429 import pydoc # import must be done here to capture i/o binding
430 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500431
432 # Keep a reference to stdin so that it won't try to exit IDLE if
433 # sys.stdin gets changed from within IDLE's shell. See issue17838.
434 self._keep_stdin = sys.stdin
435
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000436 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000437 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
438
439 def exithook(self):
440 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000441 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000442
443 def EOFhook(self):
444 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000445 global quitting
446 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000447 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000448
449 def decode_interrupthook(self):
450 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000451 global quitting
452 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000453 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000454
Chui Tey5d2af632002-05-26 13:36:41 +0000455
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000456class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000457
458 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000459 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000460 self.locals = __main__.__dict__
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400461 self.calltip = calltips.CallTips()
462 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000463
464 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000465 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000466 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000467 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000468 interruptable = True
469 try:
470 exec(code, self.locals)
471 finally:
472 interruptable = False
Roger Serwyf4675212013-06-11 22:25:14 -0500473 except SystemExit:
474 # Scripts that raise SystemExit should just
475 # return to the interactive prompt
476 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000477 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000478 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000479 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000480 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000481 # even print a user code SystemExit exception, continue
482 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000483 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
484 if jit:
485 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000486 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000487 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000488
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000489 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000490 if interruptable:
491 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000492
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000493 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400494 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000495
496 def stop_the_debugger(self, idb_adap_oid):
497 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
498 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000499
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000500 def get_the_calltip(self, name):
501 return self.calltip.fetch_tip(name)
502
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000503 def get_the_completion_list(self, what, mode):
504 return self.autocomplete.fetch_completions(what, mode)
505
Chui Tey5d2af632002-05-26 13:36:41 +0000506 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000507 if self.usr_exc_info:
508 typ, val, tb = self.usr_exc_info
509 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000510 return None
511 flist = None
512 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000513 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000514 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
515 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000516 sys.last_type = typ
517 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400518 item = stackviewer.StackTreeItem(flist, tb)
519 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400520
521capture_warnings(False) # Make sure turned off; see issue 18081