blob: fb47b994d1f18d537406803186bdc7b98480b444 [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
19
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl14fc4272008-05-17 18:39:55 +000021 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000023 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000024 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000025 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000026import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000028from idlelib.EditorWindow import EditorWindow, fixwordbreaks
29from idlelib.FileList import FileList
30from idlelib.ColorDelegator import ColorDelegator
31from idlelib.UndoDelegator import UndoDelegator
32from idlelib.OutputWindow import OutputWindow
33from idlelib.configHandler import idleConf
34from idlelib import idlever
35from idlelib import rpc
36from idlelib import Debugger
37from idlelib import RemoteDebugger
38from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000039
Kurt B. Kaisere866c812009-04-04 21:07:39 +000040HOST = '127.0.0.1' # python execution server on localhost loopback
41PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000042
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000043# Override warnings module to write to warning_stream. Initialize to send IDLE
44# internal warnings to the console. ScriptBinding.check_syntax() will
45# temporarily redirect the stream to the shell window to display warnings when
46# checking user's code.
47global warning_stream
48warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000049try:
50 import warnings
51except ImportError:
52 pass
53else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000054 def idle_showwarning(message, category, filename, lineno,
55 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000056 if file is None:
57 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000058 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000059 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070060 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000061 except IOError:
62 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000063 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000064 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 """Format warnings the IDLE way"""
66 s = "\nWarning (from warnings module):\n"
67 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000068 if line is None:
69 line = linecache.getline(filename, lineno)
70 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 if line:
72 s += " %s\n" % line
73 s += "%s: %s\n>>> " % (category.__name__, message)
74 return s
75 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000076
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000077def extended_linecache_checkcache(filename=None,
78 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079 """Extend linecache.checkcache to preserve the <pyshell#...> entries
80
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000081 Rather than repeating the linecache code, patch it to save the
82 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000083 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000084
85 orig_checkcache is bound at definition time to the original
86 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000087 """
David Scherer7aced172000-08-15 01:13:23 +000088 cache = linecache.cache
89 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000090 for key in list(cache):
91 if key[:1] + key[-1:] == '<>':
92 save[key] = cache.pop(key)
93 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000094 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000095
Kurt B. Kaiser81885592002-11-29 22:10:53 +000096# Patch linecache.checkcache():
97linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000098
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000099
David Scherer7aced172000-08-15 01:13:23 +0000100class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000101 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000102
David Scherer7aced172000-08-15 01:13:23 +0000103 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000105 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000106 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000108 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
109
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000110 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
111 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000112 # whenever a file is changed, restore breakpoints
113 if self.io.filename: self.restore_file_breaks()
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)
119
Andrew Svetlovd1837672012-11-01 22:41:19 +0200120 rmenu_specs = [
121 ("Cut", "<<cut>>", "rmenu_check_cut"),
122 ("Copy", "<<copy>>", "rmenu_check_copy"),
123 ("Paste", "<<paste>>", "rmenu_check_paste"),
124 (None, None, None),
125 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
126 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
127 ]
David Scherer7aced172000-08-15 01:13:23 +0000128
Chui Teya2adb0f2002-11-04 22:14:54 +0000129 def set_breakpoint(self, lineno):
130 text = self.text
131 filename = self.io.filename
132 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
133 try:
134 i = self.breakpoints.index(lineno)
135 except ValueError: # only add if missing, i.e. do once
136 self.breakpoints.append(lineno)
137 try: # update the subprocess debugger
138 debug = self.flist.pyshell.interp.debugger
139 debug.set_breakpoint_here(filename, lineno)
140 except: # but debugger may not be active right now....
141 pass
142
David Scherer7aced172000-08-15 01:13:23 +0000143 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000144 text = self.text
145 filename = self.io.filename
146 if not filename:
147 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000148 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000149 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000150 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000151
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000152 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 text = self.text
154 filename = self.io.filename
155 if not filename:
156 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000157 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000158 lineno = int(float(text.index("insert")))
159 try:
160 self.breakpoints.remove(lineno)
161 except:
162 pass
163 text.tag_remove("BREAK", "insert linestart",\
164 "insert lineend +1char")
165 try:
166 debug = self.flist.pyshell.interp.debugger
167 debug.clear_breakpoint_here(filename, lineno)
168 except:
169 pass
170
171 def clear_file_breaks(self):
172 if self.breakpoints:
173 text = self.text
174 filename = self.io.filename
175 if not filename:
176 text.bell()
177 return
178 self.breakpoints = []
179 text.tag_remove("BREAK", "1.0", END)
180 try:
181 debug = self.flist.pyshell.interp.debugger
182 debug.clear_file_breaks(filename)
183 except:
184 pass
185
Chui Teya2adb0f2002-11-04 22:14:54 +0000186 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000187 "Save breakpoints when file is saved"
188 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
189 # be run. The breaks are saved at that time. If we introduce
190 # a temporary file save feature the save breaks functionality
191 # needs to be re-verified, since the breaks at the time the
192 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000193 # permanent save of the file. Currently, a break introduced
194 # after a save will be effective, but not persistent.
195 # This is necessary to keep the saved breaks synched with the
196 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000197 #
198 # Breakpoints are set as tagged ranges in the text. Certain
199 # kinds of edits cause these ranges to be deleted: Inserting
200 # or deleting a line just before a breakpoint, and certain
201 # deletions prior to a breakpoint. These issues need to be
202 # investigated and understood. It's not clear if they are
203 # Tk issues or IDLE issues, or whether they can actually
204 # be fixed. Since a modified file has to be saved before it is
205 # run, and since self.breakpoints (from which the subprocess
206 # debugger is loaded) is updated during the save, the visible
207 # breaks stay synched with the subprocess even if one of these
208 # unexpected breakpoint deletions occurs.
209 breaks = self.breakpoints
210 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000211 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200212 with open(self.breakpointPath, "r") as fp:
213 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800216 try:
217 with open(self.breakpointPath, "w") as new_file:
218 for line in lines:
219 if not line.startswith(filename + '='):
220 new_file.write(line)
221 self.update_breakpoints()
222 breaks = self.breakpoints
223 if breaks:
224 new_file.write(filename + '=' + str(breaks) + '\n')
225 except IOError as err:
226 if not getattr(self.root, "breakpoint_error_displayed", False):
227 self.root.breakpoint_error_displayed = True
228 tkMessageBox.showerror(title='IDLE Error',
229 message='Unable to update breakpoint list:\n%s'
230 % str(err),
231 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000232
233 def restore_file_breaks(self):
234 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 filename = self.io.filename
236 if filename is None:
237 return
Chui Tey69371d62002-11-04 23:39:45 +0000238 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200239 with open(self.breakpointPath, "r") as fp:
240 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000241 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000242 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000243 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000244 for breakpoint_linenumber in breakpoint_linenumbers:
245 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000246
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247 def update_breakpoints(self):
248 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000249 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 ranges = text.tag_ranges("BREAK")
251 linenumber_list = self.ranges_to_linenumbers(ranges)
252 self.breakpoints = linenumber_list
253
254 def ranges_to_linenumbers(self, ranges):
255 lines = []
256 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300257 lineno = int(float(ranges[index].string))
258 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000259 while lineno < end:
260 lines.append(lineno)
261 lineno += 1
262 return lines
263
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000264# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000265# def saved_change_hook(self):
266# "Extend base method - clear breaks if module is modified"
267# if not self.get_saved():
268# self.clear_file_breaks()
269# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000270
271 def _close(self):
272 "Extend base method - clear breaks when module is closed"
273 self.clear_file_breaks()
274 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000275
David Scherer7aced172000-08-15 01:13:23 +0000276
277class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000278 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000279
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000280 # override FileList's class variable, instances return PyShellEditorWindow
281 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000282 EditorWindow = PyShellEditorWindow
283
284 pyshell = None
285
286 def open_shell(self, event=None):
287 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000288 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000289 else:
290 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000291 if self.pyshell:
292 if not self.pyshell.begin():
293 return None
David Scherer7aced172000-08-15 01:13:23 +0000294 return self.pyshell
295
296
297class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000298 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000299
Steven M. Gavab77d3432002-03-02 07:16:21 +0000300 def __init__(self):
301 ColorDelegator.__init__(self)
302 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000303
304 def recolorize_main(self):
305 self.tag_remove("TODO", "1.0", "iomark")
306 self.tag_add("SYNC", "1.0", "iomark")
307 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000308
Steven M. Gavab77d3432002-03-02 07:16:21 +0000309 def LoadTagDefs(self):
310 ColorDelegator.LoadTagDefs(self)
311 theme = idleConf.GetOption('main','Theme','name')
312 self.tagdefs.update({
313 "stdin": {'background':None,'foreground':None},
314 "stdout": idleConf.GetHighlight(theme, "stdout"),
315 "stderr": idleConf.GetHighlight(theme, "stderr"),
316 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000317 })
David Scherer7aced172000-08-15 01:13:23 +0000318
Ned Deily8b2a56b2012-05-31 09:17:29 -0700319 def removecolors(self):
320 # Don't remove shell color tags before "iomark"
321 for tag in self.tagdefs:
322 self.tag_remove(tag, "iomark", "end")
323
David Scherer7aced172000-08-15 01:13:23 +0000324class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000325 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000326
327 def insert(self, index, chars, tags=None):
328 try:
329 if self.delegate.compare(index, "<", "iomark"):
330 self.delegate.bell()
331 return
332 except TclError:
333 pass
334 UndoDelegator.insert(self, index, chars, tags)
335
336 def delete(self, index1, index2=None):
337 try:
338 if self.delegate.compare(index1, "<", "iomark"):
339 self.delegate.bell()
340 return
341 except TclError:
342 pass
343 UndoDelegator.delete(self, index1, index2)
344
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000345
346class MyRPCClient(rpc.RPCClient):
347
348 def handle_EOF(self):
349 "Override the base class - just re-raise EOFError"
350 raise EOFError
351
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000352
David Scherer7aced172000-08-15 01:13:23 +0000353class ModifiedInterpreter(InteractiveInterpreter):
354
355 def __init__(self, tkconsole):
356 self.tkconsole = tkconsole
357 locals = sys.modules['__main__'].__dict__
358 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000359 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000360 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000361 self.subprocess_arglist = None
362 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700363 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000364
Chui Tey5d2af632002-05-26 13:36:41 +0000365 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700366 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000367
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000368 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000369 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000370 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700371 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000372
Tony Lowndsf53dec22002-12-20 04:24:43 +0000373 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000374 assert (self.port!=0), (
375 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000376 w = ['-W' + s for s in sys.warnoptions]
377 # Maybe IDLE is installed and is being accessed via sys.path,
378 # or maybe it's not installed and the idle.py script is being
379 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000380 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
381 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000382 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000383 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000384 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000385 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700386 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000387
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000388 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000389 addr = (HOST, self.port)
390 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000391 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000392 time.sleep(i)
393 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000394 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000395 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000396 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000397 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000398 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000399 self.display_port_binding_error()
400 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000401 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
402 self.port = self.rpcclt.listening_sock.getsockname()[1]
403 # if PORT was not 0, probably working with a remote execution server
404 if PORT != 0:
405 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
406 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
407 # on Windows since the implementation allows two active sockets on
408 # the same address!
409 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
410 socket.SO_REUSEADDR, 1)
411 self.spawn_subprocess()
412 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000413 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000414 self.rpcclt.listening_sock.settimeout(10)
415 try:
416 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000417 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000418 self.display_no_subprocess_error()
419 return None
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200420 # Can't regiter self.tkconsole.stdin, since run.py wants to
421 # call non-TextIO methods on it (such as getvar)
422 # XXX should be renamed to "console"
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000423 self.rpcclt.register("stdin", self.tkconsole)
424 self.rpcclt.register("stdout", self.tkconsole.stdout)
425 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000426 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000427 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000428 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500429 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000430 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000431 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000432
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500433 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000435 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000436 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000437 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000438 debug = self.getdebugger()
439 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000440 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000441 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000442 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
443 except:
444 pass
445 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000446 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700447 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000448 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000449 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000450 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000451 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000452 try:
453 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000454 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000455 self.display_no_subprocess_error()
456 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500457 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000458 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000459 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000460 if was_executing:
461 console.write('\n')
462 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000463 halfbar = ((int(console.width) - 16) // 2) * '='
464 console.write(halfbar + ' RESTART ' + halfbar)
465 console.text.mark_set("restart", "end-1c")
466 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000467 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000468 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000469 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000470 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000471 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000472 # reload remote debugger breakpoints for all PyShellEditWindows
473 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700474 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000475 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000476 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000477
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000480
481 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000483
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000485 try:
486 self.rpcclt.close()
487 except AttributeError: # no socket
488 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700489 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 self.tkconsole.executing = False
491 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000492
Ned Deilye5cad232011-08-02 18:47:13 -0700493 def terminate_subprocess(self):
494 "Make sure subprocess is terminated"
495 try:
496 self.rpcsubproc.kill()
497 except OSError:
498 # process already terminated
499 return
500 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000501 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700502 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000503 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000504 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000505
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500506 def transfer_path(self, with_cwd=False):
507 if with_cwd: # Issue 13506
508 path = [''] # include Current Working Directory
509 path.extend(sys.path)
510 else:
511 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500512
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000513 self.runcommand("""if 1:
514 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000515 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000516 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500517 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000518
Chui Tey5d2af632002-05-26 13:36:41 +0000519 active_seq = None
520
521 def poll_subprocess(self):
522 clt = self.rpcclt
523 if clt is None:
524 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000525 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000526 response = clt.pollresponse(self.active_seq, wait=0.05)
527 except (EOFError, IOError, KeyboardInterrupt):
528 # lost connection or subprocess terminated itself, restart
529 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000530 if self.tkconsole.closing:
531 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000532 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000533 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000534 if response:
535 self.tkconsole.resetoutput()
536 self.active_seq = None
537 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000538 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000539 if how == "OK":
540 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000541 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000542 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000543 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
544 self.remote_stack_viewer()
545 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000546 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000547 print(errmsg, what, file=sys.__stderr__)
548 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000549 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000550 try:
551 self.tkconsole.endexecuting()
552 except AttributeError: # shell may have closed
553 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000554 # Reschedule myself
555 if not self.tkconsole.closing:
556 self.tkconsole.text.after(self.tkconsole.pollinterval,
557 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000558
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000559 debugger = None
560
561 def setdebugger(self, debugger):
562 self.debugger = debugger
563
564 def getdebugger(self):
565 return self.debugger
566
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000567 def open_remote_stack_viewer(self):
568 """Initiate the remote stack viewer from a separate thread.
569
570 This method is called from the subprocess, and by returning from this
571 method we allow the subprocess to unblock. After a bit the shell
572 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000573 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000574 the RPC mechanism.
575
576 """
577 self.tkconsole.text.after(300, self.remote_stack_viewer)
578 return
579
Chui Tey5d2af632002-05-26 13:36:41 +0000580 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000581 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000582 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000583 if oid is None:
584 self.tkconsole.root.bell()
585 return
586 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000587 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000588 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000589 theme = idleConf.GetOption('main','Theme','name')
590 background = idleConf.GetHighlight(theme, 'normal')['background']
591 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000592 sc.frame.pack(expand=1, fill="both")
593 node = TreeNode(sc.canvas, None, item)
594 node.expand()
595 # XXX Should GC the remote tree when closing the window
596
David Scherer7aced172000-08-15 01:13:23 +0000597 gid = 0
598
599 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000600 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000601 filename = self.stuffsource(source)
602 self.execfile(filename, source)
603
604 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000605 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000606 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200607 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200608 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000609 try:
610 code = compile(source, filename, "exec")
611 except (OverflowError, SyntaxError):
612 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000613 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000614 print('*** Error in script or command!\n', file=tkerr)
615 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000616 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000617 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000618 else:
619 self.runcode(code)
620
621 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000622 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000623 filename = self.stuffsource(source)
624 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000625 self.save_warnings_filters = warnings.filters[:]
626 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000627 # at the moment, InteractiveInterpreter expects str
628 assert isinstance(source, str)
629 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000630 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000631 # try:
632 # source = source.encode(IOBinding.encoding)
633 # except UnicodeError:
634 # self.tkconsole.resetoutput()
635 # self.write("Unsupported characters in input\n")
636 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000637 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000638 # InteractiveInterpreter.runsource() calls its runcode() method,
639 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000640 return InteractiveInterpreter.runsource(self, source, filename)
641 finally:
642 if self.save_warnings_filters is not None:
643 warnings.filters[:] = self.save_warnings_filters
644 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000645
646 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000647 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000648 filename = "<pyshell#%d>" % self.gid
649 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000650 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000651 linecache.cache[filename] = len(source)+1, 0, lines, filename
652 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000653
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000654 def prepend_syspath(self, filename):
655 "Prepend sys.path with file's directory if not already included"
656 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000657 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000658 import sys as _sys
659 from os.path import dirname as _dirname
660 _dir = _dirname(_filename)
661 if not _dir in _sys.path:
662 _sys.path.insert(0, _dir)
663 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000664 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000665
David Scherer7aced172000-08-15 01:13:23 +0000666 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000667 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000668
669 Color the offending position instead of printing it and pointing at it
670 with a caret.
671
672 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000673 tkconsole = self.tkconsole
674 text = tkconsole.text
675 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000676 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700677 msg = getattr(value, 'msg', '') or value or "<no detail available>"
678 lineno = getattr(value, 'lineno', '') or 1
679 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000680 if offset == 0:
681 lineno += 1 #mark end of offending line
682 if lineno == 1:
683 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000684 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000685 pos = "iomark linestart + %d lines + %d chars" % \
686 (lineno-1, offset-1)
687 tkconsole.colorize_syntax_error(text, pos)
688 tkconsole.resetoutput()
689 self.write("SyntaxError: %s\n" % msg)
690 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000691
692 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000693 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000694 self.tkconsole.resetoutput()
695 self.checklinecache()
696 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000697 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
698 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000699
700 def checklinecache(self):
701 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000702 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000703 if key[:1] + key[-1:] != "<>":
704 del c[key]
705
Chui Tey5d2af632002-05-26 13:36:41 +0000706 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000707 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000708 # The code better not raise an exception!
709 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000710 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000711 return 0
712 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000713 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000714 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000715 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000716 return 1
717
David Scherer7aced172000-08-15 01:13:23 +0000718 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000719 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000720 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000721 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000722 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000723 if self.save_warnings_filters is not None:
724 warnings.filters[:] = self.save_warnings_filters
725 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000726 debugger = self.debugger
727 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000728 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000729 if not debugger and self.rpcclt is not None:
730 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
731 (code,), {})
732 elif debugger:
733 debugger.run(code, self.locals)
734 else:
735 exec(code, self.locals)
736 except SystemExit:
737 if not self.tkconsole.closing:
738 if tkMessageBox.askyesno(
739 "Exit?",
740 "Do you want to exit altogether?",
741 default="yes",
742 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000743 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000744 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000745 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000746 else:
747 raise
748 except:
749 if use_subprocess:
750 print("IDLE internal error in runcode()",
751 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000752 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000753 self.tkconsole.endexecuting()
754 else:
755 if self.tkconsole.canceled:
756 self.tkconsole.canceled = False
757 print("KeyboardInterrupt", file=self.tkconsole.stderr)
758 else:
759 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000760 finally:
761 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000762 try:
763 self.tkconsole.endexecuting()
764 except AttributeError: # shell may have closed
765 pass
David Scherer7aced172000-08-15 01:13:23 +0000766
767 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000768 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200769 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000770
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000771 def display_port_binding_error(self):
772 tkMessageBox.showerror(
773 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000774 "IDLE can't bind to a TCP/IP port, which is necessary to "
775 "communicate with its Python execution server. This might be "
776 "because no networking is installed on this computer. "
777 "Run IDLE with the -n command line switch to start without a "
778 "subprocess and refer to Help/IDLE Help 'Running without a "
779 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000780 master=self.tkconsole.text)
781
782 def display_no_subprocess_error(self):
783 tkMessageBox.showerror(
784 "Subprocess Startup Error",
785 "IDLE's subprocess didn't make connection. Either IDLE can't "
786 "start a subprocess or personal firewall software is blocking "
787 "the connection.",
788 master=self.tkconsole.text)
789
790 def display_executing_dialog(self):
791 tkMessageBox.showerror(
792 "Already executing",
793 "The Python Shell window is already executing a command; "
794 "please wait until it is finished.",
795 master=self.tkconsole.text)
796
797
David Scherer7aced172000-08-15 01:13:23 +0000798class PyShell(OutputWindow):
799
800 shell_title = "Python Shell"
801
802 # Override classes
803 ColorDelegator = ModifiedColorDelegator
804 UndoDelegator = ModifiedUndoDelegator
805
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000806 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000807 menu_specs = [
808 ("file", "_File"),
809 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000810 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000811 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000812 ("windows", "_Windows"),
813 ("help", "_Help"),
814 ]
David Scherer7aced172000-08-15 01:13:23 +0000815
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000816 if macosxSupport.runningAsOSXApp():
817 del menu_specs[-3]
818 menu_specs[-2] = ("windows", "_Window")
819
820
David Scherer7aced172000-08-15 01:13:23 +0000821 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000822 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000823
824 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000825 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000826 ms = self.menu_specs
827 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000828 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000829 self.interp = ModifiedInterpreter(self)
830 if flist is None:
831 root = Tk()
832 fixwordbreaks(root)
833 root.withdraw()
834 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000835 #
David Scherer7aced172000-08-15 01:13:23 +0000836 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000838## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
839 self.usetabs = True
840 # indentwidth must be 8 when using tabs. See note in EditorWindow:
841 self.indentwidth = 8
842 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000843 #
David Scherer7aced172000-08-15 01:13:23 +0000844 text = self.text
845 text.configure(wrap="char")
846 text.bind("<<newline-and-indent>>", self.enter_callback)
847 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
848 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000849 text.bind("<<end-of-file>>", self.eof_callback)
850 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000851 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000852 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000853 self.color = color = self.ColorDelegator()
854 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000855 if use_subprocess:
856 text.bind("<<view-restart>>", self.view_restart_mark)
857 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000858 #
David Scherer7aced172000-08-15 01:13:23 +0000859 self.save_stdout = sys.stdout
860 self.save_stderr = sys.stderr
861 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000862 from idlelib import IOBinding
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200863 self.stdin = PseudoInputFile(self)
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000864 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
865 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
866 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000867 if not use_subprocess:
868 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000869 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200870 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000871 try:
872 # page help() text to shell.
873 import pydoc # import must be done here to capture i/o rebinding.
874 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
875 pydoc.pager = pydoc.plainpager
876 except:
877 sys.stderr = sys.__stderr__
878 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000879 #
David Scherer7aced172000-08-15 01:13:23 +0000880 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000881 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000882 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000883
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000884 def get_standard_extension_names(self):
885 return idleConf.GetExtensions(shell_only=True)
886
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000887 reading = False
888 executing = False
889 canceled = False
890 endoffile = False
891 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000892
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000893 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000894 global warning_stream
895 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000896
897 def get_warning_stream(self):
898 return warning_stream
899
David Scherer7aced172000-08-15 01:13:23 +0000900 def toggle_debugger(self, event=None):
901 if self.executing:
902 tkMessageBox.showerror("Don't debug now",
903 "You can only toggle the debugger when idle",
904 master=self.text)
905 self.set_debugger_indicator()
906 return "break"
907 else:
908 db = self.interp.getdebugger()
909 if db:
910 self.close_debugger()
911 else:
912 self.open_debugger()
913
914 def set_debugger_indicator(self):
915 db = self.interp.getdebugger()
916 self.setvar("<<toggle-debugger>>", not not db)
917
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000918 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000919 pass # All we need is the variable
920
921 def close_debugger(self):
922 db = self.interp.getdebugger()
923 if db:
924 self.interp.setdebugger(None)
925 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000926 if self.interp.rpcclt:
927 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000928 self.resetoutput()
929 self.console.write("[DEBUG OFF]\n")
930 sys.ps1 = ">>> "
931 self.showprompt()
932 self.set_debugger_indicator()
933
934 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000935 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000936 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
937 self)
938 else:
939 dbg_gui = Debugger.Debugger(self)
940 self.interp.setdebugger(dbg_gui)
941 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000942 sys.ps1 = "[DEBUG ON]\n>>> "
943 self.showprompt()
944 self.set_debugger_indicator()
945
David Scherer7aced172000-08-15 01:13:23 +0000946 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000947 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000948 self.resetoutput()
949 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000950
951 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000952 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000953 self.executing = 0
954 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000955 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000956
957 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000958 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000959 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000960 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000961 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000962 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000963 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000964 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000965 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000966 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000967 if self.reading:
968 self.top.quit()
969 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000970 self.closing = True
971 # Wait for poll_subprocess() rescheduling to stop
972 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000973
974 def close2(self):
975 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000976
977 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000978 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000979 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000980 if use_subprocess:
981 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000982 # Restore std streams
983 sys.stdout = self.save_stdout
984 sys.stderr = self.save_stderr
985 sys.stdin = self.save_stdin
986 # Break cycles
987 self.interp = None
988 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000989 self.flist.pyshell = None
990 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000991 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000992
993 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000994 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000995 return True
David Scherer7aced172000-08-15 01:13:23 +0000996
997 def short_title(self):
998 return self.shell_title
999
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001000 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001001 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001002
David Scherer7aced172000-08-15 01:13:23 +00001003 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001004 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001005 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001006 if use_subprocess:
1007 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001008 client = self.interp.start_subprocess()
1009 if not client:
1010 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001011 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001012 else:
1013 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001014 self.write("Python %s on %s\n%s\n%s" %
1015 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001016 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001017 import tkinter
1018 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001019 return True
David Scherer7aced172000-08-15 01:13:23 +00001020
1021 def readline(self):
1022 save = self.reading
1023 try:
1024 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001025 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001026 finally:
1027 self.reading = save
1028 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001029 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1030 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001031 self.resetoutput()
1032 if self.canceled:
1033 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001034 if not use_subprocess:
1035 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001036 if self.endoffile:
1037 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001038 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001039 return line
1040
1041 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001042 return True
David Scherer7aced172000-08-15 01:13:23 +00001043
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001044 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001045 try:
1046 if self.text.compare("sel.first", "!=", "sel.last"):
1047 return # Active selection -- always use default binding
1048 except:
1049 pass
1050 if not (self.executing or self.reading):
1051 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001052 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001053 self.showprompt()
1054 return "break"
1055 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001056 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001057 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001058 if self.interp.getdebugger():
1059 self.interp.restart_subprocess()
1060 else:
1061 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001062 if self.reading:
1063 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001064 return "break"
1065
1066 def eof_callback(self, event):
1067 if self.executing and not self.reading:
1068 return # Let the default binding (delete next char) take over
1069 if not (self.text.compare("iomark", "==", "insert") and
1070 self.text.compare("insert", "==", "end-1c")):
1071 return # Let the default binding (delete next char) take over
1072 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001073 self.resetoutput()
1074 self.close()
1075 else:
1076 self.canceled = 0
1077 self.endoffile = 1
1078 self.top.quit()
1079 return "break"
1080
David Scherer7aced172000-08-15 01:13:23 +00001081 def linefeed_callback(self, event):
1082 # Insert a linefeed without entering anything (still autoindented)
1083 if self.reading:
1084 self.text.insert("insert", "\n")
1085 self.text.see("insert")
1086 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001087 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001088 return "break"
1089
1090 def enter_callback(self, event):
1091 if self.executing and not self.reading:
1092 return # Let the default binding (insert '\n') take over
1093 # If some text is selected, recall the selection
1094 # (but only if this before the I/O mark)
1095 try:
1096 sel = self.text.get("sel.first", "sel.last")
1097 if sel:
1098 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001099 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001100 return "break"
1101 except:
1102 pass
1103 # If we're strictly before the line containing iomark, recall
1104 # the current line, less a leading prompt, less leading or
1105 # trailing whitespace
1106 if self.text.compare("insert", "<", "iomark linestart"):
1107 # Check if there's a relevant stdin range -- if so, use it
1108 prev = self.text.tag_prevrange("stdin", "insert")
1109 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001110 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001111 return "break"
1112 next = self.text.tag_nextrange("stdin", "insert")
1113 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001114 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001115 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001116 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001117 indices = self.text.tag_nextrange("console", "insert linestart")
1118 if indices and \
1119 self.text.compare(indices[0], "<=", "insert linestart"):
1120 self.recall(self.text.get(indices[1], "insert lineend"), event)
1121 else:
1122 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001123 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001124 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001125 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001126 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001127 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001128 # If we're in the current input and there's only whitespace
1129 # beyond the cursor, erase that whitespace first
1130 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001131 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001132 self.text.delete("insert", "end-1c")
1133 # If we're in the current input before its last line,
1134 # insert a newline right at the insert point
1135 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001136 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001137 return "break"
1138 # We're in the last line; append a newline and submit it
1139 self.text.mark_set("insert", "end-1c")
1140 if self.reading:
1141 self.text.insert("insert", "\n")
1142 self.text.see("insert")
1143 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001144 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001145 self.text.tag_add("stdin", "iomark", "end-1c")
1146 self.text.update_idletasks()
1147 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001148 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001149 else:
1150 self.runit()
1151 return "break"
1152
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001153 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001154 # remove leading and trailing empty or whitespace lines
1155 s = re.sub(r'^\s*\n', '' , s)
1156 s = re.sub(r'\n\s*$', '', s)
1157 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001158 self.text.undo_block_start()
1159 try:
1160 self.text.tag_remove("sel", "1.0", "end")
1161 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001162 prefix = self.text.get("insert linestart", "insert")
1163 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001164 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001165 prefix = self.text.get("insert linestart", "insert")
1166 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001167 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001168 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1169 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001170 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001171 if line.startswith(orig_base_indent):
1172 # replace orig base indentation with new indentation
1173 line = new_base_indent + line[len(orig_base_indent):]
1174 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001175 finally:
1176 self.text.see("insert")
1177 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001178
1179 def runit(self):
1180 line = self.text.get("iomark", "end-1c")
1181 # Strip off last newline and surrounding whitespace.
1182 # (To allow you to hit return twice to end a statement.)
1183 i = len(line)
1184 while i > 0 and line[i-1] in " \t":
1185 i = i-1
1186 if i > 0 and line[i-1] == "\n":
1187 i = i-1
1188 while i > 0 and line[i-1] in " \t":
1189 i = i-1
1190 line = line[:i]
1191 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001192
David Scherer7aced172000-08-15 01:13:23 +00001193 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001194 if self.interp.rpcclt:
1195 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001196 try:
1197 sys.last_traceback
1198 except:
1199 tkMessageBox.showerror("No stack trace",
1200 "There is no stack trace yet.\n"
1201 "(sys.last_traceback is not defined)",
1202 master=self.text)
1203 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001204 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001205 sv = StackBrowser(self.root, self.flist)
1206
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001207 def view_restart_mark(self, event=None):
1208 self.text.see("iomark")
1209 self.text.see("restart")
1210
1211 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001212 "Callback for Run/Restart Shell Cntl-F6"
1213 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001214
David Scherer7aced172000-08-15 01:13:23 +00001215 def showprompt(self):
1216 self.resetoutput()
1217 try:
1218 s = str(sys.ps1)
1219 except:
1220 s = ""
1221 self.console.write(s)
1222 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001223 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001224 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001225
1226 def resetoutput(self):
1227 source = self.text.get("iomark", "end-1c")
1228 if self.history:
1229 self.history.history_store(source)
1230 if self.text.get("end-2c") != "\n":
1231 self.text.insert("end-1c", "\n")
1232 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001233 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001234
1235 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001236 try:
1237 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001238 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001239 self.text.mark_gravity("iomark", "left")
1240 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001241 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1242 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001243 if self.canceled:
1244 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001245 if not use_subprocess:
1246 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001247 return count
David Scherer7aced172000-08-15 01:13:23 +00001248
Andrew Svetlovd1837672012-11-01 22:41:19 +02001249 def rmenu_check_cut(self):
1250 try:
1251 if self.text.compare('sel.first', '<', 'iomark'):
1252 return 'disabled'
1253 except TclError: # no selection, so the index 'sel.first' doesn't exist
1254 return 'disabled'
1255 return super().rmenu_check_cut()
1256
1257 def rmenu_check_paste(self):
1258 if self.text.compare('insert','<','iomark'):
1259 return 'disabled'
1260 return super().rmenu_check_paste()
1261
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001262class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001263
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001264 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001265 self.shell = shell
1266 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001267 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001268
1269 def write(self, s):
Martin v. Löwis9ae3f7a2012-07-09 20:46:11 +02001270 if not isinstance(s, str):
1271 raise TypeError('must be str, not ' + type(s).__name__)
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001272 return self.shell.write(s, self.tags)
David Scherer7aced172000-08-15 01:13:23 +00001273
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001274 def writelines(self, lines):
1275 for line in lines:
1276 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001277
1278 def flush(self):
1279 pass
1280
1281 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001282 return True
David Scherer7aced172000-08-15 01:13:23 +00001283
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001284class PseudoInputFile(object):
1285 def __init__(self, shell):
1286 self.readline = shell.readline
1287 self.isatty = shell.isatty
1288
1289 def write(self, s):
1290 raise io.UnsupportedOperation("not writable")
1291 writelines = write
1292
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001293
David Scherer7aced172000-08-15 01:13:23 +00001294usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001295
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001296USAGE: idle [-deins] [-t title] [file]*
1297 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1298 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001299
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001300 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001301 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001302
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001303The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001304
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001305 -e open an edit window
1306 -i open a shell window
1307
1308The following options imply -i and will open a shell:
1309
1310 -c cmd run the command in a shell, or
1311 -r file run script from file
1312
1313 -d enable the debugger
1314 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1315 -t title set title of shell window
1316
1317A default edit window will be bypassed when -c, -r, or - are used.
1318
1319[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1320
1321Examples:
1322
1323idle
1324 Open an edit window or shell depending on IDLE's configuration.
1325
1326idle foo.py foobar.py
1327 Edit the files, also open a shell if configured to start with shell.
1328
1329idle -est "Baz" foo.py
1330 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1331 window with the title "Baz".
1332
Neal Norwitz752abd02008-05-13 04:55:24 +00001333idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 Open a shell window and run the command, passing "-c" in sys.argv[0]
1335 and "foo" in sys.argv[1].
1336
1337idle -d -s -r foo.py "Hello World"
1338 Open a shell window, run a startup script, enable the debugger, and
1339 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1340 sys.argv[1].
1341
Neal Norwitz752abd02008-05-13 04:55:24 +00001342echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1344 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001345"""
1346
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001347def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001349
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001350 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001351 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001352 enable_edit = False
1353 debug = False
1354 cmd = None
1355 script = None
1356 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001357 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001358 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001359 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001360 sys.stderr.write("Error: %s\n" % str(msg))
1361 sys.stderr.write(usage_msg)
1362 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001363 for o, a in opts:
1364 if o == '-c':
1365 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001366 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001367 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 debug = True
1369 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001372 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001373 if o == '-h':
1374 sys.stdout.write(usage_msg)
1375 sys.exit()
1376 if o == '-i':
1377 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001378 if o == '-n':
1379 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 if o == '-r':
1381 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 if os.path.isfile(script):
1383 pass
1384 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001385 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 sys.exit()
1387 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001388 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 startup = True
1390 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 if o == '-t':
1392 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001393 enable_shell = True
1394 if args and args[0] == '-':
1395 cmd = sys.stdin.read()
1396 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001397 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001398 for i in range(len(sys.path)):
1399 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001400 if args and args[0] == '-':
1401 sys.argv = [''] + args[1:]
1402 elif cmd:
1403 sys.argv = ['-c'] + args
1404 elif script:
1405 sys.argv = [script] + args
1406 elif args:
1407 enable_edit = True
1408 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001409 for filename in args:
1410 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 for dir in pathx:
1412 dir = os.path.abspath(dir)
1413 if not dir in sys.path:
1414 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001415 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001416 dir = os.getcwd()
1417 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001418 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 # check the IDLE settings configuration (but command line overrides)
1420 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001421 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001423 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001424 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001425
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001426 fixwordbreaks(root)
1427 root.withdraw()
1428 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001429 macosxSupport.setupApp(root, flist)
1430
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 if enable_edit:
1432 if not (cmd or script):
Andrew Svetlov0f71f442012-03-21 13:23:41 +02001433 for filename in args[:]:
1434 if flist.open(filename) is None:
1435 # filename is a directory actually, disconsider it
1436 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001437 if not args:
1438 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001439 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001440 shell = flist.open_shell()
1441 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001442 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001443
1444 if macosxSupport.runningAsOSXApp() and flist.dict:
1445 # On OSX: when the user has double-clicked on a file that causes
1446 # IDLE to be launched the shell window will open just in front of
1447 # the file she wants to see. Lower the interpreter window when
1448 # there are open files.
1449 shell.top.lower()
1450
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001451 shell = flist.pyshell
1452 # handle remaining options:
1453 if debug:
1454 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001455 if startup:
1456 filename = os.environ.get("IDLESTARTUP") or \
1457 os.environ.get("PYTHONSTARTUP")
1458 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001459 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001460 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001461 shell.interp.runcommand("""if 1:
1462 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001463 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001464 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001465 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001466 if cmd:
1467 shell.interp.execsource(cmd)
1468 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001469 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001470 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001471
Ned Deily4ce92b22011-01-15 04:37:12 +00001472 # Check for problematic OS X Tk versions and print a warning message
1473 # in the IDLE shell window; this is less intrusive than always opening
1474 # a separate window.
1475 tkversionwarning = macosxSupport.tkVersionWarning(root)
1476 if tkversionwarning:
1477 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1478
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001479 while flist.inversedict: # keep IDLE running while files are open.
1480 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001481 root.destroy()
1482
David Scherer7aced172000-08-15 01:13:23 +00001483if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001484 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001485 main()