blob: d8a5cd24331bc2b829ca4da05e9c3a1506a563d2 [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
Roger Serwy036e8492013-06-11 22:13:17 -0500370 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000371 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700372 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000373
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000374 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000375 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000376 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700377 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000378
Tony Lowndsf53dec22002-12-20 04:24:43 +0000379 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000380 assert (self.port!=0), (
381 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000382 w = ['-W' + s for s in sys.warnoptions]
383 # Maybe IDLE is installed and is being accessed via sys.path,
384 # or maybe it's not installed and the idle.py script is being
385 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000386 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
387 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000388 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000389 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000390 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000391 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700392 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000393
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000394 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000395 addr = (HOST, self.port)
396 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000397 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000398 time.sleep(i)
399 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000400 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000401 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200402 except OSError as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000403 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000404 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 self.display_port_binding_error()
406 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000407 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
408 self.port = self.rpcclt.listening_sock.getsockname()[1]
409 # if PORT was not 0, probably working with a remote execution server
410 if PORT != 0:
411 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
412 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
413 # on Windows since the implementation allows two active sockets on
414 # the same address!
415 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
416 socket.SO_REUSEADDR, 1)
417 self.spawn_subprocess()
418 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000419 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000420 self.rpcclt.listening_sock.settimeout(10)
421 try:
422 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000423 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000424 self.display_no_subprocess_error()
425 return None
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200426 self.rpcclt.register("console", self.tkconsole)
427 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000428 self.rpcclt.register("stdout", self.tkconsole.stdout)
429 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000430 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000431 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000432 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500433 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000434 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000435 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000436
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500437 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000438 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000439 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000440 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000441 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000442 debug = self.getdebugger()
443 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000444 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000445 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000446 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
447 except:
448 pass
449 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000450 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700451 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000452 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000453 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000454 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000455 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000456 try:
457 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000458 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000459 self.display_no_subprocess_error()
460 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500461 self.transfer_path(with_cwd=with_cwd)
Roger Serwy6b7a5ae2013-04-03 00:42:24 -0500462 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000463 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000464 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000465 if was_executing:
466 console.write('\n')
467 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000468 halfbar = ((int(console.width) - 16) // 2) * '='
469 console.write(halfbar + ' RESTART ' + halfbar)
470 console.text.mark_set("restart", "end-1c")
471 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000472 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000473 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000474 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000475 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000476 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000477 # reload remote debugger breakpoints for all PyShellEditWindows
478 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700479 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000480 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000481 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000482
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000483 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000485
486 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000487 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000488
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000489 def kill_subprocess(self):
Roger Serwy036e8492013-06-11 22:13:17 -0500490 if self._afterid is not None:
491 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000492 try:
Ned Deily55f87572011-11-05 22:36:44 -0700493 self.rpcclt.listening_sock.close()
494 except AttributeError: # no socket
495 pass
496 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000497 self.rpcclt.close()
498 except AttributeError: # no socket
499 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700500 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000501 self.tkconsole.executing = False
502 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000503
Ned Deilye5cad232011-08-02 18:47:13 -0700504 def terminate_subprocess(self):
505 "Make sure subprocess is terminated"
506 try:
507 self.rpcsubproc.kill()
508 except OSError:
509 # process already terminated
510 return
511 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000512 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700513 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000514 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000515 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000516
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500517 def transfer_path(self, with_cwd=False):
518 if with_cwd: # Issue 13506
519 path = [''] # include Current Working Directory
520 path.extend(sys.path)
521 else:
522 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500523
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000524 self.runcommand("""if 1:
525 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000526 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000527 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500528 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000529
Chui Tey5d2af632002-05-26 13:36:41 +0000530 active_seq = None
531
532 def poll_subprocess(self):
533 clt = self.rpcclt
534 if clt is None:
535 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000536 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000537 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200538 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000539 # lost connection or subprocess terminated itself, restart
540 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000541 if self.tkconsole.closing:
542 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000543 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000544 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000545 if response:
546 self.tkconsole.resetoutput()
547 self.active_seq = None
548 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000549 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000550 if how == "OK":
551 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000552 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000553 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000554 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
555 self.remote_stack_viewer()
556 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000557 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000558 print(errmsg, what, file=sys.__stderr__)
559 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000560 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000561 try:
562 self.tkconsole.endexecuting()
563 except AttributeError: # shell may have closed
564 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000565 # Reschedule myself
566 if not self.tkconsole.closing:
Roger Serwy036e8492013-06-11 22:13:17 -0500567 self._afterid = self.tkconsole.text.after(
568 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000569
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000570 debugger = None
571
572 def setdebugger(self, debugger):
573 self.debugger = debugger
574
575 def getdebugger(self):
576 return self.debugger
577
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000578 def open_remote_stack_viewer(self):
579 """Initiate the remote stack viewer from a separate thread.
580
581 This method is called from the subprocess, and by returning from this
582 method we allow the subprocess to unblock. After a bit the shell
583 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000584 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000585 the RPC mechanism.
586
587 """
588 self.tkconsole.text.after(300, self.remote_stack_viewer)
589 return
590
Chui Tey5d2af632002-05-26 13:36:41 +0000591 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000592 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000593 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000594 if oid is None:
595 self.tkconsole.root.bell()
596 return
597 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000598 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000599 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000600 theme = idleConf.GetOption('main','Theme','name')
601 background = idleConf.GetHighlight(theme, 'normal')['background']
602 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000603 sc.frame.pack(expand=1, fill="both")
604 node = TreeNode(sc.canvas, None, item)
605 node.expand()
606 # XXX Should GC the remote tree when closing the window
607
David Scherer7aced172000-08-15 01:13:23 +0000608 gid = 0
609
610 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000611 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000612 filename = self.stuffsource(source)
613 self.execfile(filename, source)
614
615 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000617 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200618 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200619 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000620 try:
621 code = compile(source, filename, "exec")
622 except (OverflowError, SyntaxError):
623 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000624 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000625 print('*** Error in script or command!\n', file=tkerr)
626 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000627 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000628 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000629 else:
630 self.runcode(code)
631
632 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000633 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000634 filename = self.stuffsource(source)
635 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000636 self.save_warnings_filters = warnings.filters[:]
637 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000638 # at the moment, InteractiveInterpreter expects str
639 assert isinstance(source, str)
640 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000641 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000642 # try:
643 # source = source.encode(IOBinding.encoding)
644 # except UnicodeError:
645 # self.tkconsole.resetoutput()
646 # self.write("Unsupported characters in input\n")
647 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000648 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000649 # InteractiveInterpreter.runsource() calls its runcode() method,
650 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000651 return InteractiveInterpreter.runsource(self, source, filename)
652 finally:
653 if self.save_warnings_filters is not None:
654 warnings.filters[:] = self.save_warnings_filters
655 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000656
657 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000658 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000659 filename = "<pyshell#%d>" % self.gid
660 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000661 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000662 linecache.cache[filename] = len(source)+1, 0, lines, filename
663 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000664
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000665 def prepend_syspath(self, filename):
666 "Prepend sys.path with file's directory if not already included"
667 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000668 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000669 import sys as _sys
670 from os.path import dirname as _dirname
671 _dir = _dirname(_filename)
672 if not _dir in _sys.path:
673 _sys.path.insert(0, _dir)
674 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000675 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000676
David Scherer7aced172000-08-15 01:13:23 +0000677 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000678 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000679
680 Color the offending position instead of printing it and pointing at it
681 with a caret.
682
683 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000684 tkconsole = self.tkconsole
685 text = tkconsole.text
686 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000687 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700688 msg = getattr(value, 'msg', '') or value or "<no detail available>"
689 lineno = getattr(value, 'lineno', '') or 1
690 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000691 if offset == 0:
692 lineno += 1 #mark end of offending line
693 if lineno == 1:
694 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000695 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000696 pos = "iomark linestart + %d lines + %d chars" % \
697 (lineno-1, offset-1)
698 tkconsole.colorize_syntax_error(text, pos)
699 tkconsole.resetoutput()
700 self.write("SyntaxError: %s\n" % msg)
701 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000702
703 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000704 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000705 self.tkconsole.resetoutput()
706 self.checklinecache()
707 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000708 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
709 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000710
711 def checklinecache(self):
712 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000713 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000714 if key[:1] + key[-1:] != "<>":
715 del c[key]
716
Chui Tey5d2af632002-05-26 13:36:41 +0000717 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000718 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000719 # The code better not raise an exception!
720 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000721 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000722 return 0
723 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000724 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000725 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000726 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000727 return 1
728
David Scherer7aced172000-08-15 01:13:23 +0000729 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000730 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000731 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000732 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000733 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000734 if self.save_warnings_filters is not None:
735 warnings.filters[:] = self.save_warnings_filters
736 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000737 debugger = self.debugger
738 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000739 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000740 if not debugger and self.rpcclt is not None:
741 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
742 (code,), {})
743 elif debugger:
744 debugger.run(code, self.locals)
745 else:
746 exec(code, self.locals)
747 except SystemExit:
748 if not self.tkconsole.closing:
749 if tkMessageBox.askyesno(
750 "Exit?",
751 "Do you want to exit altogether?",
752 default="yes",
753 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000754 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000755 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000756 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000757 else:
758 raise
759 except:
760 if use_subprocess:
761 print("IDLE internal error in runcode()",
762 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000763 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000764 self.tkconsole.endexecuting()
765 else:
766 if self.tkconsole.canceled:
767 self.tkconsole.canceled = False
768 print("KeyboardInterrupt", file=self.tkconsole.stderr)
769 else:
770 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000771 finally:
772 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000773 try:
774 self.tkconsole.endexecuting()
775 except AttributeError: # shell may have closed
776 pass
David Scherer7aced172000-08-15 01:13:23 +0000777
778 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000779 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200780 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000781
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000782 def display_port_binding_error(self):
783 tkMessageBox.showerror(
784 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000785 "IDLE can't bind to a TCP/IP port, which is necessary to "
786 "communicate with its Python execution server. This might be "
787 "because no networking is installed on this computer. "
788 "Run IDLE with the -n command line switch to start without a "
789 "subprocess and refer to Help/IDLE Help 'Running without a "
790 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000791 master=self.tkconsole.text)
792
793 def display_no_subprocess_error(self):
794 tkMessageBox.showerror(
795 "Subprocess Startup Error",
796 "IDLE's subprocess didn't make connection. Either IDLE can't "
797 "start a subprocess or personal firewall software is blocking "
798 "the connection.",
799 master=self.tkconsole.text)
800
801 def display_executing_dialog(self):
802 tkMessageBox.showerror(
803 "Already executing",
804 "The Python Shell window is already executing a command; "
805 "please wait until it is finished.",
806 master=self.tkconsole.text)
807
808
David Scherer7aced172000-08-15 01:13:23 +0000809class PyShell(OutputWindow):
810
Terry Jan Reedy32622232013-03-30 18:32:19 -0400811 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000812
813 # Override classes
814 ColorDelegator = ModifiedColorDelegator
815 UndoDelegator = ModifiedUndoDelegator
816
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000817 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000818 menu_specs = [
819 ("file", "_File"),
820 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000821 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000822 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000823 ("windows", "_Windows"),
824 ("help", "_Help"),
825 ]
David Scherer7aced172000-08-15 01:13:23 +0000826
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000827 if macosxSupport.runningAsOSXApp():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000828 menu_specs[-2] = ("windows", "_Window")
829
830
David Scherer7aced172000-08-15 01:13:23 +0000831 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000832 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000833
834 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000835 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000836 ms = self.menu_specs
837 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000838 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000839 self.interp = ModifiedInterpreter(self)
840 if flist is None:
841 root = Tk()
842 fixwordbreaks(root)
843 root.withdraw()
844 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000845 #
David Scherer7aced172000-08-15 01:13:23 +0000846 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000847 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000848## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
849 self.usetabs = True
850 # indentwidth must be 8 when using tabs. See note in EditorWindow:
851 self.indentwidth = 8
852 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000853 #
David Scherer7aced172000-08-15 01:13:23 +0000854 text = self.text
855 text.configure(wrap="char")
856 text.bind("<<newline-and-indent>>", self.enter_callback)
857 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
858 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000859 text.bind("<<end-of-file>>", self.eof_callback)
860 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000861 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000862 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
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
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000979 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000980
981 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000982 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000983 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 if use_subprocess:
985 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000986 # Restore std streams
987 sys.stdout = self.save_stdout
988 sys.stderr = self.save_stderr
989 sys.stdin = self.save_stdin
990 # Break cycles
991 self.interp = None
992 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000993 self.flist.pyshell = None
994 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000995 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000996
997 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000998 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000999 return True
David Scherer7aced172000-08-15 01:13:23 +00001000
1001 def short_title(self):
1002 return self.shell_title
1003
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001004 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001005 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001006
David Scherer7aced172000-08-15 01:13:23 +00001007 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001008 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001009 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001010 if use_subprocess:
1011 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001012 client = self.interp.start_subprocess()
1013 if not client:
1014 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001015 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001016 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001017 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001018 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001019 "and will be removed in a later version. See Help/IDLE Help\n" +
1020 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001021 sys.displayhook = rpc.displayhook
1022
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001023 self.write("Python %s on %s\n%s\n%s" %
1024 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001025 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001026 import tkinter
1027 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001028 return True
David Scherer7aced172000-08-15 01:13:23 +00001029
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001030 def stop_readline(self):
1031 if not self.reading: # no nested mainloop to exit.
1032 return
1033 self._stop_readline_flag = True
1034 self.top.quit()
1035
David Scherer7aced172000-08-15 01:13:23 +00001036 def readline(self):
1037 save = self.reading
1038 try:
1039 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001040 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001041 finally:
1042 self.reading = save
Roger Serwy6b7a5ae2013-04-03 00:42:24 -05001043 if self._stop_readline_flag:
1044 self._stop_readline_flag = False
1045 return ""
David Scherer7aced172000-08-15 01:13:23 +00001046 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001047 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1048 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001049 self.resetoutput()
1050 if self.canceled:
1051 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001052 if not use_subprocess:
1053 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001054 if self.endoffile:
1055 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001056 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001057 return line
1058
1059 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001060 return True
David Scherer7aced172000-08-15 01:13:23 +00001061
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001062 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001063 try:
1064 if self.text.compare("sel.first", "!=", "sel.last"):
1065 return # Active selection -- always use default binding
1066 except:
1067 pass
1068 if not (self.executing or self.reading):
1069 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001070 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001071 self.showprompt()
1072 return "break"
1073 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001074 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001075 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001076 if self.interp.getdebugger():
1077 self.interp.restart_subprocess()
1078 else:
1079 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001080 if self.reading:
1081 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001082 return "break"
1083
1084 def eof_callback(self, event):
1085 if self.executing and not self.reading:
1086 return # Let the default binding (delete next char) take over
1087 if not (self.text.compare("iomark", "==", "insert") and
1088 self.text.compare("insert", "==", "end-1c")):
1089 return # Let the default binding (delete next char) take over
1090 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001091 self.resetoutput()
1092 self.close()
1093 else:
1094 self.canceled = 0
1095 self.endoffile = 1
1096 self.top.quit()
1097 return "break"
1098
David Scherer7aced172000-08-15 01:13:23 +00001099 def linefeed_callback(self, event):
1100 # Insert a linefeed without entering anything (still autoindented)
1101 if self.reading:
1102 self.text.insert("insert", "\n")
1103 self.text.see("insert")
1104 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001105 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001106 return "break"
1107
1108 def enter_callback(self, event):
1109 if self.executing and not self.reading:
1110 return # Let the default binding (insert '\n') take over
1111 # If some text is selected, recall the selection
1112 # (but only if this before the I/O mark)
1113 try:
1114 sel = self.text.get("sel.first", "sel.last")
1115 if sel:
1116 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001117 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001118 return "break"
1119 except:
1120 pass
1121 # If we're strictly before the line containing iomark, recall
1122 # the current line, less a leading prompt, less leading or
1123 # trailing whitespace
1124 if self.text.compare("insert", "<", "iomark linestart"):
1125 # Check if there's a relevant stdin range -- if so, use it
1126 prev = self.text.tag_prevrange("stdin", "insert")
1127 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001128 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001129 return "break"
1130 next = self.text.tag_nextrange("stdin", "insert")
1131 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001132 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001133 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001134 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001135 indices = self.text.tag_nextrange("console", "insert linestart")
1136 if indices and \
1137 self.text.compare(indices[0], "<=", "insert linestart"):
1138 self.recall(self.text.get(indices[1], "insert lineend"), event)
1139 else:
1140 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001141 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001142 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001143 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001144 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001145 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001146 # If we're in the current input and there's only whitespace
1147 # beyond the cursor, erase that whitespace first
1148 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001149 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001150 self.text.delete("insert", "end-1c")
1151 # If we're in the current input before its last line,
1152 # insert a newline right at the insert point
1153 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001154 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001155 return "break"
1156 # We're in the last line; append a newline and submit it
1157 self.text.mark_set("insert", "end-1c")
1158 if self.reading:
1159 self.text.insert("insert", "\n")
1160 self.text.see("insert")
1161 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001162 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001163 self.text.tag_add("stdin", "iomark", "end-1c")
1164 self.text.update_idletasks()
1165 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001166 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001167 else:
1168 self.runit()
1169 return "break"
1170
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001171 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001172 # remove leading and trailing empty or whitespace lines
1173 s = re.sub(r'^\s*\n', '' , s)
1174 s = re.sub(r'\n\s*$', '', s)
1175 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001176 self.text.undo_block_start()
1177 try:
1178 self.text.tag_remove("sel", "1.0", "end")
1179 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001180 prefix = self.text.get("insert linestart", "insert")
1181 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001182 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001183 prefix = self.text.get("insert linestart", "insert")
1184 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001185 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001186 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1187 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001188 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001189 if line.startswith(orig_base_indent):
1190 # replace orig base indentation with new indentation
1191 line = new_base_indent + line[len(orig_base_indent):]
1192 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001193 finally:
1194 self.text.see("insert")
1195 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001196
1197 def runit(self):
1198 line = self.text.get("iomark", "end-1c")
1199 # Strip off last newline and surrounding whitespace.
1200 # (To allow you to hit return twice to end a statement.)
1201 i = len(line)
1202 while i > 0 and line[i-1] in " \t":
1203 i = i-1
1204 if i > 0 and line[i-1] == "\n":
1205 i = i-1
1206 while i > 0 and line[i-1] in " \t":
1207 i = i-1
1208 line = line[:i]
1209 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001210
David Scherer7aced172000-08-15 01:13:23 +00001211 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001212 if self.interp.rpcclt:
1213 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001214 try:
1215 sys.last_traceback
1216 except:
1217 tkMessageBox.showerror("No stack trace",
1218 "There is no stack trace yet.\n"
1219 "(sys.last_traceback is not defined)",
1220 master=self.text)
1221 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001222 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001223 sv = StackBrowser(self.root, self.flist)
1224
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001225 def view_restart_mark(self, event=None):
1226 self.text.see("iomark")
1227 self.text.see("restart")
1228
1229 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001230 "Callback for Run/Restart Shell Cntl-F6"
1231 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001232
David Scherer7aced172000-08-15 01:13:23 +00001233 def showprompt(self):
1234 self.resetoutput()
1235 try:
1236 s = str(sys.ps1)
1237 except:
1238 s = ""
1239 self.console.write(s)
1240 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001241 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001242 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001243
1244 def resetoutput(self):
1245 source = self.text.get("iomark", "end-1c")
1246 if self.history:
1247 self.history.history_store(source)
1248 if self.text.get("end-2c") != "\n":
1249 self.text.insert("end-1c", "\n")
1250 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001251 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001252
1253 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001254 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1255 # Tk doesn't support outputting non-BMP characters
1256 # Let's assume what printed string is not very long,
1257 # find first non-BMP character and construct informative
1258 # UnicodeEncodeError exception.
1259 for start, char in enumerate(s):
1260 if char > '\uffff':
1261 break
1262 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1263 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001264 try:
1265 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001266 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001267 self.text.mark_gravity("iomark", "left")
1268 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001269 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1270 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001271 if self.canceled:
1272 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001273 if not use_subprocess:
1274 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001275 return count
David Scherer7aced172000-08-15 01:13:23 +00001276
Andrew Svetlovd1837672012-11-01 22:41:19 +02001277 def rmenu_check_cut(self):
1278 try:
1279 if self.text.compare('sel.first', '<', 'iomark'):
1280 return 'disabled'
1281 except TclError: # no selection, so the index 'sel.first' doesn't exist
1282 return 'disabled'
1283 return super().rmenu_check_cut()
1284
1285 def rmenu_check_paste(self):
1286 if self.text.compare('insert','<','iomark'):
1287 return 'disabled'
1288 return super().rmenu_check_paste()
1289
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001290class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001291
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001292 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001293 self.shell = shell
1294 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001295 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001296
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001297 @property
1298 def encoding(self):
1299 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001300
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001301 @property
1302 def name(self):
1303 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001304
1305 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001306 return True
David Scherer7aced172000-08-15 01:13:23 +00001307
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001308
1309class PseudoOutputFile(PseudoFile):
1310
1311 def writable(self):
1312 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001313
1314 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001315 if self.closed:
1316 raise ValueError("write to closed file")
1317 if not isinstance(s, str):
1318 raise TypeError('must be str, not ' + type(s).__name__)
1319 return self.shell.write(s, self.tags)
1320
1321
1322class PseudoInputFile(PseudoFile):
1323
1324 def __init__(self, shell, tags, encoding=None):
1325 PseudoFile.__init__(self, shell, tags, encoding)
1326 self._line_buffer = ''
1327
1328 def readable(self):
1329 return True
1330
1331 def read(self, size=-1):
1332 if self.closed:
1333 raise ValueError("read from closed file")
1334 if size is None:
1335 size = -1
1336 elif not isinstance(size, int):
1337 raise TypeError('must be int, not ' + type(size).__name__)
1338 result = self._line_buffer
1339 self._line_buffer = ''
1340 if size < 0:
1341 while True:
1342 line = self.shell.readline()
1343 if not line: break
1344 result += line
1345 else:
1346 while len(result) < size:
1347 line = self.shell.readline()
1348 if not line: break
1349 result += line
1350 self._line_buffer = result[size:]
1351 result = result[:size]
1352 return result
1353
1354 def readline(self, size=-1):
1355 if self.closed:
1356 raise ValueError("read from closed file")
1357 if size is None:
1358 size = -1
1359 elif not isinstance(size, int):
1360 raise TypeError('must be int, not ' + type(size).__name__)
1361 line = self._line_buffer or self.shell.readline()
1362 if size < 0:
1363 size = len(line)
1364 self._line_buffer = line[size:]
1365 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001366
Roger Serwy1eafd102013-04-11 19:16:44 -05001367 def close(self):
1368 self.shell.close()
1369
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370
David Scherer7aced172000-08-15 01:13:23 +00001371usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001372
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001373USAGE: idle [-deins] [-t title] [file]*
1374 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1375 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001376
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001377 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001378 -n run IDLE without a subprocess (DEPRECATED,
1379 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001380
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001382
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001383 -e open an edit window
1384 -i open a shell window
1385
1386The following options imply -i and will open a shell:
1387
1388 -c cmd run the command in a shell, or
1389 -r file run script from file
1390
1391 -d enable the debugger
1392 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1393 -t title set title of shell window
1394
1395A default edit window will be bypassed when -c, -r, or - are used.
1396
1397[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1398
1399Examples:
1400
1401idle
1402 Open an edit window or shell depending on IDLE's configuration.
1403
1404idle foo.py foobar.py
1405 Edit the files, also open a shell if configured to start with shell.
1406
1407idle -est "Baz" foo.py
1408 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1409 window with the title "Baz".
1410
Neal Norwitz752abd02008-05-13 04:55:24 +00001411idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 Open a shell window and run the command, passing "-c" in sys.argv[0]
1413 and "foo" in sys.argv[1].
1414
1415idle -d -s -r foo.py "Hello World"
1416 Open a shell window, run a startup script, enable the debugger, and
1417 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1418 sys.argv[1].
1419
Neal Norwitz752abd02008-05-13 04:55:24 +00001420echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1422 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001423"""
1424
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001425def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001427
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001428 use_subprocess = True
Roger Serwyc35151c2013-03-31 23:28:55 -05001429 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001430 enable_edit = False
1431 debug = False
1432 cmd = None
1433 script = None
1434 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001435 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001436 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001437 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001438 sys.stderr.write("Error: %s\n" % str(msg))
1439 sys.stderr.write(usage_msg)
1440 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001441 for o, a in opts:
1442 if o == '-c':
1443 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001444 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001445 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001446 debug = True
1447 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001448 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001449 enable_edit = True
1450 if o == '-h':
1451 sys.stdout.write(usage_msg)
1452 sys.exit()
1453 if o == '-i':
1454 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001455 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001456 print(" Warning: running IDLE without a subprocess is deprecated.",
1457 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001458 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001459 if o == '-r':
1460 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001461 if os.path.isfile(script):
1462 pass
1463 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001464 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001465 sys.exit()
1466 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001467 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001468 startup = True
1469 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001470 if o == '-t':
1471 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001472 enable_shell = True
1473 if args and args[0] == '-':
1474 cmd = sys.stdin.read()
1475 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001476 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001477 for i in range(len(sys.path)):
1478 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001479 if args and args[0] == '-':
1480 sys.argv = [''] + args[1:]
1481 elif cmd:
1482 sys.argv = ['-c'] + args
1483 elif script:
1484 sys.argv = [script] + args
1485 elif args:
1486 enable_edit = True
1487 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001488 for filename in args:
1489 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001490 for dir in pathx:
1491 dir = os.path.abspath(dir)
1492 if not dir in sys.path:
1493 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001494 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001495 dir = os.getcwd()
1496 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001497 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001498 # check the IDLE settings configuration (but command line overrides)
1499 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001500 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001501 enable_edit = enable_edit or edit_start
Roger Serwyc35151c2013-03-31 23:28:55 -05001502 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001503 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001504 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001505
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001506 fixwordbreaks(root)
1507 root.withdraw()
1508 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001509 macosxSupport.setupApp(root, flist)
1510
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001511 if enable_edit:
1512 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001513 for filename in args[:]:
1514 if flist.open(filename) is None:
1515 # filename is a directory actually, disconsider it
1516 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001517 if not args:
1518 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001519 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001520 shell = flist.open_shell()
1521 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001522 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001523
1524 if macosxSupport.runningAsOSXApp() and flist.dict:
1525 # On OSX: when the user has double-clicked on a file that causes
1526 # IDLE to be launched the shell window will open just in front of
1527 # the file she wants to see. Lower the interpreter window when
1528 # there are open files.
1529 shell.top.lower()
1530
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001531 shell = flist.pyshell
1532 # handle remaining options:
1533 if debug:
1534 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001535 if startup:
1536 filename = os.environ.get("IDLESTARTUP") or \
1537 os.environ.get("PYTHONSTARTUP")
1538 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001539 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001540 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001541 shell.interp.runcommand("""if 1:
1542 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001543 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001544 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001545 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001546 if cmd:
1547 shell.interp.execsource(cmd)
1548 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001549 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001550 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001551
Ned Deily4ce92b22011-01-15 04:37:12 +00001552 # Check for problematic OS X Tk versions and print a warning message
1553 # in the IDLE shell window; this is less intrusive than always opening
1554 # a separate window.
1555 tkversionwarning = macosxSupport.tkVersionWarning(root)
1556 if tkversionwarning:
1557 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1558
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001559 while flist.inversedict: # keep IDLE running while files are open.
1560 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001561 root.destroy()
1562
David Scherer7aced172000-08-15 01:13:23 +00001563if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001564 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001565 main()