blob: b1ef4ca8c42723f201e73f1cc6894333d99e3b5f [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.
Chui Tey5d2af632002-05-26 13:36:41 +000064 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000065 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000066 """Format warnings the IDLE way"""
67 s = "\nWarning (from warnings module):\n"
68 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000069 if line is None:
70 line = linecache.getline(filename, lineno)
71 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000072 if line:
73 s += " %s\n" % line
74 s += "%s: %s\n>>> " % (category.__name__, message)
75 return s
76 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000077
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000078def extended_linecache_checkcache(filename=None,
79 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000080 """Extend linecache.checkcache to preserve the <pyshell#...> entries
81
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000082 Rather than repeating the linecache code, patch it to save the
83 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000084 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000085
86 orig_checkcache is bound at definition time to the original
87 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000088 """
David Scherer7aced172000-08-15 01:13:23 +000089 cache = linecache.cache
90 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000091 for key in list(cache):
92 if key[:1] + key[-1:] == '<>':
93 save[key] = cache.pop(key)
94 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000095 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000096
Kurt B. Kaiser81885592002-11-29 22:10:53 +000097# Patch linecache.checkcache():
98linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000099
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000100
David Scherer7aced172000-08-15 01:13:23 +0000101class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000102 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103
David Scherer7aced172000-08-15 01:13:23 +0000104 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000106 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000109 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
110
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000111 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
112 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000113 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000114 def filename_changed_hook(old_hook=self.io.filename_change_hook,
115 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000116 self.restore_file_breaks()
117 old_hook()
118 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500119 if self.io.filename:
120 self.restore_file_breaks()
Chui Teya2adb0f2002-11-04 22:14:54 +0000121
Andrew Svetlovd1837672012-11-01 22:41:19 +0200122 rmenu_specs = [
123 ("Cut", "<<cut>>", "rmenu_check_cut"),
124 ("Copy", "<<copy>>", "rmenu_check_copy"),
125 ("Paste", "<<paste>>", "rmenu_check_paste"),
126 (None, None, None),
127 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
128 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
129 ]
David Scherer7aced172000-08-15 01:13:23 +0000130
Chui Teya2adb0f2002-11-04 22:14:54 +0000131 def set_breakpoint(self, lineno):
132 text = self.text
133 filename = self.io.filename
134 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
135 try:
136 i = self.breakpoints.index(lineno)
137 except ValueError: # only add if missing, i.e. do once
138 self.breakpoints.append(lineno)
139 try: # update the subprocess debugger
140 debug = self.flist.pyshell.interp.debugger
141 debug.set_breakpoint_here(filename, lineno)
142 except: # but debugger may not be active right now....
143 pass
144
David Scherer7aced172000-08-15 01:13:23 +0000145 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000146 text = self.text
147 filename = self.io.filename
148 if not filename:
149 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000150 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000151 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000152 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000153
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000154 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000155 text = self.text
156 filename = self.io.filename
157 if not filename:
158 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000159 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000160 lineno = int(float(text.index("insert")))
161 try:
162 self.breakpoints.remove(lineno)
163 except:
164 pass
165 text.tag_remove("BREAK", "insert linestart",\
166 "insert lineend +1char")
167 try:
168 debug = self.flist.pyshell.interp.debugger
169 debug.clear_breakpoint_here(filename, lineno)
170 except:
171 pass
172
173 def clear_file_breaks(self):
174 if self.breakpoints:
175 text = self.text
176 filename = self.io.filename
177 if not filename:
178 text.bell()
179 return
180 self.breakpoints = []
181 text.tag_remove("BREAK", "1.0", END)
182 try:
183 debug = self.flist.pyshell.interp.debugger
184 debug.clear_file_breaks(filename)
185 except:
186 pass
187
Chui Teya2adb0f2002-11-04 22:14:54 +0000188 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000189 "Save breakpoints when file is saved"
190 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
191 # be run. The breaks are saved at that time. If we introduce
192 # a temporary file save feature the save breaks functionality
193 # needs to be re-verified, since the breaks at the time the
194 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000195 # permanent save of the file. Currently, a break introduced
196 # after a save will be effective, but not persistent.
197 # This is necessary to keep the saved breaks synched with the
198 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000199 #
200 # Breakpoints are set as tagged ranges in the text. Certain
201 # kinds of edits cause these ranges to be deleted: Inserting
202 # or deleting a line just before a breakpoint, and certain
203 # deletions prior to a breakpoint. These issues need to be
204 # investigated and understood. It's not clear if they are
205 # Tk issues or IDLE issues, or whether they can actually
206 # be fixed. Since a modified file has to be saved before it is
207 # run, and since self.breakpoints (from which the subprocess
208 # debugger is loaded) is updated during the save, the visible
209 # breaks stay synched with the subprocess even if one of these
210 # unexpected breakpoint deletions occurs.
211 breaks = self.breakpoints
212 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000213 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200214 with open(self.breakpointPath, "r") as fp:
215 lines = fp.readlines()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200216 except OSError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000217 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800218 try:
219 with open(self.breakpointPath, "w") as new_file:
220 for line in lines:
221 if not line.startswith(filename + '='):
222 new_file.write(line)
223 self.update_breakpoints()
224 breaks = self.breakpoints
225 if breaks:
226 new_file.write(filename + '=' + str(breaks) + '\n')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200227 except OSError as err:
Ned Deilyf505b742011-12-14 14:58:24 -0800228 if not getattr(self.root, "breakpoint_error_displayed", False):
229 self.root.breakpoint_error_displayed = True
230 tkMessageBox.showerror(title='IDLE Error',
231 message='Unable to update breakpoint list:\n%s'
232 % str(err),
233 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000234
235 def restore_file_breaks(self):
236 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500237 if self.io is None:
238 # can happen if IDLE closes due to the .update() call
239 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 filename = self.io.filename
241 if filename is None:
242 return
Chui Tey69371d62002-11-04 23:39:45 +0000243 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200244 with open(self.breakpointPath, "r") as fp:
245 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000246 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000248 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000249 for breakpoint_linenumber in breakpoint_linenumbers:
250 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000251
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000252 def update_breakpoints(self):
253 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000254 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000255 ranges = text.tag_ranges("BREAK")
256 linenumber_list = self.ranges_to_linenumbers(ranges)
257 self.breakpoints = linenumber_list
258
259 def ranges_to_linenumbers(self, ranges):
260 lines = []
261 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300262 lineno = int(float(ranges[index].string))
263 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000264 while lineno < end:
265 lines.append(lineno)
266 lineno += 1
267 return lines
268
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000269# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000270# def saved_change_hook(self):
271# "Extend base method - clear breaks if module is modified"
272# if not self.get_saved():
273# self.clear_file_breaks()
274# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000275
276 def _close(self):
277 "Extend base method - clear breaks when module is closed"
278 self.clear_file_breaks()
279 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000280
David Scherer7aced172000-08-15 01:13:23 +0000281
282class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000283 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000284
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000285 # override FileList's class variable, instances return PyShellEditorWindow
286 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000287 EditorWindow = PyShellEditorWindow
288
289 pyshell = None
290
291 def open_shell(self, event=None):
292 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000293 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000294 else:
295 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000296 if self.pyshell:
297 if not self.pyshell.begin():
298 return None
David Scherer7aced172000-08-15 01:13:23 +0000299 return self.pyshell
300
301
302class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000303 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000304
Steven M. Gavab77d3432002-03-02 07:16:21 +0000305 def __init__(self):
306 ColorDelegator.__init__(self)
307 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000308
309 def recolorize_main(self):
310 self.tag_remove("TODO", "1.0", "iomark")
311 self.tag_add("SYNC", "1.0", "iomark")
312 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000313
Steven M. Gavab77d3432002-03-02 07:16:21 +0000314 def LoadTagDefs(self):
315 ColorDelegator.LoadTagDefs(self)
316 theme = idleConf.GetOption('main','Theme','name')
317 self.tagdefs.update({
318 "stdin": {'background':None,'foreground':None},
319 "stdout": idleConf.GetHighlight(theme, "stdout"),
320 "stderr": idleConf.GetHighlight(theme, "stderr"),
321 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000322 })
David Scherer7aced172000-08-15 01:13:23 +0000323
Ned Deily8b2a56b2012-05-31 09:17:29 -0700324 def removecolors(self):
325 # Don't remove shell color tags before "iomark"
326 for tag in self.tagdefs:
327 self.tag_remove(tag, "iomark", "end")
328
David Scherer7aced172000-08-15 01:13:23 +0000329class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000330 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000331
332 def insert(self, index, chars, tags=None):
333 try:
334 if self.delegate.compare(index, "<", "iomark"):
335 self.delegate.bell()
336 return
337 except TclError:
338 pass
339 UndoDelegator.insert(self, index, chars, tags)
340
341 def delete(self, index1, index2=None):
342 try:
343 if self.delegate.compare(index1, "<", "iomark"):
344 self.delegate.bell()
345 return
346 except TclError:
347 pass
348 UndoDelegator.delete(self, index1, index2)
349
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000350
351class MyRPCClient(rpc.RPCClient):
352
353 def handle_EOF(self):
354 "Override the base class - just re-raise EOFError"
355 raise EOFError
356
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000357
David Scherer7aced172000-08-15 01:13:23 +0000358class ModifiedInterpreter(InteractiveInterpreter):
359
360 def __init__(self, tkconsole):
361 self.tkconsole = tkconsole
362 locals = sys.modules['__main__'].__dict__
363 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000364 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000365 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000366 self.subprocess_arglist = None
367 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700368 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000369
Chui Tey5d2af632002-05-26 13:36:41 +0000370 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700371 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000372
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000373 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000374 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000375 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700376 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000377
Tony Lowndsf53dec22002-12-20 04:24:43 +0000378 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000379 assert (self.port!=0), (
380 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000381 w = ['-W' + s for s in sys.warnoptions]
382 # Maybe IDLE is installed and is being accessed via sys.path,
383 # or maybe it's not installed and the idle.py script is being
384 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000385 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
386 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000387 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000388 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000389 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000390 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700391 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000392
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000393 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000394 addr = (HOST, self.port)
395 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000396 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000397 time.sleep(i)
398 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000399 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000400 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200401 except OSError as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000402 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000403 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000404 self.display_port_binding_error()
405 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000406 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
407 self.port = self.rpcclt.listening_sock.getsockname()[1]
408 # if PORT was not 0, probably working with a remote execution server
409 if PORT != 0:
410 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
411 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
412 # on Windows since the implementation allows two active sockets on
413 # the same address!
414 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
415 socket.SO_REUSEADDR, 1)
416 self.spawn_subprocess()
417 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000418 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000419 self.rpcclt.listening_sock.settimeout(10)
420 try:
421 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000422 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000423 self.display_no_subprocess_error()
424 return None
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200425 self.rpcclt.register("console", self.tkconsole)
426 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000427 self.rpcclt.register("stdout", self.tkconsole.stdout)
428 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000429 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000430 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000431 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500432 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000433 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000434 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000435
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500436 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000437 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000438 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000439 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000440 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000441 debug = self.getdebugger()
442 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000443 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000444 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000445 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
446 except:
447 pass
448 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000449 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700450 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000451 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000452 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000453 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000454 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000455 try:
456 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000457 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000458 self.display_no_subprocess_error()
459 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500460 self.transfer_path(with_cwd=with_cwd)
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500461 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000462 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000463 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000464 if was_executing:
465 console.write('\n')
466 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000467 halfbar = ((int(console.width) - 16) // 2) * '='
468 console.write(halfbar + ' RESTART ' + halfbar)
469 console.text.mark_set("restart", "end-1c")
470 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000471 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000472 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000473 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000474 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000475 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000476 # reload remote debugger breakpoints for all PyShellEditWindows
477 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700478 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000479 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000480 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000481
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000482 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000483 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000484
485 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000486 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000487
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000488 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000489 try:
Ned Deily55f87572011-11-05 22:36:44 -0700490 self.rpcclt.listening_sock.close()
491 except AttributeError: # no socket
492 pass
493 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000494 self.rpcclt.close()
495 except AttributeError: # no socket
496 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700497 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000498 self.tkconsole.executing = False
499 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000500
Ned Deilye5cad232011-08-02 18:47:13 -0700501 def terminate_subprocess(self):
502 "Make sure subprocess is terminated"
503 try:
504 self.rpcsubproc.kill()
505 except OSError:
506 # process already terminated
507 return
508 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000509 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700510 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000511 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000512 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000513
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500514 def transfer_path(self, with_cwd=False):
515 if with_cwd: # Issue 13506
516 path = [''] # include Current Working Directory
517 path.extend(sys.path)
518 else:
519 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500520
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000521 self.runcommand("""if 1:
522 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000523 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000524 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500525 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000526
Chui Tey5d2af632002-05-26 13:36:41 +0000527 active_seq = None
528
529 def poll_subprocess(self):
530 clt = self.rpcclt
531 if clt is None:
532 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000533 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000534 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200535 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000536 # lost connection or subprocess terminated itself, restart
537 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000538 if self.tkconsole.closing:
539 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000540 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000541 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000542 if response:
543 self.tkconsole.resetoutput()
544 self.active_seq = None
545 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000546 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000547 if how == "OK":
548 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000549 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000550 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000551 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
552 self.remote_stack_viewer()
553 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000554 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000555 print(errmsg, what, file=sys.__stderr__)
556 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000557 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000558 try:
559 self.tkconsole.endexecuting()
560 except AttributeError: # shell may have closed
561 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000562 # Reschedule myself
563 if not self.tkconsole.closing:
564 self.tkconsole.text.after(self.tkconsole.pollinterval,
565 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000566
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000567 debugger = None
568
569 def setdebugger(self, debugger):
570 self.debugger = debugger
571
572 def getdebugger(self):
573 return self.debugger
574
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000575 def open_remote_stack_viewer(self):
576 """Initiate the remote stack viewer from a separate thread.
577
578 This method is called from the subprocess, and by returning from this
579 method we allow the subprocess to unblock. After a bit the shell
580 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000581 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000582 the RPC mechanism.
583
584 """
585 self.tkconsole.text.after(300, self.remote_stack_viewer)
586 return
587
Chui Tey5d2af632002-05-26 13:36:41 +0000588 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000589 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000590 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000591 if oid is None:
592 self.tkconsole.root.bell()
593 return
594 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000595 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000596 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000597 theme = idleConf.GetOption('main','Theme','name')
598 background = idleConf.GetHighlight(theme, 'normal')['background']
599 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000600 sc.frame.pack(expand=1, fill="both")
601 node = TreeNode(sc.canvas, None, item)
602 node.expand()
603 # XXX Should GC the remote tree when closing the window
604
David Scherer7aced172000-08-15 01:13:23 +0000605 gid = 0
606
607 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000608 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000609 filename = self.stuffsource(source)
610 self.execfile(filename, source)
611
612 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000613 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000614 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200615 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200616 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000617 try:
618 code = compile(source, filename, "exec")
619 except (OverflowError, SyntaxError):
620 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000621 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000622 print('*** Error in script or command!\n', file=tkerr)
623 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000624 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000625 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000626 else:
627 self.runcode(code)
628
629 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000630 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000631 filename = self.stuffsource(source)
632 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000633 self.save_warnings_filters = warnings.filters[:]
634 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000635 # at the moment, InteractiveInterpreter expects str
636 assert isinstance(source, str)
637 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000638 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000639 # try:
640 # source = source.encode(IOBinding.encoding)
641 # except UnicodeError:
642 # self.tkconsole.resetoutput()
643 # self.write("Unsupported characters in input\n")
644 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000645 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000646 # InteractiveInterpreter.runsource() calls its runcode() method,
647 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000648 return InteractiveInterpreter.runsource(self, source, filename)
649 finally:
650 if self.save_warnings_filters is not None:
651 warnings.filters[:] = self.save_warnings_filters
652 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000653
654 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000655 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000656 filename = "<pyshell#%d>" % self.gid
657 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000658 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000659 linecache.cache[filename] = len(source)+1, 0, lines, filename
660 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000661
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000662 def prepend_syspath(self, filename):
663 "Prepend sys.path with file's directory if not already included"
664 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000665 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000666 import sys as _sys
667 from os.path import dirname as _dirname
668 _dir = _dirname(_filename)
669 if not _dir in _sys.path:
670 _sys.path.insert(0, _dir)
671 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000672 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000673
David Scherer7aced172000-08-15 01:13:23 +0000674 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000675 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000676
677 Color the offending position instead of printing it and pointing at it
678 with a caret.
679
680 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000681 tkconsole = self.tkconsole
682 text = tkconsole.text
683 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000684 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700685 msg = getattr(value, 'msg', '') or value or "<no detail available>"
686 lineno = getattr(value, 'lineno', '') or 1
687 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000688 if offset == 0:
689 lineno += 1 #mark end of offending line
690 if lineno == 1:
691 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000692 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000693 pos = "iomark linestart + %d lines + %d chars" % \
694 (lineno-1, offset-1)
695 tkconsole.colorize_syntax_error(text, pos)
696 tkconsole.resetoutput()
697 self.write("SyntaxError: %s\n" % msg)
698 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000699
700 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000701 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000702 self.tkconsole.resetoutput()
703 self.checklinecache()
704 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000705 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
706 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000707
708 def checklinecache(self):
709 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000710 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000711 if key[:1] + key[-1:] != "<>":
712 del c[key]
713
Chui Tey5d2af632002-05-26 13:36:41 +0000714 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000715 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000716 # The code better not raise an exception!
717 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000718 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000719 return 0
720 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000721 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000722 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000723 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000724 return 1
725
David Scherer7aced172000-08-15 01:13:23 +0000726 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000727 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000728 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000729 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000730 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000731 if self.save_warnings_filters is not None:
732 warnings.filters[:] = self.save_warnings_filters
733 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000734 debugger = self.debugger
735 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000736 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000737 if not debugger and self.rpcclt is not None:
738 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
739 (code,), {})
740 elif debugger:
741 debugger.run(code, self.locals)
742 else:
743 exec(code, self.locals)
744 except SystemExit:
745 if not self.tkconsole.closing:
746 if tkMessageBox.askyesno(
747 "Exit?",
748 "Do you want to exit altogether?",
749 default="yes",
750 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000751 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000752 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000753 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000754 else:
755 raise
756 except:
757 if use_subprocess:
758 print("IDLE internal error in runcode()",
759 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000760 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000761 self.tkconsole.endexecuting()
762 else:
763 if self.tkconsole.canceled:
764 self.tkconsole.canceled = False
765 print("KeyboardInterrupt", file=self.tkconsole.stderr)
766 else:
767 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000768 finally:
769 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000770 try:
771 self.tkconsole.endexecuting()
772 except AttributeError: # shell may have closed
773 pass
David Scherer7aced172000-08-15 01:13:23 +0000774
775 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000776 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200777 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000778
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000779 def display_port_binding_error(self):
780 tkMessageBox.showerror(
781 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000782 "IDLE can't bind to a TCP/IP port, which is necessary to "
783 "communicate with its Python execution server. This might be "
784 "because no networking is installed on this computer. "
785 "Run IDLE with the -n command line switch to start without a "
786 "subprocess and refer to Help/IDLE Help 'Running without a "
787 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000788 master=self.tkconsole.text)
789
790 def display_no_subprocess_error(self):
791 tkMessageBox.showerror(
792 "Subprocess Startup Error",
793 "IDLE's subprocess didn't make connection. Either IDLE can't "
794 "start a subprocess or personal firewall software is blocking "
795 "the connection.",
796 master=self.tkconsole.text)
797
798 def display_executing_dialog(self):
799 tkMessageBox.showerror(
800 "Already executing",
801 "The Python Shell window is already executing a command; "
802 "please wait until it is finished.",
803 master=self.tkconsole.text)
804
805
David Scherer7aced172000-08-15 01:13:23 +0000806class PyShell(OutputWindow):
807
Terry Jan Reedy32622232013-03-30 18:32:19 -0400808 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000809
810 # Override classes
811 ColorDelegator = ModifiedColorDelegator
812 UndoDelegator = ModifiedUndoDelegator
813
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000814 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000815 menu_specs = [
816 ("file", "_File"),
817 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000818 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000819 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000820 ("windows", "_Windows"),
821 ("help", "_Help"),
822 ]
David Scherer7aced172000-08-15 01:13:23 +0000823
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000824 if macosxSupport.runningAsOSXApp():
825 del menu_specs[-3]
826 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. Kaiser8a78cad2007-12-13 03:38:16 +0000861 self.color = color = self.ColorDelegator()
862 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000863 if use_subprocess:
864 text.bind("<<view-restart>>", self.view_restart_mark)
865 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000866 #
David Scherer7aced172000-08-15 01:13:23 +0000867 self.save_stdout = sys.stdout
868 self.save_stderr = sys.stderr
869 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000870 from idlelib import IOBinding
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200871 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
872 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
873 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
874 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000875 if not use_subprocess:
876 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000877 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200878 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000879 try:
880 # page help() text to shell.
881 import pydoc # import must be done here to capture i/o rebinding.
882 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
883 pydoc.pager = pydoc.plainpager
884 except:
885 sys.stderr = sys.__stderr__
886 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000887 #
David Scherer7aced172000-08-15 01:13:23 +0000888 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000889 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000890 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000891
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000892 def get_standard_extension_names(self):
893 return idleConf.GetExtensions(shell_only=True)
894
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000895 reading = False
896 executing = False
897 canceled = False
898 endoffile = False
899 closing = False
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500900 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000901
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000902 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000903 global warning_stream
904 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000905
906 def get_warning_stream(self):
907 return warning_stream
908
David Scherer7aced172000-08-15 01:13:23 +0000909 def toggle_debugger(self, event=None):
910 if self.executing:
911 tkMessageBox.showerror("Don't debug now",
912 "You can only toggle the debugger when idle",
913 master=self.text)
914 self.set_debugger_indicator()
915 return "break"
916 else:
917 db = self.interp.getdebugger()
918 if db:
919 self.close_debugger()
920 else:
921 self.open_debugger()
922
923 def set_debugger_indicator(self):
924 db = self.interp.getdebugger()
925 self.setvar("<<toggle-debugger>>", not not db)
926
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000927 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000928 pass # All we need is the variable
929
930 def close_debugger(self):
931 db = self.interp.getdebugger()
932 if db:
933 self.interp.setdebugger(None)
934 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000935 if self.interp.rpcclt:
936 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000937 self.resetoutput()
938 self.console.write("[DEBUG OFF]\n")
939 sys.ps1 = ">>> "
940 self.showprompt()
941 self.set_debugger_indicator()
942
943 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000944 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000945 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
946 self)
947 else:
948 dbg_gui = Debugger.Debugger(self)
949 self.interp.setdebugger(dbg_gui)
950 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000951 sys.ps1 = "[DEBUG ON]\n>>> "
952 self.showprompt()
953 self.set_debugger_indicator()
954
David Scherer7aced172000-08-15 01:13:23 +0000955 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000956 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000957 self.resetoutput()
958 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000959
960 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000961 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000962 self.executing = 0
963 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000964 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000965
966 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000967 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000968 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000969 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000970 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000971 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000972 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000973 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000974 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000975 return "cancel"
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500976 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000977 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000978 self.closing = True
979 # Wait for poll_subprocess() rescheduling to stop
980 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000981
982 def close2(self):
983 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000984
985 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000986 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000987 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000988 if use_subprocess:
989 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000990 # Restore std streams
991 sys.stdout = self.save_stdout
992 sys.stderr = self.save_stderr
993 sys.stdin = self.save_stdin
994 # Break cycles
995 self.interp = None
996 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000997 self.flist.pyshell = None
998 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000999 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001000
1001 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001002 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001003 return True
David Scherer7aced172000-08-15 01:13:23 +00001004
1005 def short_title(self):
1006 return self.shell_title
1007
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001008 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001009 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001010
David Scherer7aced172000-08-15 01:13:23 +00001011 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001012 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001013 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001014 if use_subprocess:
1015 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001016 client = self.interp.start_subprocess()
1017 if not client:
1018 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001019 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001020 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001021 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001022 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001023 "and will be removed in a later version. See Help/IDLE Help\n" +
1024 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001025 sys.displayhook = rpc.displayhook
1026
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001027 self.write("Python %s on %s\n%s\n%s" %
1028 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001029 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001030 import tkinter
1031 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001032 return True
David Scherer7aced172000-08-15 01:13:23 +00001033
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001034 def stop_readline(self):
1035 if not self.reading: # no nested mainloop to exit.
1036 return
1037 self._stop_readline_flag = True
1038 self.top.quit()
1039
David Scherer7aced172000-08-15 01:13:23 +00001040 def readline(self):
1041 save = self.reading
1042 try:
1043 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001045 finally:
1046 self.reading = save
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001047 if self._stop_readline_flag:
1048 self._stop_readline_flag = False
1049 return ""
David Scherer7aced172000-08-15 01:13:23 +00001050 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001051 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1052 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001053 self.resetoutput()
1054 if self.canceled:
1055 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001056 if not use_subprocess:
1057 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001058 if self.endoffile:
1059 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001060 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001061 return line
1062
1063 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001064 return True
David Scherer7aced172000-08-15 01:13:23 +00001065
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001066 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001067 try:
1068 if self.text.compare("sel.first", "!=", "sel.last"):
1069 return # Active selection -- always use default binding
1070 except:
1071 pass
1072 if not (self.executing or self.reading):
1073 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001074 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001075 self.showprompt()
1076 return "break"
1077 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001078 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001079 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001080 if self.interp.getdebugger():
1081 self.interp.restart_subprocess()
1082 else:
1083 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001084 if self.reading:
1085 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001086 return "break"
1087
1088 def eof_callback(self, event):
1089 if self.executing and not self.reading:
1090 return # Let the default binding (delete next char) take over
1091 if not (self.text.compare("iomark", "==", "insert") and
1092 self.text.compare("insert", "==", "end-1c")):
1093 return # Let the default binding (delete next char) take over
1094 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001095 self.resetoutput()
1096 self.close()
1097 else:
1098 self.canceled = 0
1099 self.endoffile = 1
1100 self.top.quit()
1101 return "break"
1102
David Scherer7aced172000-08-15 01:13:23 +00001103 def linefeed_callback(self, event):
1104 # Insert a linefeed without entering anything (still autoindented)
1105 if self.reading:
1106 self.text.insert("insert", "\n")
1107 self.text.see("insert")
1108 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001109 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
1111
1112 def enter_callback(self, event):
1113 if self.executing and not self.reading:
1114 return # Let the default binding (insert '\n') take over
1115 # If some text is selected, recall the selection
1116 # (but only if this before the I/O mark)
1117 try:
1118 sel = self.text.get("sel.first", "sel.last")
1119 if sel:
1120 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001121 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001122 return "break"
1123 except:
1124 pass
1125 # If we're strictly before the line containing iomark, recall
1126 # the current line, less a leading prompt, less leading or
1127 # trailing whitespace
1128 if self.text.compare("insert", "<", "iomark linestart"):
1129 # Check if there's a relevant stdin range -- if so, use it
1130 prev = self.text.tag_prevrange("stdin", "insert")
1131 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001132 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001133 return "break"
1134 next = self.text.tag_nextrange("stdin", "insert")
1135 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001136 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001137 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001138 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001139 indices = self.text.tag_nextrange("console", "insert linestart")
1140 if indices and \
1141 self.text.compare(indices[0], "<=", "insert linestart"):
1142 self.recall(self.text.get(indices[1], "insert lineend"), event)
1143 else:
1144 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001145 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001146 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001147 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001148 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001149 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001150 # If we're in the current input and there's only whitespace
1151 # beyond the cursor, erase that whitespace first
1152 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001153 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001154 self.text.delete("insert", "end-1c")
1155 # If we're in the current input before its last line,
1156 # insert a newline right at the insert point
1157 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001158 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001159 return "break"
1160 # We're in the last line; append a newline and submit it
1161 self.text.mark_set("insert", "end-1c")
1162 if self.reading:
1163 self.text.insert("insert", "\n")
1164 self.text.see("insert")
1165 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001166 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001167 self.text.tag_add("stdin", "iomark", "end-1c")
1168 self.text.update_idletasks()
1169 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001170 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001171 else:
1172 self.runit()
1173 return "break"
1174
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001175 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001176 # remove leading and trailing empty or whitespace lines
1177 s = re.sub(r'^\s*\n', '' , s)
1178 s = re.sub(r'\n\s*$', '', s)
1179 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001180 self.text.undo_block_start()
1181 try:
1182 self.text.tag_remove("sel", "1.0", "end")
1183 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001184 prefix = self.text.get("insert linestart", "insert")
1185 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001186 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001187 prefix = self.text.get("insert linestart", "insert")
1188 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001189 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001190 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1191 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001192 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001193 if line.startswith(orig_base_indent):
1194 # replace orig base indentation with new indentation
1195 line = new_base_indent + line[len(orig_base_indent):]
1196 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001197 finally:
1198 self.text.see("insert")
1199 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001200
1201 def runit(self):
1202 line = self.text.get("iomark", "end-1c")
1203 # Strip off last newline and surrounding whitespace.
1204 # (To allow you to hit return twice to end a statement.)
1205 i = len(line)
1206 while i > 0 and line[i-1] in " \t":
1207 i = i-1
1208 if i > 0 and line[i-1] == "\n":
1209 i = i-1
1210 while i > 0 and line[i-1] in " \t":
1211 i = i-1
1212 line = line[:i]
1213 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001214
David Scherer7aced172000-08-15 01:13:23 +00001215 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001216 if self.interp.rpcclt:
1217 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001218 try:
1219 sys.last_traceback
1220 except:
1221 tkMessageBox.showerror("No stack trace",
1222 "There is no stack trace yet.\n"
1223 "(sys.last_traceback is not defined)",
1224 master=self.text)
1225 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001226 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001227 sv = StackBrowser(self.root, self.flist)
1228
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001229 def view_restart_mark(self, event=None):
1230 self.text.see("iomark")
1231 self.text.see("restart")
1232
1233 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001234 "Callback for Run/Restart Shell Cntl-F6"
1235 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001236
David Scherer7aced172000-08-15 01:13:23 +00001237 def showprompt(self):
1238 self.resetoutput()
1239 try:
1240 s = str(sys.ps1)
1241 except:
1242 s = ""
1243 self.console.write(s)
1244 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001245 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001246 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001247
1248 def resetoutput(self):
1249 source = self.text.get("iomark", "end-1c")
1250 if self.history:
1251 self.history.history_store(source)
1252 if self.text.get("end-2c") != "\n":
1253 self.text.insert("end-1c", "\n")
1254 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001255 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001256
1257 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001258 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1259 # Tk doesn't support outputting non-BMP characters
1260 # Let's assume what printed string is not very long,
1261 # find first non-BMP character and construct informative
1262 # UnicodeEncodeError exception.
1263 for start, char in enumerate(s):
1264 if char > '\uffff':
1265 break
1266 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1267 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001268 try:
1269 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001270 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001271 self.text.mark_gravity("iomark", "left")
1272 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001273 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1274 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001275 if self.canceled:
1276 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001277 if not use_subprocess:
1278 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001279 return count
David Scherer7aced172000-08-15 01:13:23 +00001280
Andrew Svetlovd1837672012-11-01 22:41:19 +02001281 def rmenu_check_cut(self):
1282 try:
1283 if self.text.compare('sel.first', '<', 'iomark'):
1284 return 'disabled'
1285 except TclError: # no selection, so the index 'sel.first' doesn't exist
1286 return 'disabled'
1287 return super().rmenu_check_cut()
1288
1289 def rmenu_check_paste(self):
1290 if self.text.compare('insert','<','iomark'):
1291 return 'disabled'
1292 return super().rmenu_check_paste()
1293
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001294class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001295
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001296 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001297 self.shell = shell
1298 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001299 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001300
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001301 @property
1302 def encoding(self):
1303 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001304
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001305 @property
1306 def name(self):
1307 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001308
1309 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001310 return True
David Scherer7aced172000-08-15 01:13:23 +00001311
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001312
1313class PseudoOutputFile(PseudoFile):
1314
1315 def writable(self):
1316 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001317
1318 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001319 if self.closed:
1320 raise ValueError("write to closed file")
1321 if not isinstance(s, str):
1322 raise TypeError('must be str, not ' + type(s).__name__)
1323 return self.shell.write(s, self.tags)
1324
1325
1326class PseudoInputFile(PseudoFile):
1327
1328 def __init__(self, shell, tags, encoding=None):
1329 PseudoFile.__init__(self, shell, tags, encoding)
1330 self._line_buffer = ''
1331
1332 def readable(self):
1333 return True
1334
1335 def read(self, size=-1):
1336 if self.closed:
1337 raise ValueError("read from closed file")
1338 if size is None:
1339 size = -1
1340 elif not isinstance(size, int):
1341 raise TypeError('must be int, not ' + type(size).__name__)
1342 result = self._line_buffer
1343 self._line_buffer = ''
1344 if size < 0:
1345 while True:
1346 line = self.shell.readline()
1347 if not line: break
1348 result += line
1349 else:
1350 while len(result) < size:
1351 line = self.shell.readline()
1352 if not line: break
1353 result += line
1354 self._line_buffer = result[size:]
1355 result = result[:size]
1356 return result
1357
1358 def readline(self, size=-1):
1359 if self.closed:
1360 raise ValueError("read from closed file")
1361 if size is None:
1362 size = -1
1363 elif not isinstance(size, int):
1364 raise TypeError('must be int, not ' + type(size).__name__)
1365 line = self._line_buffer or self.shell.readline()
1366 if size < 0:
1367 size = len(line)
1368 self._line_buffer = line[size:]
1369 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001370
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001371
David Scherer7aced172000-08-15 01:13:23 +00001372usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001373
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001374USAGE: idle [-deins] [-t title] [file]*
1375 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1376 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001377
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001379 -n run IDLE without a subprocess (DEPRECATED,
1380 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001381
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001383
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001384 -e open an edit window
1385 -i open a shell window
1386
1387The following options imply -i and will open a shell:
1388
1389 -c cmd run the command in a shell, or
1390 -r file run script from file
1391
1392 -d enable the debugger
1393 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1394 -t title set title of shell window
1395
1396A default edit window will be bypassed when -c, -r, or - are used.
1397
1398[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1399
1400Examples:
1401
1402idle
1403 Open an edit window or shell depending on IDLE's configuration.
1404
1405idle foo.py foobar.py
1406 Edit the files, also open a shell if configured to start with shell.
1407
1408idle -est "Baz" foo.py
1409 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1410 window with the title "Baz".
1411
Neal Norwitz752abd02008-05-13 04:55:24 +00001412idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 Open a shell window and run the command, passing "-c" in sys.argv[0]
1414 and "foo" in sys.argv[1].
1415
1416idle -d -s -r foo.py "Hello World"
1417 Open a shell window, run a startup script, enable the debugger, and
1418 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1419 sys.argv[1].
1420
Neal Norwitz752abd02008-05-13 04:55:24 +00001421echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1423 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001424"""
1425
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001426def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001427 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001428
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()