blob: 6b3928b7bf2bc79fb24351ee348edc7562461864 [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()
Terry Jan Reedy8fac1222019-06-17 17:23:28 -0400202 showerror(
203 "Subprocess Connection Error",
204 f"IDLE's subprocess can't connect to {address[0]}:{address[1]}.\n"
205 f"Fatal OSError #{err.errno}: {err.strerror}.\n"
206 "See the 'Startup failure' section of the IDLE doc, online at\n"
207 "https://docs.python.org/3/library/idle.html#startup-failure",
208 parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000209 root.destroy()
210
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000211def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000212 import linecache
213 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000214 flush_stdout()
215 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000216 typ, val, tb = excinfo = sys.exc_info()
217 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200218 seen = set()
219
220 def print_exc(typ, exc, tb):
Zane Bitterde860732017-10-17 17:29:39 -0400221 seen.add(id(exc))
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200222 context = exc.__context__
223 cause = exc.__cause__
Zane Bitterde860732017-10-17 17:29:39 -0400224 if cause is not None and id(cause) not in seen:
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200225 print_exc(type(cause), cause, cause.__traceback__)
226 print("\nThe above exception was the direct cause "
227 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200228 elif (context is not None and
229 not exc.__suppress_context__ and
Zane Bitterde860732017-10-17 17:29:39 -0400230 id(context) not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200231 print_exc(type(context), context, context.__traceback__)
232 print("\nDuring handling of the above exception, "
233 "another exception occurred:\n", file=efile)
234 if tb:
235 tbe = traceback.extract_tb(tb)
236 print('Traceback (most recent call last):', file=efile)
237 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400238 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200239 cleanup_traceback(tbe, exclude)
240 traceback.print_list(tbe, file=efile)
241 lines = traceback.format_exception_only(typ, exc)
242 for line in lines:
243 print(line, end='', file=efile)
244
245 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000246
247def cleanup_traceback(tb, exclude):
248 "Remove excluded traces from beginning/end of tb; get cached lines"
249 orig_tb = tb[:]
250 while tb:
251 for rpcfile in exclude:
252 if tb[0][0].count(rpcfile):
253 break # found an exclude, break for: and delete tb[0]
254 else:
255 break # no excludes, have left RPC code, break while:
256 del tb[0]
257 while tb:
258 for rpcfile in exclude:
259 if tb[-1][0].count(rpcfile):
260 break
261 else:
262 break
263 del tb[-1]
264 if len(tb) == 0:
265 # exception was in IDLE internals, don't prune!
266 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000267 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000268 rpchandler = rpc.objecttable['exec'].rpchandler
269 for i in range(len(tb)):
270 fn, ln, nm, line = tb[i]
271 if nm == '?':
272 nm = "-toplevel-"
273 if not line and fn.startswith("<pyshell#"):
274 line = rpchandler.remotecall('linecache', 'getline',
275 (fn, ln), {})
276 tb[i] = fn, ln, nm, line
277
278def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000279 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000280
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000281def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000282 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000283
284 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000285 functions registered with atexit will be removed before exiting.
286 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000287
288 """
289 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000290 import atexit
291 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400292 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000293 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000294
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -0400295
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300296def fix_scaling(root):
297 """Scale fonts on HiDPI displays."""
298 import tkinter.font
299 scaling = float(root.tk.call('tk', 'scaling'))
300 if scaling > 1.4:
301 for name in tkinter.font.names(root):
302 font = tkinter.font.Font(root=root, name=name, exists=True)
303 size = int(font['size'])
304 if size < 0:
305 font['size'] = round(-0.75*size)
306
307
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000308class MyRPCServer(rpc.RPCServer):
309
310 def handle_error(self, request, client_address):
311 """Override RPCServer method for IDLE
312
313 Interrupt the MainThread and exit server if link is dropped.
314
315 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000316 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000317 try:
318 raise
319 except SystemExit:
320 raise
321 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000322 global exit_now
323 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000324 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000325 except:
326 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000327 print('\n' + '-'*40, file=erf)
328 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000329 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000330 print('Client Address: ', client_address, file=erf)
331 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000332 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000333 print('\n*** Unrecoverable, server exiting!', file=erf)
334 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000335 quitting = True
336 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000337
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400338
339# Pseudofiles for shell-remote communication (also used in pyshell)
340
341class PseudoFile(io.TextIOBase):
342
343 def __init__(self, shell, tags, encoding=None):
344 self.shell = shell
345 self.tags = tags
346 self._encoding = encoding
347
348 @property
349 def encoding(self):
350 return self._encoding
351
352 @property
353 def name(self):
354 return '<%s>' % self.tags
355
356 def isatty(self):
357 return True
358
359
360class PseudoOutputFile(PseudoFile):
361
362 def writable(self):
363 return True
364
365 def write(self, s):
366 if self.closed:
367 raise ValueError("write to closed file")
368 if type(s) is not str:
369 if not isinstance(s, str):
370 raise TypeError('must be str, not ' + type(s).__name__)
371 # See issue #19481
372 s = str.__str__(s)
373 return self.shell.write(s, self.tags)
374
375
376class PseudoInputFile(PseudoFile):
377
378 def __init__(self, shell, tags, encoding=None):
379 PseudoFile.__init__(self, shell, tags, encoding)
380 self._line_buffer = ''
381
382 def readable(self):
383 return True
384
385 def read(self, size=-1):
386 if self.closed:
387 raise ValueError("read from closed file")
388 if size is None:
389 size = -1
390 elif not isinstance(size, int):
391 raise TypeError('must be int, not ' + type(size).__name__)
392 result = self._line_buffer
393 self._line_buffer = ''
394 if size < 0:
395 while True:
396 line = self.shell.readline()
397 if not line: break
398 result += line
399 else:
400 while len(result) < size:
401 line = self.shell.readline()
402 if not line: break
403 result += line
404 self._line_buffer = result[size:]
405 result = result[:size]
406 return result
407
408 def readline(self, size=-1):
409 if self.closed:
410 raise ValueError("read from closed file")
411 if size is None:
412 size = -1
413 elif not isinstance(size, int):
414 raise TypeError('must be int, not ' + type(size).__name__)
415 line = self._line_buffer or self.shell.readline()
416 if size < 0:
417 size = len(line)
418 eol = line.find('\n', 0, size)
419 if eol >= 0:
420 size = eol + 1
421 self._line_buffer = line[size:]
422 return line[:size]
423
424 def close(self):
425 self.shell.close()
426
427
Chui Tey5d2af632002-05-26 13:36:41 +0000428class MyHandler(rpc.RPCHandler):
429
430 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000431 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000432 executive = Executive(self)
433 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200434 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400435 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400436 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400437 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400438 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400439 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400440 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200441
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300442 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000443 # page help() text to shell.
444 import pydoc # import must be done here to capture i/o binding
445 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500446
447 # Keep a reference to stdin so that it won't try to exit IDLE if
448 # sys.stdin gets changed from within IDLE's shell. See issue17838.
449 self._keep_stdin = sys.stdin
450
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000451 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
453
454 def exithook(self):
455 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000456 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000457
458 def EOFhook(self):
459 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000460 global quitting
461 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000462 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000463
464 def decode_interrupthook(self):
465 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000466 global quitting
467 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000468 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000469
Chui Tey5d2af632002-05-26 13:36:41 +0000470
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000471class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000472
473 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000474 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000475 self.locals = __main__.__dict__
Terry Jan Reedy06e20292018-06-19 23:00:35 -0400476 self.calltip = calltip.Calltip()
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400477 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000478
479 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000480 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000481 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000482 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000483 interruptable = True
484 try:
485 exec(code, self.locals)
486 finally:
487 interruptable = False
Terry Jan Reedy6d965b32019-05-19 22:52:22 -0400488 except SystemExit as e:
489 if e.args: # SystemExit called with an argument.
490 ob = e.args[0]
491 if not isinstance(ob, (type(None), int)):
492 print('SystemExit: ' + str(ob), file=sys.stderr)
493 # Return to the interactive prompt.
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000494 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000495 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000496 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000497 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000498 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000499 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
500 if jit:
501 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000502 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000503 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000504
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000505 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000506 if interruptable:
507 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000508
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000509 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400510 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000511
512 def stop_the_debugger(self, idb_adap_oid):
513 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
514 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000515
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000516 def get_the_calltip(self, name):
517 return self.calltip.fetch_tip(name)
518
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000519 def get_the_completion_list(self, what, mode):
520 return self.autocomplete.fetch_completions(what, mode)
521
Chui Tey5d2af632002-05-26 13:36:41 +0000522 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000523 if self.usr_exc_info:
524 typ, val, tb = self.usr_exc_info
525 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000526 return None
527 flist = None
528 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000529 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000530 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
531 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000532 sys.last_type = typ
533 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400534 item = stackviewer.StackTreeItem(flist, tb)
535 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400536
Terry Jan Reedy81bb97d2019-05-24 21:59:53 -0400537
538if __name__ == '__main__':
539 from unittest import main
540 main('idlelib.idle_test.test_run', verbosity=2)
541
542capture_warnings(False) # Make sure turned off; see bpo-18081.