blob: cde389ad009cbe3d6b45e5e2f12fbd111d5730cb [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
David Scherer7aced172000-08-15 01:13:23 +00002
Victor Stinner979482a2011-09-02 01:00:40 +02003import getopt
David Scherer7aced172000-08-15 01:13:23 +00004import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00005import os.path
David Scherer7aced172000-08-15 01:13:23 +00006import re
Chui Tey5d2af632002-05-26 13:36:41 +00007import socket
Victor Stinner979482a2011-09-02 01:00:40 +02008import subprocess
9import sys
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000010import threading
Victor Stinner979482a2011-09-02 01:00:40 +020011import time
12import tokenize
Chui Tey5d2af632002-05-26 13:36:41 +000013import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000014import types
Martin v. Löwisc882b7c2012-07-25 10:47:20 +020015import io
David Scherer7aced172000-08-15 01:13:23 +000016
17import linecache
18from code import InteractiveInterpreter
Terry Jan Reedy32622232013-03-30 18:32:19 -040019from platform import python_version
David Scherer7aced172000-08-15 01:13:23 +000020
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021try:
Georg Brandl14fc4272008-05-17 18:39:55 +000022 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000023except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000024 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000025 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000026 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000027import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000028
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000029from idlelib.EditorWindow import EditorWindow, fixwordbreaks
30from idlelib.FileList import FileList
31from idlelib.ColorDelegator import ColorDelegator
32from idlelib.UndoDelegator import UndoDelegator
33from idlelib.OutputWindow import OutputWindow
34from idlelib.configHandler import idleConf
35from idlelib import idlever
36from idlelib import rpc
37from idlelib import Debugger
38from idlelib import RemoteDebugger
39from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000040
Kurt B. Kaisere866c812009-04-04 21:07:39 +000041HOST = '127.0.0.1' # python execution server on localhost loopback
42PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000043
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000044# Override warnings module to write to warning_stream. Initialize to send IDLE
45# internal warnings to the console. ScriptBinding.check_syntax() will
46# temporarily redirect the stream to the shell window to display warnings when
47# checking user's code.
48global warning_stream
49warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000050try:
51 import warnings
52except ImportError:
53 pass
54else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000055 def idle_showwarning(message, category, filename, lineno,
56 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000057 if file is None:
58 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000059 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000060 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070061 lineno, line=line))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020062 except OSError:
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000063 pass ## file (probably __stderr__) is invalid, warning dropped.
Guilherme Polo1fff0082009-08-14 15:05:30 +000064 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 """Format warnings the IDLE way"""
66 s = "\nWarning (from warnings module):\n"
67 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000068 if line is None:
69 line = linecache.getline(filename, lineno)
70 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 if line:
72 s += " %s\n" % line
73 s += "%s: %s\n>>> " % (category.__name__, message)
74 return s
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000082 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086 """
David Scherer7aced172000-08-15 01:13:23 +000087 cache = linecache.cache
88 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000089 for key in list(cache):
90 if key[:1] + key[-1:] == '<>':
91 save[key] = cache.pop(key)
92 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000093 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000094
Kurt B. Kaiser81885592002-11-29 22:10:53 +000095# Patch linecache.checkcache():
96linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000097
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000098
David Scherer7aced172000-08-15 01:13:23 +000099class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000100 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000101
David Scherer7aced172000-08-15 01:13:23 +0000102 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000104 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000105 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
108
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000109 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
110 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000111 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000112 def filename_changed_hook(old_hook=self.io.filename_change_hook,
113 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000114 self.restore_file_breaks()
115 old_hook()
116 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500117 if self.io.filename:
118 self.restore_file_breaks()
Chui Teya2adb0f2002-11-04 22:14:54 +0000119
Andrew Svetlovd1837672012-11-01 22:41:19 +0200120 rmenu_specs = [
121 ("Cut", "<<cut>>", "rmenu_check_cut"),
122 ("Copy", "<<copy>>", "rmenu_check_copy"),
123 ("Paste", "<<paste>>", "rmenu_check_paste"),
124 (None, None, None),
125 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
126 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
127 ]
David Scherer7aced172000-08-15 01:13:23 +0000128
Chui Teya2adb0f2002-11-04 22:14:54 +0000129 def set_breakpoint(self, lineno):
130 text = self.text
131 filename = self.io.filename
132 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
133 try:
134 i = self.breakpoints.index(lineno)
135 except ValueError: # only add if missing, i.e. do once
136 self.breakpoints.append(lineno)
137 try: # update the subprocess debugger
138 debug = self.flist.pyshell.interp.debugger
139 debug.set_breakpoint_here(filename, lineno)
140 except: # but debugger may not be active right now....
141 pass
142
David Scherer7aced172000-08-15 01:13:23 +0000143 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000144 text = self.text
145 filename = self.io.filename
146 if not filename:
147 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000148 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000149 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000150 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000151
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000152 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 text = self.text
154 filename = self.io.filename
155 if not filename:
156 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000157 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000158 lineno = int(float(text.index("insert")))
159 try:
160 self.breakpoints.remove(lineno)
161 except:
162 pass
163 text.tag_remove("BREAK", "insert linestart",\
164 "insert lineend +1char")
165 try:
166 debug = self.flist.pyshell.interp.debugger
167 debug.clear_breakpoint_here(filename, lineno)
168 except:
169 pass
170
171 def clear_file_breaks(self):
172 if self.breakpoints:
173 text = self.text
174 filename = self.io.filename
175 if not filename:
176 text.bell()
177 return
178 self.breakpoints = []
179 text.tag_remove("BREAK", "1.0", END)
180 try:
181 debug = self.flist.pyshell.interp.debugger
182 debug.clear_file_breaks(filename)
183 except:
184 pass
185
Chui Teya2adb0f2002-11-04 22:14:54 +0000186 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000187 "Save breakpoints when file is saved"
188 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
189 # be run. The breaks are saved at that time. If we introduce
190 # a temporary file save feature the save breaks functionality
191 # needs to be re-verified, since the breaks at the time the
192 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000193 # permanent save of the file. Currently, a break introduced
194 # after a save will be effective, but not persistent.
195 # This is necessary to keep the saved breaks synched with the
196 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000197 #
198 # Breakpoints are set as tagged ranges in the text. Certain
199 # kinds of edits cause these ranges to be deleted: Inserting
200 # or deleting a line just before a breakpoint, and certain
201 # deletions prior to a breakpoint. These issues need to be
202 # investigated and understood. It's not clear if they are
203 # Tk issues or IDLE issues, or whether they can actually
204 # be fixed. Since a modified file has to be saved before it is
205 # run, and since self.breakpoints (from which the subprocess
206 # debugger is loaded) is updated during the save, the visible
207 # breaks stay synched with the subprocess even if one of these
208 # unexpected breakpoint deletions occurs.
209 breaks = self.breakpoints
210 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000211 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200212 with open(self.breakpointPath, "r") as fp:
213 lines = fp.readlines()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200214 except OSError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800216 try:
217 with open(self.breakpointPath, "w") as new_file:
218 for line in lines:
219 if not line.startswith(filename + '='):
220 new_file.write(line)
221 self.update_breakpoints()
222 breaks = self.breakpoints
223 if breaks:
224 new_file.write(filename + '=' + str(breaks) + '\n')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200225 except OSError as err:
Ned Deilyf505b742011-12-14 14:58:24 -0800226 if not getattr(self.root, "breakpoint_error_displayed", False):
227 self.root.breakpoint_error_displayed = True
228 tkMessageBox.showerror(title='IDLE Error',
229 message='Unable to update breakpoint list:\n%s'
230 % str(err),
231 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000232
233 def restore_file_breaks(self):
234 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500235 if self.io is None:
236 # can happen if IDLE closes due to the .update() call
237 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000238 filename = self.io.filename
239 if filename is None:
240 return
Chui Tey69371d62002-11-04 23:39:45 +0000241 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200242 with open(self.breakpointPath, "r") as fp:
243 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000244 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000245 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000246 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000247 for breakpoint_linenumber in breakpoint_linenumbers:
248 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000249
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 def update_breakpoints(self):
251 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000252 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000253 ranges = text.tag_ranges("BREAK")
254 linenumber_list = self.ranges_to_linenumbers(ranges)
255 self.breakpoints = linenumber_list
256
257 def ranges_to_linenumbers(self, ranges):
258 lines = []
259 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300260 lineno = int(float(ranges[index].string))
261 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000262 while lineno < end:
263 lines.append(lineno)
264 lineno += 1
265 return lines
266
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000267# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000268# def saved_change_hook(self):
269# "Extend base method - clear breaks if module is modified"
270# if not self.get_saved():
271# self.clear_file_breaks()
272# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000273
274 def _close(self):
275 "Extend base method - clear breaks when module is closed"
276 self.clear_file_breaks()
277 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000278
David Scherer7aced172000-08-15 01:13:23 +0000279
280class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000282
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000283 # override FileList's class variable, instances return PyShellEditorWindow
284 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000285 EditorWindow = PyShellEditorWindow
286
287 pyshell = None
288
289 def open_shell(self, event=None):
290 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000291 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000292 else:
293 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000294 if self.pyshell:
295 if not self.pyshell.begin():
296 return None
David Scherer7aced172000-08-15 01:13:23 +0000297 return self.pyshell
298
299
300class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000301 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000302
Steven M. Gavab77d3432002-03-02 07:16:21 +0000303 def __init__(self):
304 ColorDelegator.__init__(self)
305 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000306
307 def recolorize_main(self):
308 self.tag_remove("TODO", "1.0", "iomark")
309 self.tag_add("SYNC", "1.0", "iomark")
310 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000311
Steven M. Gavab77d3432002-03-02 07:16:21 +0000312 def LoadTagDefs(self):
313 ColorDelegator.LoadTagDefs(self)
314 theme = idleConf.GetOption('main','Theme','name')
315 self.tagdefs.update({
316 "stdin": {'background':None,'foreground':None},
317 "stdout": idleConf.GetHighlight(theme, "stdout"),
318 "stderr": idleConf.GetHighlight(theme, "stderr"),
319 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000320 })
David Scherer7aced172000-08-15 01:13:23 +0000321
Ned Deily8b2a56b2012-05-31 09:17:29 -0700322 def removecolors(self):
323 # Don't remove shell color tags before "iomark"
324 for tag in self.tagdefs:
325 self.tag_remove(tag, "iomark", "end")
326
David Scherer7aced172000-08-15 01:13:23 +0000327class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000328 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000329
330 def insert(self, index, chars, tags=None):
331 try:
332 if self.delegate.compare(index, "<", "iomark"):
333 self.delegate.bell()
334 return
335 except TclError:
336 pass
337 UndoDelegator.insert(self, index, chars, tags)
338
339 def delete(self, index1, index2=None):
340 try:
341 if self.delegate.compare(index1, "<", "iomark"):
342 self.delegate.bell()
343 return
344 except TclError:
345 pass
346 UndoDelegator.delete(self, index1, index2)
347
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000348
349class MyRPCClient(rpc.RPCClient):
350
351 def handle_EOF(self):
352 "Override the base class - just re-raise EOFError"
353 raise EOFError
354
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000355
David Scherer7aced172000-08-15 01:13:23 +0000356class ModifiedInterpreter(InteractiveInterpreter):
357
358 def __init__(self, tkconsole):
359 self.tkconsole = tkconsole
360 locals = sys.modules['__main__'].__dict__
361 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000362 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000363 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000364 self.subprocess_arglist = None
365 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700366 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000367
Roger Serwy036e8492013-06-11 22:13:17 -0500368 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000369 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700370 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000371
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000372 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000373 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000374 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700375 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000376
Tony Lowndsf53dec22002-12-20 04:24:43 +0000377 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000378 assert (self.port!=0), (
379 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000380 w = ['-W' + s for s in sys.warnoptions]
381 # Maybe IDLE is installed and is being accessed via sys.path,
382 # or maybe it's not installed and the idle.py script is being
383 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000384 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
385 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000386 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000387 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000388 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000389 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700390 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000391
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000392 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000393 addr = (HOST, self.port)
394 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000395 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000396 time.sleep(i)
397 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000398 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000399 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200400 except OSError as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000401 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000402 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000403 self.display_port_binding_error()
404 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000405 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
406 self.port = self.rpcclt.listening_sock.getsockname()[1]
407 # if PORT was not 0, probably working with a remote execution server
408 if PORT != 0:
409 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
410 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
411 # on Windows since the implementation allows two active sockets on
412 # the same address!
413 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
414 socket.SO_REUSEADDR, 1)
415 self.spawn_subprocess()
416 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000417 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000418 self.rpcclt.listening_sock.settimeout(10)
419 try:
420 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000421 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000422 self.display_no_subprocess_error()
423 return None
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200424 self.rpcclt.register("console", self.tkconsole)
425 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000426 self.rpcclt.register("stdout", self.tkconsole.stdout)
427 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000428 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000429 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000430 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500431 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000432 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000433 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000434
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500435 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000436 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000437 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000438 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000439 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000440 debug = self.getdebugger()
441 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000442 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000443 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000444 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
445 except:
446 pass
447 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000448 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700449 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000450 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000451 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000452 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000453 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000454 try:
455 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000456 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000457 self.display_no_subprocess_error()
458 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500459 self.transfer_path(with_cwd=with_cwd)
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500460 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000461 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000462 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000463 if was_executing:
464 console.write('\n')
465 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000466 halfbar = ((int(console.width) - 16) // 2) * '='
467 console.write(halfbar + ' RESTART ' + halfbar)
468 console.text.mark_set("restart", "end-1c")
469 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000470 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000471 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000472 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000473 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000474 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000475 # reload remote debugger breakpoints for all PyShellEditWindows
476 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700477 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000478 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000479 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000480
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000481 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000483
484 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000485 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000486
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000487 def kill_subprocess(self):
Roger Serwy036e8492013-06-11 22:13:17 -0500488 if self._afterid is not None:
489 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000490 try:
Ned Deily55f87572011-11-05 22:36:44 -0700491 self.rpcclt.listening_sock.close()
492 except AttributeError: # no socket
493 pass
494 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000495 self.rpcclt.close()
496 except AttributeError: # no socket
497 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700498 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000499 self.tkconsole.executing = False
500 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000501
Ned Deilye5cad232011-08-02 18:47:13 -0700502 def terminate_subprocess(self):
503 "Make sure subprocess is terminated"
504 try:
505 self.rpcsubproc.kill()
506 except OSError:
507 # process already terminated
508 return
509 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000510 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700511 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000512 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000513 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000514
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500515 def transfer_path(self, with_cwd=False):
516 if with_cwd: # Issue 13506
517 path = [''] # include Current Working Directory
518 path.extend(sys.path)
519 else:
520 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500521
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000522 self.runcommand("""if 1:
523 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000524 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000525 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500526 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000527
Chui Tey5d2af632002-05-26 13:36:41 +0000528 active_seq = None
529
530 def poll_subprocess(self):
531 clt = self.rpcclt
532 if clt is None:
533 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000534 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000535 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200536 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000537 # lost connection or subprocess terminated itself, restart
538 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000539 if self.tkconsole.closing:
540 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000541 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000542 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000543 if response:
544 self.tkconsole.resetoutput()
545 self.active_seq = None
546 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000547 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000548 if how == "OK":
549 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000550 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000551 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000552 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
553 self.remote_stack_viewer()
554 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000555 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000556 print(errmsg, what, file=sys.__stderr__)
557 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000558 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000559 try:
560 self.tkconsole.endexecuting()
561 except AttributeError: # shell may have closed
562 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000563 # Reschedule myself
564 if not self.tkconsole.closing:
Roger Serwy036e8492013-06-11 22:13:17 -0500565 self._afterid = self.tkconsole.text.after(
566 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000567
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000568 debugger = None
569
570 def setdebugger(self, debugger):
571 self.debugger = debugger
572
573 def getdebugger(self):
574 return self.debugger
575
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000576 def open_remote_stack_viewer(self):
577 """Initiate the remote stack viewer from a separate thread.
578
579 This method is called from the subprocess, and by returning from this
580 method we allow the subprocess to unblock. After a bit the shell
581 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000582 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000583 the RPC mechanism.
584
585 """
586 self.tkconsole.text.after(300, self.remote_stack_viewer)
587 return
588
Chui Tey5d2af632002-05-26 13:36:41 +0000589 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000590 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000591 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000592 if oid is None:
593 self.tkconsole.root.bell()
594 return
595 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000596 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000597 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000598 theme = idleConf.GetOption('main','Theme','name')
599 background = idleConf.GetHighlight(theme, 'normal')['background']
600 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000601 sc.frame.pack(expand=1, fill="both")
602 node = TreeNode(sc.canvas, None, item)
603 node.expand()
604 # XXX Should GC the remote tree when closing the window
605
David Scherer7aced172000-08-15 01:13:23 +0000606 gid = 0
607
608 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000609 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000610 filename = self.stuffsource(source)
611 self.execfile(filename, source)
612
613 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000614 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000615 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200616 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200617 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000618 try:
619 code = compile(source, filename, "exec")
620 except (OverflowError, SyntaxError):
621 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000622 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000623 print('*** Error in script or command!\n', file=tkerr)
624 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000625 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000626 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000627 else:
628 self.runcode(code)
629
630 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000631 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000632 filename = self.stuffsource(source)
633 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000634 self.save_warnings_filters = warnings.filters[:]
635 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000636 # at the moment, InteractiveInterpreter expects str
637 assert isinstance(source, str)
638 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000639 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000640 # try:
641 # source = source.encode(IOBinding.encoding)
642 # except UnicodeError:
643 # self.tkconsole.resetoutput()
644 # self.write("Unsupported characters in input\n")
645 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000646 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000647 # InteractiveInterpreter.runsource() calls its runcode() method,
648 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000649 return InteractiveInterpreter.runsource(self, source, filename)
650 finally:
651 if self.save_warnings_filters is not None:
652 warnings.filters[:] = self.save_warnings_filters
653 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000654
655 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000656 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000657 filename = "<pyshell#%d>" % self.gid
658 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000659 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000660 linecache.cache[filename] = len(source)+1, 0, lines, filename
661 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000662
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000663 def prepend_syspath(self, filename):
664 "Prepend sys.path with file's directory if not already included"
665 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000666 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000667 import sys as _sys
668 from os.path import dirname as _dirname
669 _dir = _dirname(_filename)
670 if not _dir in _sys.path:
671 _sys.path.insert(0, _dir)
672 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000673 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000674
David Scherer7aced172000-08-15 01:13:23 +0000675 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000676 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000677
678 Color the offending position instead of printing it and pointing at it
679 with a caret.
680
681 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000682 tkconsole = self.tkconsole
683 text = tkconsole.text
684 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000685 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700686 msg = getattr(value, 'msg', '') or value or "<no detail available>"
687 lineno = getattr(value, 'lineno', '') or 1
688 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000689 if offset == 0:
690 lineno += 1 #mark end of offending line
691 if lineno == 1:
692 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000693 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000694 pos = "iomark linestart + %d lines + %d chars" % \
695 (lineno-1, offset-1)
696 tkconsole.colorize_syntax_error(text, pos)
697 tkconsole.resetoutput()
698 self.write("SyntaxError: %s\n" % msg)
699 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000700
701 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000702 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000703 self.tkconsole.resetoutput()
704 self.checklinecache()
705 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000706 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
707 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000708
709 def checklinecache(self):
710 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000711 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000712 if key[:1] + key[-1:] != "<>":
713 del c[key]
714
Chui Tey5d2af632002-05-26 13:36:41 +0000715 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000716 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000717 # The code better not raise an exception!
718 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000719 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000720 return 0
721 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000722 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000723 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000724 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000725 return 1
726
David Scherer7aced172000-08-15 01:13:23 +0000727 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000728 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000729 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000730 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000731 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000732 if self.save_warnings_filters is not None:
733 warnings.filters[:] = self.save_warnings_filters
734 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000735 debugger = self.debugger
736 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000737 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000738 if not debugger and self.rpcclt is not None:
739 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
740 (code,), {})
741 elif debugger:
742 debugger.run(code, self.locals)
743 else:
744 exec(code, self.locals)
745 except SystemExit:
746 if not self.tkconsole.closing:
747 if tkMessageBox.askyesno(
748 "Exit?",
749 "Do you want to exit altogether?",
750 default="yes",
751 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000752 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000753 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000754 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000755 else:
756 raise
757 except:
758 if use_subprocess:
759 print("IDLE internal error in runcode()",
760 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000761 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000762 self.tkconsole.endexecuting()
763 else:
764 if self.tkconsole.canceled:
765 self.tkconsole.canceled = False
766 print("KeyboardInterrupt", file=self.tkconsole.stderr)
767 else:
768 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000769 finally:
770 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000771 try:
772 self.tkconsole.endexecuting()
773 except AttributeError: # shell may have closed
774 pass
David Scherer7aced172000-08-15 01:13:23 +0000775
776 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000777 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200778 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000779
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000780 def display_port_binding_error(self):
781 tkMessageBox.showerror(
782 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000783 "IDLE can't bind to a TCP/IP port, which is necessary to "
784 "communicate with its Python execution server. This might be "
785 "because no networking is installed on this computer. "
786 "Run IDLE with the -n command line switch to start without a "
787 "subprocess and refer to Help/IDLE Help 'Running without a "
788 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000789 master=self.tkconsole.text)
790
791 def display_no_subprocess_error(self):
792 tkMessageBox.showerror(
793 "Subprocess Startup Error",
794 "IDLE's subprocess didn't make connection. Either IDLE can't "
795 "start a subprocess or personal firewall software is blocking "
796 "the connection.",
797 master=self.tkconsole.text)
798
799 def display_executing_dialog(self):
800 tkMessageBox.showerror(
801 "Already executing",
802 "The Python Shell window is already executing a command; "
803 "please wait until it is finished.",
804 master=self.tkconsole.text)
805
806
David Scherer7aced172000-08-15 01:13:23 +0000807class PyShell(OutputWindow):
808
Terry Jan Reedy32622232013-03-30 18:32:19 -0400809 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000810
811 # Override classes
812 ColorDelegator = ModifiedColorDelegator
813 UndoDelegator = ModifiedUndoDelegator
814
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000815 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000816 menu_specs = [
817 ("file", "_File"),
818 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000819 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000820 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000821 ("windows", "_Windows"),
822 ("help", "_Help"),
823 ]
David Scherer7aced172000-08-15 01:13:23 +0000824
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000825 if macosxSupport.runningAsOSXApp():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000826 menu_specs[-2] = ("windows", "_Window")
827
828
David Scherer7aced172000-08-15 01:13:23 +0000829 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000830 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000831
832 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000833 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000834 ms = self.menu_specs
835 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000836 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000837 self.interp = ModifiedInterpreter(self)
838 if flist is None:
839 root = Tk()
840 fixwordbreaks(root)
841 root.withdraw()
842 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000843 #
David Scherer7aced172000-08-15 01:13:23 +0000844 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000845 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000846## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
847 self.usetabs = True
848 # indentwidth must be 8 when using tabs. See note in EditorWindow:
849 self.indentwidth = 8
850 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000851 #
David Scherer7aced172000-08-15 01:13:23 +0000852 text = self.text
853 text.configure(wrap="char")
854 text.bind("<<newline-and-indent>>", self.enter_callback)
855 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
856 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000857 text.bind("<<end-of-file>>", self.eof_callback)
858 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000859 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000860 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000861 if use_subprocess:
862 text.bind("<<view-restart>>", self.view_restart_mark)
863 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000864 #
David Scherer7aced172000-08-15 01:13:23 +0000865 self.save_stdout = sys.stdout
866 self.save_stderr = sys.stderr
867 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000868 from idlelib import IOBinding
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200869 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
870 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
871 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
872 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000873 if not use_subprocess:
874 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000875 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200876 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000877 try:
878 # page help() text to shell.
879 import pydoc # import must be done here to capture i/o rebinding.
880 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
881 pydoc.pager = pydoc.plainpager
882 except:
883 sys.stderr = sys.__stderr__
884 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000885 #
David Scherer7aced172000-08-15 01:13:23 +0000886 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000887 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000888 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000889
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000890 def get_standard_extension_names(self):
891 return idleConf.GetExtensions(shell_only=True)
892
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000893 reading = False
894 executing = False
895 canceled = False
896 endoffile = False
897 closing = False
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500898 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000899
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000900 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000901 global warning_stream
902 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000903
904 def get_warning_stream(self):
905 return warning_stream
906
David Scherer7aced172000-08-15 01:13:23 +0000907 def toggle_debugger(self, event=None):
908 if self.executing:
909 tkMessageBox.showerror("Don't debug now",
910 "You can only toggle the debugger when idle",
911 master=self.text)
912 self.set_debugger_indicator()
913 return "break"
914 else:
915 db = self.interp.getdebugger()
916 if db:
917 self.close_debugger()
918 else:
919 self.open_debugger()
920
921 def set_debugger_indicator(self):
922 db = self.interp.getdebugger()
923 self.setvar("<<toggle-debugger>>", not not db)
924
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000925 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000926 pass # All we need is the variable
927
928 def close_debugger(self):
929 db = self.interp.getdebugger()
930 if db:
931 self.interp.setdebugger(None)
932 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000933 if self.interp.rpcclt:
934 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000935 self.resetoutput()
936 self.console.write("[DEBUG OFF]\n")
937 sys.ps1 = ">>> "
938 self.showprompt()
939 self.set_debugger_indicator()
940
941 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000942 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000943 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
944 self)
945 else:
946 dbg_gui = Debugger.Debugger(self)
947 self.interp.setdebugger(dbg_gui)
948 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000949 sys.ps1 = "[DEBUG ON]\n>>> "
950 self.showprompt()
951 self.set_debugger_indicator()
952
David Scherer7aced172000-08-15 01:13:23 +0000953 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000954 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000955 self.resetoutput()
956 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000957
958 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000959 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000960 self.executing = 0
961 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000962 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000963
964 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000965 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000966 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000967 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000968 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000969 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000970 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000971 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000972 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000973 return "cancel"
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500974 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000975 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000976 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000977 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000978
979 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000980 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000981 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000982 if use_subprocess:
983 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000984 # Restore std streams
985 sys.stdout = self.save_stdout
986 sys.stderr = self.save_stderr
987 sys.stdin = self.save_stdin
988 # Break cycles
989 self.interp = None
990 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000991 self.flist.pyshell = None
992 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000993 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000994
995 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000996 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000997 return True
David Scherer7aced172000-08-15 01:13:23 +0000998
999 def short_title(self):
1000 return self.shell_title
1001
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001002 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001003 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001004
David Scherer7aced172000-08-15 01:13:23 +00001005 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001006 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001007 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001008 if use_subprocess:
1009 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001010 client = self.interp.start_subprocess()
1011 if not client:
1012 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001013 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001014 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001015 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001016 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001017 "and will be removed in a later version. See Help/IDLE Help\n" +
1018 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001019 sys.displayhook = rpc.displayhook
1020
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001021 self.write("Python %s on %s\n%s\n%s" %
1022 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001023 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001024 import tkinter
1025 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001026 return True
David Scherer7aced172000-08-15 01:13:23 +00001027
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001028 def stop_readline(self):
1029 if not self.reading: # no nested mainloop to exit.
1030 return
1031 self._stop_readline_flag = True
1032 self.top.quit()
1033
David Scherer7aced172000-08-15 01:13:23 +00001034 def readline(self):
1035 save = self.reading
1036 try:
1037 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001038 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001039 finally:
1040 self.reading = save
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001041 if self._stop_readline_flag:
1042 self._stop_readline_flag = False
1043 return ""
David Scherer7aced172000-08-15 01:13:23 +00001044 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001045 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1046 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001047 self.resetoutput()
1048 if self.canceled:
1049 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001050 if not use_subprocess:
1051 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001052 if self.endoffile:
1053 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001054 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001055 return line
1056
1057 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001058 return True
David Scherer7aced172000-08-15 01:13:23 +00001059
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001060 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001061 try:
1062 if self.text.compare("sel.first", "!=", "sel.last"):
1063 return # Active selection -- always use default binding
1064 except:
1065 pass
1066 if not (self.executing or self.reading):
1067 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001068 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001069 self.showprompt()
1070 return "break"
1071 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001072 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001073 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001074 if self.interp.getdebugger():
1075 self.interp.restart_subprocess()
1076 else:
1077 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001078 if self.reading:
1079 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001080 return "break"
1081
1082 def eof_callback(self, event):
1083 if self.executing and not self.reading:
1084 return # Let the default binding (delete next char) take over
1085 if not (self.text.compare("iomark", "==", "insert") and
1086 self.text.compare("insert", "==", "end-1c")):
1087 return # Let the default binding (delete next char) take over
1088 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001089 self.resetoutput()
1090 self.close()
1091 else:
1092 self.canceled = 0
1093 self.endoffile = 1
1094 self.top.quit()
1095 return "break"
1096
David Scherer7aced172000-08-15 01:13:23 +00001097 def linefeed_callback(self, event):
1098 # Insert a linefeed without entering anything (still autoindented)
1099 if self.reading:
1100 self.text.insert("insert", "\n")
1101 self.text.see("insert")
1102 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001103 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001104 return "break"
1105
1106 def enter_callback(self, event):
1107 if self.executing and not self.reading:
1108 return # Let the default binding (insert '\n') take over
1109 # If some text is selected, recall the selection
1110 # (but only if this before the I/O mark)
1111 try:
1112 sel = self.text.get("sel.first", "sel.last")
1113 if sel:
1114 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001115 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001116 return "break"
1117 except:
1118 pass
1119 # If we're strictly before the line containing iomark, recall
1120 # the current line, less a leading prompt, less leading or
1121 # trailing whitespace
1122 if self.text.compare("insert", "<", "iomark linestart"):
1123 # Check if there's a relevant stdin range -- if so, use it
1124 prev = self.text.tag_prevrange("stdin", "insert")
1125 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001126 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001127 return "break"
1128 next = self.text.tag_nextrange("stdin", "insert")
1129 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001130 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001131 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001132 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001133 indices = self.text.tag_nextrange("console", "insert linestart")
1134 if indices and \
1135 self.text.compare(indices[0], "<=", "insert linestart"):
1136 self.recall(self.text.get(indices[1], "insert lineend"), event)
1137 else:
1138 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001139 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001140 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001141 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001142 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001143 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001144 # If we're in the current input and there's only whitespace
1145 # beyond the cursor, erase that whitespace first
1146 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001147 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001148 self.text.delete("insert", "end-1c")
1149 # If we're in the current input before its last line,
1150 # insert a newline right at the insert point
1151 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001152 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001153 return "break"
1154 # We're in the last line; append a newline and submit it
1155 self.text.mark_set("insert", "end-1c")
1156 if self.reading:
1157 self.text.insert("insert", "\n")
1158 self.text.see("insert")
1159 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001160 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001161 self.text.tag_add("stdin", "iomark", "end-1c")
1162 self.text.update_idletasks()
1163 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001164 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001165 else:
1166 self.runit()
1167 return "break"
1168
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001169 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001170 # remove leading and trailing empty or whitespace lines
1171 s = re.sub(r'^\s*\n', '' , s)
1172 s = re.sub(r'\n\s*$', '', s)
1173 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001174 self.text.undo_block_start()
1175 try:
1176 self.text.tag_remove("sel", "1.0", "end")
1177 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001178 prefix = self.text.get("insert linestart", "insert")
1179 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001180 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001181 prefix = self.text.get("insert linestart", "insert")
1182 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001183 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001184 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1185 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001186 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001187 if line.startswith(orig_base_indent):
1188 # replace orig base indentation with new indentation
1189 line = new_base_indent + line[len(orig_base_indent):]
1190 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001191 finally:
1192 self.text.see("insert")
1193 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001194
1195 def runit(self):
1196 line = self.text.get("iomark", "end-1c")
1197 # Strip off last newline and surrounding whitespace.
1198 # (To allow you to hit return twice to end a statement.)
1199 i = len(line)
1200 while i > 0 and line[i-1] in " \t":
1201 i = i-1
1202 if i > 0 and line[i-1] == "\n":
1203 i = i-1
1204 while i > 0 and line[i-1] in " \t":
1205 i = i-1
1206 line = line[:i]
1207 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001208
David Scherer7aced172000-08-15 01:13:23 +00001209 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001210 if self.interp.rpcclt:
1211 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001212 try:
1213 sys.last_traceback
1214 except:
1215 tkMessageBox.showerror("No stack trace",
1216 "There is no stack trace yet.\n"
1217 "(sys.last_traceback is not defined)",
1218 master=self.text)
1219 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001220 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001221 sv = StackBrowser(self.root, self.flist)
1222
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001223 def view_restart_mark(self, event=None):
1224 self.text.see("iomark")
1225 self.text.see("restart")
1226
1227 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001228 "Callback for Run/Restart Shell Cntl-F6"
1229 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001230
David Scherer7aced172000-08-15 01:13:23 +00001231 def showprompt(self):
1232 self.resetoutput()
1233 try:
1234 s = str(sys.ps1)
1235 except:
1236 s = ""
1237 self.console.write(s)
1238 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001239 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001240 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001241
1242 def resetoutput(self):
1243 source = self.text.get("iomark", "end-1c")
1244 if self.history:
1245 self.history.history_store(source)
1246 if self.text.get("end-2c") != "\n":
1247 self.text.insert("end-1c", "\n")
1248 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001249 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001250
1251 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001252 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1253 # Tk doesn't support outputting non-BMP characters
1254 # Let's assume what printed string is not very long,
1255 # find first non-BMP character and construct informative
1256 # UnicodeEncodeError exception.
1257 for start, char in enumerate(s):
1258 if char > '\uffff':
1259 break
1260 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1261 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001262 try:
1263 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001264 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001265 self.text.mark_gravity("iomark", "left")
1266 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001267 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1268 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001269 if self.canceled:
1270 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001271 if not use_subprocess:
1272 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001273 return count
David Scherer7aced172000-08-15 01:13:23 +00001274
Andrew Svetlovd1837672012-11-01 22:41:19 +02001275 def rmenu_check_cut(self):
1276 try:
1277 if self.text.compare('sel.first', '<', 'iomark'):
1278 return 'disabled'
1279 except TclError: # no selection, so the index 'sel.first' doesn't exist
1280 return 'disabled'
1281 return super().rmenu_check_cut()
1282
1283 def rmenu_check_paste(self):
1284 if self.text.compare('insert','<','iomark'):
1285 return 'disabled'
1286 return super().rmenu_check_paste()
1287
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001288class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001289
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001290 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001291 self.shell = shell
1292 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001293 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001294
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001295 @property
1296 def encoding(self):
1297 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001298
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001299 @property
1300 def name(self):
1301 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001302
1303 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001304 return True
David Scherer7aced172000-08-15 01:13:23 +00001305
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001306
1307class PseudoOutputFile(PseudoFile):
1308
1309 def writable(self):
1310 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001311
1312 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001313 if self.closed:
1314 raise ValueError("write to closed file")
1315 if not isinstance(s, str):
1316 raise TypeError('must be str, not ' + type(s).__name__)
1317 return self.shell.write(s, self.tags)
1318
1319
1320class PseudoInputFile(PseudoFile):
1321
1322 def __init__(self, shell, tags, encoding=None):
1323 PseudoFile.__init__(self, shell, tags, encoding)
1324 self._line_buffer = ''
1325
1326 def readable(self):
1327 return True
1328
1329 def read(self, size=-1):
1330 if self.closed:
1331 raise ValueError("read from closed file")
1332 if size is None:
1333 size = -1
1334 elif not isinstance(size, int):
1335 raise TypeError('must be int, not ' + type(size).__name__)
1336 result = self._line_buffer
1337 self._line_buffer = ''
1338 if size < 0:
1339 while True:
1340 line = self.shell.readline()
1341 if not line: break
1342 result += line
1343 else:
1344 while len(result) < size:
1345 line = self.shell.readline()
1346 if not line: break
1347 result += line
1348 self._line_buffer = result[size:]
1349 result = result[:size]
1350 return result
1351
1352 def readline(self, size=-1):
1353 if self.closed:
1354 raise ValueError("read from closed file")
1355 if size is None:
1356 size = -1
1357 elif not isinstance(size, int):
1358 raise TypeError('must be int, not ' + type(size).__name__)
1359 line = self._line_buffer or self.shell.readline()
1360 if size < 0:
1361 size = len(line)
1362 self._line_buffer = line[size:]
1363 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001364
Roger Serwy1eafd102013-04-11 19:16:44 -05001365 def close(self):
1366 self.shell.close()
1367
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368
David Scherer7aced172000-08-15 01:13:23 +00001369usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001370
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001371USAGE: idle [-deins] [-t title] [file]*
1372 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1373 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001374
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001376 -n run IDLE without a subprocess (DEPRECATED,
1377 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001378
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001380
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381 -e open an edit window
1382 -i open a shell window
1383
1384The following options imply -i and will open a shell:
1385
1386 -c cmd run the command in a shell, or
1387 -r file run script from file
1388
1389 -d enable the debugger
1390 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1391 -t title set title of shell window
1392
1393A default edit window will be bypassed when -c, -r, or - are used.
1394
1395[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1396
1397Examples:
1398
1399idle
1400 Open an edit window or shell depending on IDLE's configuration.
1401
1402idle foo.py foobar.py
1403 Edit the files, also open a shell if configured to start with shell.
1404
1405idle -est "Baz" foo.py
1406 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1407 window with the title "Baz".
1408
Neal Norwitz752abd02008-05-13 04:55:24 +00001409idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001410 Open a shell window and run the command, passing "-c" in sys.argv[0]
1411 and "foo" in sys.argv[1].
1412
1413idle -d -s -r foo.py "Hello World"
1414 Open a shell window, run a startup script, enable the debugger, and
1415 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1416 sys.argv[1].
1417
Neal Norwitz752abd02008-05-13 04:55:24 +00001418echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1420 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001421"""
1422
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001423def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001425
Victor Stinnerb28a3752013-06-25 00:17:37 +02001426 warnings.showwarning = idle_showwarning
1427 warnings.formatwarning = idle_formatwarning
1428
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001429 use_subprocess = True
Roger Serwyc35151c2013-03-31 23:28:55 -05001430 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 enable_edit = False
1432 debug = False
1433 cmd = None
1434 script = None
1435 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001436 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001437 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001438 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001439 sys.stderr.write("Error: %s\n" % str(msg))
1440 sys.stderr.write(usage_msg)
1441 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001442 for o, a in opts:
1443 if o == '-c':
1444 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001445 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001446 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001447 debug = True
1448 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001449 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001450 enable_edit = True
1451 if o == '-h':
1452 sys.stdout.write(usage_msg)
1453 sys.exit()
1454 if o == '-i':
1455 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001456 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001457 print(" Warning: running IDLE without a subprocess is deprecated.",
1458 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001459 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001460 if o == '-r':
1461 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001462 if os.path.isfile(script):
1463 pass
1464 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001465 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001466 sys.exit()
1467 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001468 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001469 startup = True
1470 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001471 if o == '-t':
1472 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001473 enable_shell = True
1474 if args and args[0] == '-':
1475 cmd = sys.stdin.read()
1476 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001477 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001478 for i in range(len(sys.path)):
1479 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 if args and args[0] == '-':
1481 sys.argv = [''] + args[1:]
1482 elif cmd:
1483 sys.argv = ['-c'] + args
1484 elif script:
1485 sys.argv = [script] + args
1486 elif args:
1487 enable_edit = True
1488 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001489 for filename in args:
1490 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001491 for dir in pathx:
1492 dir = os.path.abspath(dir)
1493 if not dir in sys.path:
1494 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001495 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001496 dir = os.getcwd()
1497 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001498 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001499 # check the IDLE settings configuration (but command line overrides)
1500 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001501 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001502 enable_edit = enable_edit or edit_start
Roger Serwyc35151c2013-03-31 23:28:55 -05001503 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001504 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001505 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001506
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001507 fixwordbreaks(root)
1508 root.withdraw()
1509 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001510 macosxSupport.setupApp(root, flist)
1511
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001512 if enable_edit:
1513 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001514 for filename in args[:]:
1515 if flist.open(filename) is None:
1516 # filename is a directory actually, disconsider it
1517 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001518 if not args:
1519 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001520 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001521 shell = flist.open_shell()
1522 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001523 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001524
1525 if macosxSupport.runningAsOSXApp() and flist.dict:
1526 # On OSX: when the user has double-clicked on a file that causes
1527 # IDLE to be launched the shell window will open just in front of
1528 # the file she wants to see. Lower the interpreter window when
1529 # there are open files.
1530 shell.top.lower()
1531
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001532 shell = flist.pyshell
1533 # handle remaining options:
1534 if debug:
1535 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001536 if startup:
1537 filename = os.environ.get("IDLESTARTUP") or \
1538 os.environ.get("PYTHONSTARTUP")
1539 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001540 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001541 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001542 shell.interp.runcommand("""if 1:
1543 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001544 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001545 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001546 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001547 if cmd:
1548 shell.interp.execsource(cmd)
1549 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001550 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001551 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001552
Ned Deily4ce92b22011-01-15 04:37:12 +00001553 # Check for problematic OS X Tk versions and print a warning message
1554 # in the IDLE shell window; this is less intrusive than always opening
1555 # a separate window.
1556 tkversionwarning = macosxSupport.tkVersionWarning(root)
1557 if tkversionwarning:
1558 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1559
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001560 while flist.inversedict: # keep IDLE running while files are open.
1561 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001562 root.destroy()
1563
David Scherer7aced172000-08-15 01:13:23 +00001564if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001565 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001566 main()