blob: 4075deec51d8ed1e4cfdd34f1688db864377a428 [file] [log] [blame]
Terry Jan Reedy81bb97d2019-05-24 21:59:53 -04001""" idlelib.run
2
3Simplified, pyshell.ModifiedInterpreter spawns a subprocess with
4f'''{sys.executable} -c "__import__('idlelib.run').run.main()"'''
5'.run' is needed because __import__ returns idlelib, not idlelib.run.
6"""
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04007import io
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +00008import linecache
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -04009import queue
10import sys
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040011import time
12import traceback
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040013import _thread as thread
14import threading
15import warnings
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000016
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040017from idlelib import autocomplete # AutoComplete, fetch_encodings
Terry Jan Reedy06e20292018-06-19 23:00:35 -040018from idlelib import calltip # Calltip
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040019from idlelib import debugger_r # start_debugger
20from idlelib import debugobj_r # remote_object_tree_item
21from idlelib import iomenu # encoding
22from idlelib import rpc # multiple objects
23from idlelib import stackviewer # StackTreeItem
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000024import __main__
25
Terry Jan Reedy81bb97d2019-05-24 21:59:53 -040026import tkinter # Use tcl and, if startup fails, messagebox.
27if not hasattr(sys.modules['idlelib.run'], 'firstrun'):
28 # Undo modifications of tkinter by idlelib imports; see bpo-25507.
29 for mod in ('simpledialog', 'messagebox', 'font',
30 'dialog', 'filedialog', 'commondialog',
31 'ttk'):
32 delattr(tkinter, mod)
33 del sys.modules['tkinter.' + mod]
34 # Avoid AttributeError if run again; see bpo-37038.
35 sys.modules['idlelib.run'].firstrun = False
Terry Jan Reedyff1d5ab2016-07-16 18:26:32 -040036
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000037LOCALHOST = '127.0.0.1'
38
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000039
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040040def idle_formatwarning(message, category, filename, lineno, line=None):
41 """Format warnings the IDLE way."""
42
43 s = "\nWarning (from warnings module):\n"
44 s += ' File \"%s\", line %s\n' % (filename, lineno)
45 if line is None:
46 line = linecache.getline(filename, lineno)
47 line = line.strip()
48 if line:
49 s += " %s\n" % line
50 s += "%s: %s\n" % (category.__name__, message)
51 return s
52
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040053def idle_showwarning_subproc(
54 message, category, filename, lineno, file=None, line=None):
55 """Show Idle-format warning after replacing warnings.showwarning.
Andrew Svetlova2251aa2012-03-13 18:36:13 -070056
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040057 The only difference is the formatter called.
58 """
59 if file is None:
60 file = sys.stderr
61 try:
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -040062 file.write(idle_formatwarning(
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040063 message, category, filename, lineno, line))
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +030064 except OSError:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -040065 pass # the file (probably stderr) is invalid - this warning gets lost.
66
67_warnings_showwarning = None
68
69def capture_warnings(capture):
70 "Replace warning.showwarning with idle_showwarning_subproc, or reverse."
71
72 global _warnings_showwarning
73 if capture:
74 if _warnings_showwarning is None:
75 _warnings_showwarning = warnings.showwarning
76 warnings.showwarning = idle_showwarning_subproc
77 else:
78 if _warnings_showwarning is not None:
79 warnings.showwarning = _warnings_showwarning
80 _warnings_showwarning = None
81
82capture_warnings(True)
Andrew Svetlov753445a2012-03-26 21:56:44 +030083tcl = tkinter.Tcl()
84
Andrew Svetlov753445a2012-03-26 21:56:44 +030085def handle_tk_events(tcl=tcl):
Andrew Svetlova2251aa2012-03-13 18:36:13 -070086 """Process any tk events that are ready to be dispatched if tkinter
87 has been imported, a tcl interpreter has been created and tk has been
88 loaded."""
Andrew Svetlov753445a2012-03-26 21:56:44 +030089 tcl.eval("update")
Andrew Svetlova2251aa2012-03-13 18:36:13 -070090
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000091# Thread shared globals: Establish a queue between a subthread (which handles
92# the socket) and the main thread (which runs user code), plus global
Guido van Rossum8ce8a782007-11-01 19:42:39 +000093# completion, exit and interruptable (the main thread) flags:
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000094
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000095exit_now = False
96quitting = False
Guido van Rossum8ce8a782007-11-01 19:42:39 +000097interruptable = False
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000098
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000099def main(del_exitfunc=False):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000100 """Start the Python execution server in a subprocess
101
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000102 In the Python subprocess, RPCServer is instantiated with handlerclass
103 MyHandler, which inherits register/unregister methods from RPCHandler via
104 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000105
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000106 When the RPCServer 'server' is instantiated, the TCPServer initialization
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000107 creates an instance of run.MyHandler and calls its handle() method.
108 handle() instantiates a run.Executive object, passing it a reference to the
109 MyHandler object. That reference is saved as attribute rpchandler of the
110 Executive instance. The Executive methods have access to the reference and
111 can pass it on to entities that they command
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400112 (e.g. debugger_r.Debugger.start_debugger()). The latter, in turn, can
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000113 call MyHandler(SocketIO) register/unregister methods via the reference to
114 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000115
116 """
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000117 global exit_now
118 global quitting
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000119 global no_exitfunc
120 no_exitfunc = del_exitfunc
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000121 #time.sleep(15) # test subprocess not responding
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000122 try:
123 assert(len(sys.argv) > 1)
124 port = int(sys.argv[-1])
125 except:
Kurt B. Kaiser8fc98c32009-04-04 20:20:29 +0000126 print("IDLE Subprocess: no IP port passed in sys.argv.",
127 file=sys.__stderr__)
Kurt B. Kaisere67842a2009-04-04 20:13:23 +0000128 return
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400129
130 capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000131 sys.argv[:] = [""]
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000132 sockthread = threading.Thread(target=manage_socket,
133 name='SockThread',
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000134 args=((LOCALHOST, port),))
Benjamin Peterson71088cc2008-09-19 21:49:37 +0000135 sockthread.daemon = True
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000136 sockthread.start()
137 while 1:
138 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000139 if exit_now:
140 try:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000141 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000142 except KeyboardInterrupt:
143 # exiting but got an extra KBI? Try again!
144 continue
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000145 try:
Terry Jan Reedy1e2fcac2017-12-04 16:16:18 -0500146 request = rpc.request_queue.get(block=True, timeout=0.05)
Alexandre Vassalottif260e442008-05-11 19:59:59 +0000147 except queue.Empty:
Terry Jan Reedy1e2fcac2017-12-04 16:16:18 -0500148 request = None
149 # Issue 32207: calling handle_tk_events here adds spurious
150 # queue.Empty traceback to event handling exceptions.
151 if request:
152 seq, (method, args, kwargs) = request
153 ret = method(*args, **kwargs)
154 rpc.response_queue.put((seq, ret))
155 else:
Andrew Svetlova2251aa2012-03-13 18:36:13 -0700156 handle_tk_events()
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000157 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000158 if quitting:
159 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000160 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000161 except SystemExit:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400162 capture_warnings(False)
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000163 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000164 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000165 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000166 try:
167 print_exception()
168 rpc.response_queue.put((seq, None))
169 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000170 # Link didn't work, print same exception to __stderr__
171 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000172 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000173 else:
174 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000175
176def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000177 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000178 time.sleep(i)
179 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000180 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000181 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200182 except OSError as err:
183 print("IDLE Subprocess: OSError: " + err.args[1] +
Georg Brandl6464d472007-10-22 16:16:13 +0000184 ", retrying....", file=sys.__stderr__)
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000185 socket_error = err
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000186 else:
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000187 print("IDLE Subprocess: Connection to "
188 "IDLE GUI failed, exiting.", file=sys.__stderr__)
189 show_socket_error(socket_error, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000190 global exit_now
191 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000192 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000193 server.handle_request() # A single request only
194
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000195def show_socket_error(err, address):
terryjreedy188aedf2017-06-13 21:32:16 -0400196 "Display socket error from manage_socket."
Georg Brandl14fc4272008-05-17 18:39:55 +0000197 import tkinter
terryjreedy188aedf2017-06-13 21:32:16 -0400198 from tkinter.messagebox import showerror
Georg Brandl14fc4272008-05-17 18:39:55 +0000199 root = tkinter.Tk()
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300200 fix_scaling(root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000201 root.withdraw()
terryjreedy188aedf2017-06-13 21:32:16 -0400202 msg = f"IDLE's subprocess can't connect to {address[0]}:{address[1]}.\n"\
203 f"Fatal OSError #{err.errno}: {err.strerror}.\n"\
204 f"See the 'Startup failure' section of the IDLE doc, online at\n"\
205 f"https://docs.python.org/3/library/idle.html#startup-failure"
206 showerror("IDLE Subprocess Error", msg, parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000207 root.destroy()
208
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000209def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000210 import linecache
211 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000212 flush_stdout()
213 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000214 typ, val, tb = excinfo = sys.exc_info()
215 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200216 seen = set()
217
218 def print_exc(typ, exc, tb):
Zane Bitterde860732017-10-17 17:29:39 -0400219 seen.add(id(exc))
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200220 context = exc.__context__
221 cause = exc.__cause__
Zane Bitterde860732017-10-17 17:29:39 -0400222 if cause is not None and id(cause) not in seen:
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200223 print_exc(type(cause), cause, cause.__traceback__)
224 print("\nThe above exception was the direct cause "
225 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200226 elif (context is not None and
227 not exc.__suppress_context__ and
Zane Bitterde860732017-10-17 17:29:39 -0400228 id(context) not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200229 print_exc(type(context), context, context.__traceback__)
230 print("\nDuring handling of the above exception, "
231 "another exception occurred:\n", file=efile)
232 if tb:
233 tbe = traceback.extract_tb(tb)
234 print('Traceback (most recent call last):', file=efile)
235 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400236 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200237 cleanup_traceback(tbe, exclude)
238 traceback.print_list(tbe, file=efile)
239 lines = traceback.format_exception_only(typ, exc)
240 for line in lines:
241 print(line, end='', file=efile)
242
243 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000244
245def cleanup_traceback(tb, exclude):
246 "Remove excluded traces from beginning/end of tb; get cached lines"
247 orig_tb = tb[:]
248 while tb:
249 for rpcfile in exclude:
250 if tb[0][0].count(rpcfile):
251 break # found an exclude, break for: and delete tb[0]
252 else:
253 break # no excludes, have left RPC code, break while:
254 del tb[0]
255 while tb:
256 for rpcfile in exclude:
257 if tb[-1][0].count(rpcfile):
258 break
259 else:
260 break
261 del tb[-1]
262 if len(tb) == 0:
263 # exception was in IDLE internals, don't prune!
264 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000265 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000266 rpchandler = rpc.objecttable['exec'].rpchandler
267 for i in range(len(tb)):
268 fn, ln, nm, line = tb[i]
269 if nm == '?':
270 nm = "-toplevel-"
271 if not line and fn.startswith("<pyshell#"):
272 line = rpchandler.remotecall('linecache', 'getline',
273 (fn, ln), {})
274 tb[i] = fn, ln, nm, line
275
276def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000277 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000278
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000279def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000280 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000281
282 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000283 functions registered with atexit will be removed before exiting.
284 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000285
286 """
287 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000288 import atexit
289 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400290 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000291 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000292
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -0400293
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300294def fix_scaling(root):
295 """Scale fonts on HiDPI displays."""
296 import tkinter.font
297 scaling = float(root.tk.call('tk', 'scaling'))
298 if scaling > 1.4:
299 for name in tkinter.font.names(root):
300 font = tkinter.font.Font(root=root, name=name, exists=True)
301 size = int(font['size'])
302 if size < 0:
303 font['size'] = round(-0.75*size)
304
305
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000306class MyRPCServer(rpc.RPCServer):
307
308 def handle_error(self, request, client_address):
309 """Override RPCServer method for IDLE
310
311 Interrupt the MainThread and exit server if link is dropped.
312
313 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000314 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000315 try:
316 raise
317 except SystemExit:
318 raise
319 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000320 global exit_now
321 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000322 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000323 except:
324 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000325 print('\n' + '-'*40, file=erf)
326 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000327 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000328 print('Client Address: ', client_address, file=erf)
329 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000330 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000331 print('\n*** Unrecoverable, server exiting!', file=erf)
332 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000333 quitting = True
334 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000335
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400336
337# Pseudofiles for shell-remote communication (also used in pyshell)
338
339class PseudoFile(io.TextIOBase):
340
341 def __init__(self, shell, tags, encoding=None):
342 self.shell = shell
343 self.tags = tags
344 self._encoding = encoding
345
346 @property
347 def encoding(self):
348 return self._encoding
349
350 @property
351 def name(self):
352 return '<%s>' % self.tags
353
354 def isatty(self):
355 return True
356
357
358class PseudoOutputFile(PseudoFile):
359
360 def writable(self):
361 return True
362
363 def write(self, s):
364 if self.closed:
365 raise ValueError("write to closed file")
366 if type(s) is not str:
367 if not isinstance(s, str):
368 raise TypeError('must be str, not ' + type(s).__name__)
369 # See issue #19481
370 s = str.__str__(s)
371 return self.shell.write(s, self.tags)
372
373
374class PseudoInputFile(PseudoFile):
375
376 def __init__(self, shell, tags, encoding=None):
377 PseudoFile.__init__(self, shell, tags, encoding)
378 self._line_buffer = ''
379
380 def readable(self):
381 return True
382
383 def read(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 result = self._line_buffer
391 self._line_buffer = ''
392 if size < 0:
393 while True:
394 line = self.shell.readline()
395 if not line: break
396 result += line
397 else:
398 while len(result) < size:
399 line = self.shell.readline()
400 if not line: break
401 result += line
402 self._line_buffer = result[size:]
403 result = result[:size]
404 return result
405
406 def readline(self, size=-1):
407 if self.closed:
408 raise ValueError("read from closed file")
409 if size is None:
410 size = -1
411 elif not isinstance(size, int):
412 raise TypeError('must be int, not ' + type(size).__name__)
413 line = self._line_buffer or self.shell.readline()
414 if size < 0:
415 size = len(line)
416 eol = line.find('\n', 0, size)
417 if eol >= 0:
418 size = eol + 1
419 self._line_buffer = line[size:]
420 return line[:size]
421
422 def close(self):
423 self.shell.close()
424
425
Chui Tey5d2af632002-05-26 13:36:41 +0000426class MyHandler(rpc.RPCHandler):
427
428 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000429 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000430 executive = Executive(self)
431 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200432 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400433 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400434 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400435 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400436 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400437 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400438 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200439
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300440 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000441 # page help() text to shell.
442 import pydoc # import must be done here to capture i/o binding
443 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500444
445 # Keep a reference to stdin so that it won't try to exit IDLE if
446 # sys.stdin gets changed from within IDLE's shell. See issue17838.
447 self._keep_stdin = sys.stdin
448
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000449 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000450 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
451
452 def exithook(self):
453 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000454 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000455
456 def EOFhook(self):
457 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000458 global quitting
459 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000460 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000461
462 def decode_interrupthook(self):
463 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000464 global quitting
465 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000466 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000467
Chui Tey5d2af632002-05-26 13:36:41 +0000468
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000469class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000470
471 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000472 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000473 self.locals = __main__.__dict__
Terry Jan Reedy06e20292018-06-19 23:00:35 -0400474 self.calltip = calltip.Calltip()
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400475 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000476
477 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000478 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000479 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000480 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000481 interruptable = True
482 try:
483 exec(code, self.locals)
484 finally:
485 interruptable = False
Terry Jan Reedy6d965b32019-05-19 22:52:22 -0400486 except SystemExit as e:
487 if e.args: # SystemExit called with an argument.
488 ob = e.args[0]
489 if not isinstance(ob, (type(None), int)):
490 print('SystemExit: ' + str(ob), file=sys.stderr)
491 # Return to the interactive prompt.
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000492 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000493 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000494 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000495 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000496 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000497 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
498 if jit:
499 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000500 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000501 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000502
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000503 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000504 if interruptable:
505 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000506
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000507 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400508 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000509
510 def stop_the_debugger(self, idb_adap_oid):
511 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
512 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000513
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000514 def get_the_calltip(self, name):
515 return self.calltip.fetch_tip(name)
516
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000517 def get_the_completion_list(self, what, mode):
518 return self.autocomplete.fetch_completions(what, mode)
519
Chui Tey5d2af632002-05-26 13:36:41 +0000520 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000521 if self.usr_exc_info:
522 typ, val, tb = self.usr_exc_info
523 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000524 return None
525 flist = None
526 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000527 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000528 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
529 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000530 sys.last_type = typ
531 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400532 item = stackviewer.StackTreeItem(flist, tb)
533 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400534
Terry Jan Reedy81bb97d2019-05-24 21:59:53 -0400535
536if __name__ == '__main__':
537 from unittest import main
538 main('idlelib.idle_test.test_run', verbosity=2)
539
540capture_warnings(False) # Make sure turned off; see bpo-18081.