blob: b4a2b54a33c850b49734b78ce6efec038077fc12 [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
Terry Jan Reedy06e20292018-06-19 23:00:35 -040014from idlelib import calltip # Calltip
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040015from 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:
Terry Jan Reedy1e2fcac2017-12-04 16:16:18 -0500137 request = rpc.request_queue.get(block=True, timeout=0.05)
Alexandre Vassalottif260e442008-05-11 19:59:59 +0000138 except queue.Empty:
Terry Jan Reedy1e2fcac2017-12-04 16:16:18 -0500139 request = None
140 # Issue 32207: calling handle_tk_events here adds spurious
141 # queue.Empty traceback to event handling exceptions.
142 if request:
143 seq, (method, args, kwargs) = request
144 ret = method(*args, **kwargs)
145 rpc.response_queue.put((seq, ret))
146 else:
Andrew Svetlova2251aa2012-03-13 18:36:13 -0700147 handle_tk_events()
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000148 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000149 if quitting:
150 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000151 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000152 except SystemExit:
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400153 capture_warnings(False)
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000154 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000155 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000156 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000157 try:
158 print_exception()
159 rpc.response_queue.put((seq, None))
160 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000161 # Link didn't work, print same exception to __stderr__
162 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000163 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000164 else:
165 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000166
167def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000168 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000169 time.sleep(i)
170 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000171 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000172 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200173 except OSError as err:
174 print("IDLE Subprocess: OSError: " + err.args[1] +
Georg Brandl6464d472007-10-22 16:16:13 +0000175 ", retrying....", file=sys.__stderr__)
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000176 socket_error = err
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000177 else:
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000178 print("IDLE Subprocess: Connection to "
179 "IDLE GUI failed, exiting.", file=sys.__stderr__)
180 show_socket_error(socket_error, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000181 global exit_now
182 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000183 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000184 server.handle_request() # A single request only
185
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000186def show_socket_error(err, address):
terryjreedy188aedf2017-06-13 21:32:16 -0400187 "Display socket error from manage_socket."
Georg Brandl14fc4272008-05-17 18:39:55 +0000188 import tkinter
terryjreedy188aedf2017-06-13 21:32:16 -0400189 from tkinter.messagebox import showerror
Georg Brandl14fc4272008-05-17 18:39:55 +0000190 root = tkinter.Tk()
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300191 fix_scaling(root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000192 root.withdraw()
terryjreedy188aedf2017-06-13 21:32:16 -0400193 msg = f"IDLE's subprocess can't connect to {address[0]}:{address[1]}.\n"\
194 f"Fatal OSError #{err.errno}: {err.strerror}.\n"\
195 f"See the 'Startup failure' section of the IDLE doc, online at\n"\
196 f"https://docs.python.org/3/library/idle.html#startup-failure"
197 showerror("IDLE Subprocess Error", msg, parent=root)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000198 root.destroy()
199
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000200def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000201 import linecache
202 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000203 flush_stdout()
204 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000205 typ, val, tb = excinfo = sys.exc_info()
206 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200207 seen = set()
208
209 def print_exc(typ, exc, tb):
Zane Bitterde860732017-10-17 17:29:39 -0400210 seen.add(id(exc))
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200211 context = exc.__context__
212 cause = exc.__cause__
Zane Bitterde860732017-10-17 17:29:39 -0400213 if cause is not None and id(cause) not in seen:
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200214 print_exc(type(cause), cause, cause.__traceback__)
215 print("\nThe above exception was the direct cause "
216 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200217 elif (context is not None and
218 not exc.__suppress_context__ and
Zane Bitterde860732017-10-17 17:29:39 -0400219 id(context) not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200220 print_exc(type(context), context, context.__traceback__)
221 print("\nDuring handling of the above exception, "
222 "another exception occurred:\n", file=efile)
223 if tb:
224 tbe = traceback.extract_tb(tb)
225 print('Traceback (most recent call last):', file=efile)
226 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400227 "debugger_r.py", "bdb.py")
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200228 cleanup_traceback(tbe, exclude)
229 traceback.print_list(tbe, file=efile)
230 lines = traceback.format_exception_only(typ, exc)
231 for line in lines:
232 print(line, end='', file=efile)
233
234 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000235
236def cleanup_traceback(tb, exclude):
237 "Remove excluded traces from beginning/end of tb; get cached lines"
238 orig_tb = tb[:]
239 while tb:
240 for rpcfile in exclude:
241 if tb[0][0].count(rpcfile):
242 break # found an exclude, break for: and delete tb[0]
243 else:
244 break # no excludes, have left RPC code, break while:
245 del tb[0]
246 while tb:
247 for rpcfile in exclude:
248 if tb[-1][0].count(rpcfile):
249 break
250 else:
251 break
252 del tb[-1]
253 if len(tb) == 0:
254 # exception was in IDLE internals, don't prune!
255 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000256 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000257 rpchandler = rpc.objecttable['exec'].rpchandler
258 for i in range(len(tb)):
259 fn, ln, nm, line = tb[i]
260 if nm == '?':
261 nm = "-toplevel-"
262 if not line and fn.startswith("<pyshell#"):
263 line = rpchandler.remotecall('linecache', 'getline',
264 (fn, ln), {})
265 tb[i] = fn, ln, nm, line
266
267def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000268 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000269
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000270def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000271 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000272
273 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000274 functions registered with atexit will be removed before exiting.
275 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000276
277 """
278 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000279 import atexit
280 atexit._clear()
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400281 capture_warnings(False)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000282 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000283
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -0400284
Serhiy Storchakaa96c96f2017-09-21 11:20:06 +0300285def fix_scaling(root):
286 """Scale fonts on HiDPI displays."""
287 import tkinter.font
288 scaling = float(root.tk.call('tk', 'scaling'))
289 if scaling > 1.4:
290 for name in tkinter.font.names(root):
291 font = tkinter.font.Font(root=root, name=name, exists=True)
292 size = int(font['size'])
293 if size < 0:
294 font['size'] = round(-0.75*size)
295
296
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000297class MyRPCServer(rpc.RPCServer):
298
299 def handle_error(self, request, client_address):
300 """Override RPCServer method for IDLE
301
302 Interrupt the MainThread and exit server if link is dropped.
303
304 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000305 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000306 try:
307 raise
308 except SystemExit:
309 raise
310 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000311 global exit_now
312 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000313 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000314 except:
315 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000316 print('\n' + '-'*40, file=erf)
317 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000318 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000319 print('Client Address: ', client_address, file=erf)
320 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000321 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000322 print('\n*** Unrecoverable, server exiting!', file=erf)
323 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000324 quitting = True
325 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000326
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400327
328# Pseudofiles for shell-remote communication (also used in pyshell)
329
330class PseudoFile(io.TextIOBase):
331
332 def __init__(self, shell, tags, encoding=None):
333 self.shell = shell
334 self.tags = tags
335 self._encoding = encoding
336
337 @property
338 def encoding(self):
339 return self._encoding
340
341 @property
342 def name(self):
343 return '<%s>' % self.tags
344
345 def isatty(self):
346 return True
347
348
349class PseudoOutputFile(PseudoFile):
350
351 def writable(self):
352 return True
353
354 def write(self, s):
355 if self.closed:
356 raise ValueError("write to closed file")
357 if type(s) is not str:
358 if not isinstance(s, str):
359 raise TypeError('must be str, not ' + type(s).__name__)
360 # See issue #19481
361 s = str.__str__(s)
362 return self.shell.write(s, self.tags)
363
364
365class PseudoInputFile(PseudoFile):
366
367 def __init__(self, shell, tags, encoding=None):
368 PseudoFile.__init__(self, shell, tags, encoding)
369 self._line_buffer = ''
370
371 def readable(self):
372 return True
373
374 def read(self, size=-1):
375 if self.closed:
376 raise ValueError("read from closed file")
377 if size is None:
378 size = -1
379 elif not isinstance(size, int):
380 raise TypeError('must be int, not ' + type(size).__name__)
381 result = self._line_buffer
382 self._line_buffer = ''
383 if size < 0:
384 while True:
385 line = self.shell.readline()
386 if not line: break
387 result += line
388 else:
389 while len(result) < size:
390 line = self.shell.readline()
391 if not line: break
392 result += line
393 self._line_buffer = result[size:]
394 result = result[:size]
395 return result
396
397 def readline(self, size=-1):
398 if self.closed:
399 raise ValueError("read from closed file")
400 if size is None:
401 size = -1
402 elif not isinstance(size, int):
403 raise TypeError('must be int, not ' + type(size).__name__)
404 line = self._line_buffer or self.shell.readline()
405 if size < 0:
406 size = len(line)
407 eol = line.find('\n', 0, size)
408 if eol >= 0:
409 size = eol + 1
410 self._line_buffer = line[size:]
411 return line[:size]
412
413 def close(self):
414 self.shell.close()
415
416
Chui Tey5d2af632002-05-26 13:36:41 +0000417class MyHandler(rpc.RPCHandler):
418
419 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000420 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000421 executive = Executive(self)
422 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200423 self.console = self.get_remote_proxy("console")
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400424 sys.stdin = PseudoInputFile(self.console, "stdin",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400425 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400426 sys.stdout = PseudoOutputFile(self.console, "stdout",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400427 iomenu.encoding)
Terry Jan Reedy6cf0e132016-07-15 02:43:03 -0400428 sys.stderr = PseudoOutputFile(self.console, "stderr",
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400429 iomenu.encoding)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200430
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300431 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000432 # page help() text to shell.
433 import pydoc # import must be done here to capture i/o binding
434 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500435
436 # Keep a reference to stdin so that it won't try to exit IDLE if
437 # sys.stdin gets changed from within IDLE's shell. See issue17838.
438 self._keep_stdin = sys.stdin
439
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000440 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000441 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
442
443 def exithook(self):
444 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000445 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000446
447 def EOFhook(self):
448 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000449 global quitting
450 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000451 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452
453 def decode_interrupthook(self):
454 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000455 global quitting
456 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000457 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000458
Chui Tey5d2af632002-05-26 13:36:41 +0000459
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000460class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000461
462 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000463 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000464 self.locals = __main__.__dict__
Terry Jan Reedy06e20292018-06-19 23:00:35 -0400465 self.calltip = calltip.Calltip()
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400466 self.autocomplete = autocomplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000467
468 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000469 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000470 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000471 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000472 interruptable = True
473 try:
474 exec(code, self.locals)
475 finally:
476 interruptable = False
Terry Jan Reedy6d965b32019-05-19 22:52:22 -0400477 except SystemExit as e:
478 if e.args: # SystemExit called with an argument.
479 ob = e.args[0]
480 if not isinstance(ob, (type(None), int)):
481 print('SystemExit: ' + str(ob), file=sys.stderr)
482 # Return to the interactive prompt.
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000483 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000484 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000485 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000486 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000487 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000488 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
489 if jit:
490 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000491 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000492 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000493
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000494 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000495 if interruptable:
496 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000497
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000498 def start_the_debugger(self, gui_adap_oid):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400499 return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000500
501 def stop_the_debugger(self, idb_adap_oid):
502 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
503 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000504
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000505 def get_the_calltip(self, name):
506 return self.calltip.fetch_tip(name)
507
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000508 def get_the_completion_list(self, what, mode):
509 return self.autocomplete.fetch_completions(what, mode)
510
Chui Tey5d2af632002-05-26 13:36:41 +0000511 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000512 if self.usr_exc_info:
513 typ, val, tb = self.usr_exc_info
514 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000515 return None
516 flist = None
517 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000518 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000519 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
520 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000521 sys.last_type = typ
522 sys.last_value = val
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -0400523 item = stackviewer.StackTreeItem(flist, tb)
524 return debugobj_r.remote_object_tree_item(item)
Terry Jan Reedy95a3f112013-06-28 23:50:12 -0400525
526capture_warnings(False) # Make sure turned off; see issue 18081