blob: e7c71b7c69b060743332d1f3c0b0851e5e5e5efe [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
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
Georg Brandl14fc4272008-05-17 18:39:55 +000020 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000022 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000023 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000025import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000026
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000027from idlelib.EditorWindow import EditorWindow, fixwordbreaks
28from idlelib.FileList import FileList
29from idlelib.ColorDelegator import ColorDelegator
30from idlelib.UndoDelegator import UndoDelegator
31from idlelib.OutputWindow import OutputWindow
32from idlelib.configHandler import idleConf
33from idlelib import idlever
34from idlelib import rpc
35from idlelib import Debugger
36from idlelib import RemoteDebugger
37from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaisere866c812009-04-04 21:07:39 +000039HOST = '127.0.0.1' # python execution server on localhost loopback
40PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000042# Override warnings module to write to warning_stream. Initialize to send IDLE
43# internal warnings to the console. ScriptBinding.check_syntax() will
44# temporarily redirect the stream to the shell window to display warnings when
45# checking user's code.
46global warning_stream
47warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000048try:
49 import warnings
50except ImportError:
51 pass
52else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000053 def idle_showwarning(message, category, filename, lineno,
54 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000055 if file is None:
56 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000057 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000058 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070059 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000060 except IOError:
61 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000062 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000063 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000064 """Format warnings the IDLE way"""
65 s = "\nWarning (from warnings module):\n"
66 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000067 if line is None:
68 line = linecache.getline(filename, lineno)
69 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000070 if line:
71 s += " %s\n" % line
72 s += "%s: %s\n>>> " % (category.__name__, message)
73 return s
74 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000082 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086 """
David Scherer7aced172000-08-15 01:13:23 +000087 cache = linecache.cache
88 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000089 for key in list(cache):
90 if key[:1] + key[-1:] == '<>':
91 save[key] = cache.pop(key)
92 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000093 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000094
Kurt B. Kaiser81885592002-11-29 22:10:53 +000095# Patch linecache.checkcache():
96linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000097
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000098
David Scherer7aced172000-08-15 01:13:23 +000099class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000100 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000101
David Scherer7aced172000-08-15 01:13:23 +0000102 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000104 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000105 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
108
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000109 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
110 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000111 # whenever a file is changed, restore breakpoints
112 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000113 def filename_changed_hook(old_hook=self.io.filename_change_hook,
114 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000115 self.restore_file_breaks()
116 old_hook()
117 self.io.set_filename_change_hook(filename_changed_hook)
118
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000119 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
120 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000121
Chui Teya2adb0f2002-11-04 22:14:54 +0000122 def set_breakpoint(self, lineno):
123 text = self.text
124 filename = self.io.filename
125 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
126 try:
127 i = self.breakpoints.index(lineno)
128 except ValueError: # only add if missing, i.e. do once
129 self.breakpoints.append(lineno)
130 try: # update the subprocess debugger
131 debug = self.flist.pyshell.interp.debugger
132 debug.set_breakpoint_here(filename, lineno)
133 except: # but debugger may not be active right now....
134 pass
135
David Scherer7aced172000-08-15 01:13:23 +0000136 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000137 text = self.text
138 filename = self.io.filename
139 if not filename:
140 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000141 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000142 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000143 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000144
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000145 def clear_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()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000150 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000151 lineno = int(float(text.index("insert")))
152 try:
153 self.breakpoints.remove(lineno)
154 except:
155 pass
156 text.tag_remove("BREAK", "insert linestart",\
157 "insert lineend +1char")
158 try:
159 debug = self.flist.pyshell.interp.debugger
160 debug.clear_breakpoint_here(filename, lineno)
161 except:
162 pass
163
164 def clear_file_breaks(self):
165 if self.breakpoints:
166 text = self.text
167 filename = self.io.filename
168 if not filename:
169 text.bell()
170 return
171 self.breakpoints = []
172 text.tag_remove("BREAK", "1.0", END)
173 try:
174 debug = self.flist.pyshell.interp.debugger
175 debug.clear_file_breaks(filename)
176 except:
177 pass
178
Chui Teya2adb0f2002-11-04 22:14:54 +0000179 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000180 "Save breakpoints when file is saved"
181 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
182 # be run. The breaks are saved at that time. If we introduce
183 # a temporary file save feature the save breaks functionality
184 # needs to be re-verified, since the breaks at the time the
185 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000186 # permanent save of the file. Currently, a break introduced
187 # after a save will be effective, but not persistent.
188 # This is necessary to keep the saved breaks synched with the
189 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000190 #
191 # Breakpoints are set as tagged ranges in the text. Certain
192 # kinds of edits cause these ranges to be deleted: Inserting
193 # or deleting a line just before a breakpoint, and certain
194 # deletions prior to a breakpoint. These issues need to be
195 # investigated and understood. It's not clear if they are
196 # Tk issues or IDLE issues, or whether they can actually
197 # be fixed. Since a modified file has to be saved before it is
198 # run, and since self.breakpoints (from which the subprocess
199 # debugger is loaded) is updated during the save, the visible
200 # breaks stay synched with the subprocess even if one of these
201 # unexpected breakpoint deletions occurs.
202 breaks = self.breakpoints
203 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000204 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200205 with open(self.breakpointPath, "r") as fp:
206 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800209 try:
210 with open(self.breakpointPath, "w") as new_file:
211 for line in lines:
212 if not line.startswith(filename + '='):
213 new_file.write(line)
214 self.update_breakpoints()
215 breaks = self.breakpoints
216 if breaks:
217 new_file.write(filename + '=' + str(breaks) + '\n')
218 except IOError as err:
219 if not getattr(self.root, "breakpoint_error_displayed", False):
220 self.root.breakpoint_error_displayed = True
221 tkMessageBox.showerror(title='IDLE Error',
222 message='Unable to update breakpoint list:\n%s'
223 % str(err),
224 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000225
226 def restore_file_breaks(self):
227 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000228 filename = self.io.filename
229 if filename is None:
230 return
Chui Tey69371d62002-11-04 23:39:45 +0000231 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200232 with open(self.breakpointPath, "r") as fp:
233 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000234 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000236 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000237 for breakpoint_linenumber in breakpoint_linenumbers:
238 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000239
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 def update_breakpoints(self):
241 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000242 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000243 ranges = text.tag_ranges("BREAK")
244 linenumber_list = self.ranges_to_linenumbers(ranges)
245 self.breakpoints = linenumber_list
246
247 def ranges_to_linenumbers(self, ranges):
248 lines = []
249 for index in range(0, len(ranges), 2):
250 lineno = int(float(ranges[index]))
251 end = int(float(ranges[index+1]))
252 while lineno < end:
253 lines.append(lineno)
254 lineno += 1
255 return lines
256
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000257# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000258# def saved_change_hook(self):
259# "Extend base method - clear breaks if module is modified"
260# if not self.get_saved():
261# self.clear_file_breaks()
262# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000263
264 def _close(self):
265 "Extend base method - clear breaks when module is closed"
266 self.clear_file_breaks()
267 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000268
David Scherer7aced172000-08-15 01:13:23 +0000269
270class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000271 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000272
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 # override FileList's class variable, instances return PyShellEditorWindow
274 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000275 EditorWindow = PyShellEditorWindow
276
277 pyshell = None
278
279 def open_shell(self, event=None):
280 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000282 else:
283 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000284 if self.pyshell:
285 if not self.pyshell.begin():
286 return None
David Scherer7aced172000-08-15 01:13:23 +0000287 return self.pyshell
288
289
290class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000291 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000292
Steven M. Gavab77d3432002-03-02 07:16:21 +0000293 def __init__(self):
294 ColorDelegator.__init__(self)
295 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000296
297 def recolorize_main(self):
298 self.tag_remove("TODO", "1.0", "iomark")
299 self.tag_add("SYNC", "1.0", "iomark")
300 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000301
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 def LoadTagDefs(self):
303 ColorDelegator.LoadTagDefs(self)
304 theme = idleConf.GetOption('main','Theme','name')
305 self.tagdefs.update({
306 "stdin": {'background':None,'foreground':None},
307 "stdout": idleConf.GetHighlight(theme, "stdout"),
308 "stderr": idleConf.GetHighlight(theme, "stderr"),
309 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000310 })
David Scherer7aced172000-08-15 01:13:23 +0000311
David Scherer7aced172000-08-15 01:13:23 +0000312class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000313 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000314
315 def insert(self, index, chars, tags=None):
316 try:
317 if self.delegate.compare(index, "<", "iomark"):
318 self.delegate.bell()
319 return
320 except TclError:
321 pass
322 UndoDelegator.insert(self, index, chars, tags)
323
324 def delete(self, index1, index2=None):
325 try:
326 if self.delegate.compare(index1, "<", "iomark"):
327 self.delegate.bell()
328 return
329 except TclError:
330 pass
331 UndoDelegator.delete(self, index1, index2)
332
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000333
334class MyRPCClient(rpc.RPCClient):
335
336 def handle_EOF(self):
337 "Override the base class - just re-raise EOFError"
338 raise EOFError
339
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000340
David Scherer7aced172000-08-15 01:13:23 +0000341class ModifiedInterpreter(InteractiveInterpreter):
342
343 def __init__(self, tkconsole):
344 self.tkconsole = tkconsole
345 locals = sys.modules['__main__'].__dict__
346 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000347 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000348 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000349 self.subprocess_arglist = None
350 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700351 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000352
Chui Tey5d2af632002-05-26 13:36:41 +0000353 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700354 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000355
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000356 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000357 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000358 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700359 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000360
Tony Lowndsf53dec22002-12-20 04:24:43 +0000361 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000362 assert (self.port!=0), (
363 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000364 w = ['-W' + s for s in sys.warnoptions]
365 # Maybe IDLE is installed and is being accessed via sys.path,
366 # or maybe it's not installed and the idle.py script is being
367 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000368 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
369 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000370 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000371 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000372 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000373 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700374 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000375
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000376 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000377 addr = (HOST, self.port)
378 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000379 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000380 time.sleep(i)
381 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000382 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000383 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000384 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000385 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000386 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000387 self.display_port_binding_error()
388 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000389 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
390 self.port = self.rpcclt.listening_sock.getsockname()[1]
391 # if PORT was not 0, probably working with a remote execution server
392 if PORT != 0:
393 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
394 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
395 # on Windows since the implementation allows two active sockets on
396 # the same address!
397 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
398 socket.SO_REUSEADDR, 1)
399 self.spawn_subprocess()
400 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000401 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000402 self.rpcclt.listening_sock.settimeout(10)
403 try:
404 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000405 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000406 self.display_no_subprocess_error()
407 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000408 self.rpcclt.register("stdin", self.tkconsole)
409 self.rpcclt.register("stdout", self.tkconsole.stdout)
410 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000411 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000412 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000413 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000414 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000415 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000416 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000417
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000418 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000419 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000420 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000421 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000422 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000423 debug = self.getdebugger()
424 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000425 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000426 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000427 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
428 except:
429 pass
430 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000431 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700432 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000433 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000435 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000436 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000437 try:
438 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000439 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000440 self.display_no_subprocess_error()
441 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000442 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000443 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000444 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000445 if was_executing:
446 console.write('\n')
447 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000448 halfbar = ((int(console.width) - 16) // 2) * '='
449 console.write(halfbar + ' RESTART ' + halfbar)
450 console.text.mark_set("restart", "end-1c")
451 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000452 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000454 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000455 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000456 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000457 # reload remote debugger breakpoints for all PyShellEditWindows
458 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700459 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000460 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000461 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000462
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000463 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000464 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000465
466 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000467 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000468
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000469 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000470 try:
471 self.rpcclt.close()
472 except AttributeError: # no socket
473 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700474 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000475 self.tkconsole.executing = False
476 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000477
Ned Deilye5cad232011-08-02 18:47:13 -0700478 def terminate_subprocess(self):
479 "Make sure subprocess is terminated"
480 try:
481 self.rpcsubproc.kill()
482 except OSError:
483 # process already terminated
484 return
485 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000486 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700487 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000488 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000489 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000490
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000491 def transfer_path(self):
492 self.runcommand("""if 1:
493 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000494 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000495 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000496 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000497
Chui Tey5d2af632002-05-26 13:36:41 +0000498 active_seq = None
499
500 def poll_subprocess(self):
501 clt = self.rpcclt
502 if clt is None:
503 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000504 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000505 response = clt.pollresponse(self.active_seq, wait=0.05)
506 except (EOFError, IOError, KeyboardInterrupt):
507 # lost connection or subprocess terminated itself, restart
508 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000509 if self.tkconsole.closing:
510 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000511 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000512 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000513 if response:
514 self.tkconsole.resetoutput()
515 self.active_seq = None
516 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000517 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000518 if how == "OK":
519 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000520 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000521 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000522 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
523 self.remote_stack_viewer()
524 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000525 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000526 print(errmsg, what, file=sys.__stderr__)
527 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000528 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000529 try:
530 self.tkconsole.endexecuting()
531 except AttributeError: # shell may have closed
532 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000533 # Reschedule myself
534 if not self.tkconsole.closing:
535 self.tkconsole.text.after(self.tkconsole.pollinterval,
536 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000537
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000538 debugger = None
539
540 def setdebugger(self, debugger):
541 self.debugger = debugger
542
543 def getdebugger(self):
544 return self.debugger
545
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000546 def open_remote_stack_viewer(self):
547 """Initiate the remote stack viewer from a separate thread.
548
549 This method is called from the subprocess, and by returning from this
550 method we allow the subprocess to unblock. After a bit the shell
551 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000552 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000553 the RPC mechanism.
554
555 """
556 self.tkconsole.text.after(300, self.remote_stack_viewer)
557 return
558
Chui Tey5d2af632002-05-26 13:36:41 +0000559 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000560 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000561 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000562 if oid is None:
563 self.tkconsole.root.bell()
564 return
565 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000566 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000567 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000568 theme = idleConf.GetOption('main','Theme','name')
569 background = idleConf.GetHighlight(theme, 'normal')['background']
570 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000571 sc.frame.pack(expand=1, fill="both")
572 node = TreeNode(sc.canvas, None, item)
573 node.expand()
574 # XXX Should GC the remote tree when closing the window
575
David Scherer7aced172000-08-15 01:13:23 +0000576 gid = 0
577
578 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000579 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000580 filename = self.stuffsource(source)
581 self.execfile(filename, source)
582
583 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000584 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000585 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200586 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200587 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000588 try:
589 code = compile(source, filename, "exec")
590 except (OverflowError, SyntaxError):
591 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000592 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000593 print('*** Error in script or command!\n', file=tkerr)
594 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000595 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000596 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000597 else:
598 self.runcode(code)
599
600 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000601 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000602 filename = self.stuffsource(source)
603 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000604 self.save_warnings_filters = warnings.filters[:]
605 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000606 # at the moment, InteractiveInterpreter expects str
607 assert isinstance(source, str)
608 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000609 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000610 # try:
611 # source = source.encode(IOBinding.encoding)
612 # except UnicodeError:
613 # self.tkconsole.resetoutput()
614 # self.write("Unsupported characters in input\n")
615 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000616 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000617 # InteractiveInterpreter.runsource() calls its runcode() method,
618 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000619 return InteractiveInterpreter.runsource(self, source, filename)
620 finally:
621 if self.save_warnings_filters is not None:
622 warnings.filters[:] = self.save_warnings_filters
623 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000624
625 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000626 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000627 filename = "<pyshell#%d>" % self.gid
628 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000629 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000630 linecache.cache[filename] = len(source)+1, 0, lines, filename
631 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000632
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000633 def prepend_syspath(self, filename):
634 "Prepend sys.path with file's directory if not already included"
635 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000636 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000637 import sys as _sys
638 from os.path import dirname as _dirname
639 _dir = _dirname(_filename)
640 if not _dir in _sys.path:
641 _sys.path.insert(0, _dir)
642 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000643 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000644
David Scherer7aced172000-08-15 01:13:23 +0000645 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000646 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000647
648 Color the offending position instead of printing it and pointing at it
649 with a caret.
650
651 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000652 tkconsole = self.tkconsole
653 text = tkconsole.text
654 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000655 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700656 msg = getattr(value, 'msg', '') or value or "<no detail available>"
657 lineno = getattr(value, 'lineno', '') or 1
658 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000659 if offset == 0:
660 lineno += 1 #mark end of offending line
661 if lineno == 1:
662 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000663 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000664 pos = "iomark linestart + %d lines + %d chars" % \
665 (lineno-1, offset-1)
666 tkconsole.colorize_syntax_error(text, pos)
667 tkconsole.resetoutput()
668 self.write("SyntaxError: %s\n" % msg)
669 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000670
671 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000672 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000673 self.tkconsole.resetoutput()
674 self.checklinecache()
675 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000676 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
677 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000678
679 def checklinecache(self):
680 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000681 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000682 if key[:1] + key[-1:] != "<>":
683 del c[key]
684
Chui Tey5d2af632002-05-26 13:36:41 +0000685 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000686 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000687 # The code better not raise an exception!
688 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000689 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000690 return 0
691 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000692 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000693 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000694 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000695 return 1
696
David Scherer7aced172000-08-15 01:13:23 +0000697 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000698 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000699 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000700 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000701 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000702 if self.save_warnings_filters is not None:
703 warnings.filters[:] = self.save_warnings_filters
704 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000705 debugger = self.debugger
706 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000707 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000708 if not debugger and self.rpcclt is not None:
709 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
710 (code,), {})
711 elif debugger:
712 debugger.run(code, self.locals)
713 else:
714 exec(code, self.locals)
715 except SystemExit:
716 if not self.tkconsole.closing:
717 if tkMessageBox.askyesno(
718 "Exit?",
719 "Do you want to exit altogether?",
720 default="yes",
721 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000722 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000723 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000724 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000725 else:
726 raise
727 except:
728 if use_subprocess:
729 print("IDLE internal error in runcode()",
730 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000731 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000732 self.tkconsole.endexecuting()
733 else:
734 if self.tkconsole.canceled:
735 self.tkconsole.canceled = False
736 print("KeyboardInterrupt", file=self.tkconsole.stderr)
737 else:
738 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000739 finally:
740 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000741 try:
742 self.tkconsole.endexecuting()
743 except AttributeError: # shell may have closed
744 pass
David Scherer7aced172000-08-15 01:13:23 +0000745
746 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000747 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000748 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000749
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000750 def display_port_binding_error(self):
751 tkMessageBox.showerror(
752 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000753 "IDLE can't bind to a TCP/IP port, which is necessary to "
754 "communicate with its Python execution server. This might be "
755 "because no networking is installed on this computer. "
756 "Run IDLE with the -n command line switch to start without a "
757 "subprocess and refer to Help/IDLE Help 'Running without a "
758 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000759 master=self.tkconsole.text)
760
761 def display_no_subprocess_error(self):
762 tkMessageBox.showerror(
763 "Subprocess Startup Error",
764 "IDLE's subprocess didn't make connection. Either IDLE can't "
765 "start a subprocess or personal firewall software is blocking "
766 "the connection.",
767 master=self.tkconsole.text)
768
769 def display_executing_dialog(self):
770 tkMessageBox.showerror(
771 "Already executing",
772 "The Python Shell window is already executing a command; "
773 "please wait until it is finished.",
774 master=self.tkconsole.text)
775
776
David Scherer7aced172000-08-15 01:13:23 +0000777class PyShell(OutputWindow):
778
779 shell_title = "Python Shell"
780
781 # Override classes
782 ColorDelegator = ModifiedColorDelegator
783 UndoDelegator = ModifiedUndoDelegator
784
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000785 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000786 menu_specs = [
787 ("file", "_File"),
788 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000789 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000790 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000791 ("windows", "_Windows"),
792 ("help", "_Help"),
793 ]
David Scherer7aced172000-08-15 01:13:23 +0000794
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000795 if macosxSupport.runningAsOSXApp():
796 del menu_specs[-3]
797 menu_specs[-2] = ("windows", "_Window")
798
799
David Scherer7aced172000-08-15 01:13:23 +0000800 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000801 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000802
803 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000804 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000805 ms = self.menu_specs
806 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000807 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000808 self.interp = ModifiedInterpreter(self)
809 if flist is None:
810 root = Tk()
811 fixwordbreaks(root)
812 root.withdraw()
813 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000814 #
David Scherer7aced172000-08-15 01:13:23 +0000815 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000816 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000817## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
818 self.usetabs = True
819 # indentwidth must be 8 when using tabs. See note in EditorWindow:
820 self.indentwidth = 8
821 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000822 #
David Scherer7aced172000-08-15 01:13:23 +0000823 text = self.text
824 text.configure(wrap="char")
825 text.bind("<<newline-and-indent>>", self.enter_callback)
826 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
827 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000828 text.bind("<<end-of-file>>", self.eof_callback)
829 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000830 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000831 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000832 self.color = color = self.ColorDelegator()
833 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000834 if use_subprocess:
835 text.bind("<<view-restart>>", self.view_restart_mark)
836 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
David Scherer7aced172000-08-15 01:13:23 +0000838 self.save_stdout = sys.stdout
839 self.save_stderr = sys.stderr
840 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000841 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000842 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
843 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
844 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000845 if not use_subprocess:
846 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000847 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000848 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000849 try:
850 # page help() text to shell.
851 import pydoc # import must be done here to capture i/o rebinding.
852 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
853 pydoc.pager = pydoc.plainpager
854 except:
855 sys.stderr = sys.__stderr__
856 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000857 #
David Scherer7aced172000-08-15 01:13:23 +0000858 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000859 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000860 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000861
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000862 def get_standard_extension_names(self):
863 return idleConf.GetExtensions(shell_only=True)
864
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000865 reading = False
866 executing = False
867 canceled = False
868 endoffile = False
869 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000870
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000871 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000872 global warning_stream
873 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000874
875 def get_warning_stream(self):
876 return warning_stream
877
David Scherer7aced172000-08-15 01:13:23 +0000878 def toggle_debugger(self, event=None):
879 if self.executing:
880 tkMessageBox.showerror("Don't debug now",
881 "You can only toggle the debugger when idle",
882 master=self.text)
883 self.set_debugger_indicator()
884 return "break"
885 else:
886 db = self.interp.getdebugger()
887 if db:
888 self.close_debugger()
889 else:
890 self.open_debugger()
891
892 def set_debugger_indicator(self):
893 db = self.interp.getdebugger()
894 self.setvar("<<toggle-debugger>>", not not db)
895
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000896 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000897 pass # All we need is the variable
898
899 def close_debugger(self):
900 db = self.interp.getdebugger()
901 if db:
902 self.interp.setdebugger(None)
903 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000904 if self.interp.rpcclt:
905 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000906 self.resetoutput()
907 self.console.write("[DEBUG OFF]\n")
908 sys.ps1 = ">>> "
909 self.showprompt()
910 self.set_debugger_indicator()
911
912 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000913 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000914 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
915 self)
916 else:
917 dbg_gui = Debugger.Debugger(self)
918 self.interp.setdebugger(dbg_gui)
919 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000920 sys.ps1 = "[DEBUG ON]\n>>> "
921 self.showprompt()
922 self.set_debugger_indicator()
923
David Scherer7aced172000-08-15 01:13:23 +0000924 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000925 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000926 self.resetoutput()
927 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000928
929 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000930 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000931 self.executing = 0
932 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000933 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000934
935 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000936 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000937 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000938 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000939 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000940 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000941 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000942 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000943 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000944 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000945 if self.reading:
946 self.top.quit()
947 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000948 self.closing = True
949 # Wait for poll_subprocess() rescheduling to stop
950 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000951
952 def close2(self):
953 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000954
955 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000956 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000957 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000958 if use_subprocess:
959 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000960 # Restore std streams
961 sys.stdout = self.save_stdout
962 sys.stderr = self.save_stderr
963 sys.stdin = self.save_stdin
964 # Break cycles
965 self.interp = None
966 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000967 self.flist.pyshell = None
968 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000969 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000970
971 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000972 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000973 return True
David Scherer7aced172000-08-15 01:13:23 +0000974
975 def short_title(self):
976 return self.shell_title
977
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000978 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000979 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000980
David Scherer7aced172000-08-15 01:13:23 +0000981 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000982 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000983 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 if use_subprocess:
985 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000986 client = self.interp.start_subprocess()
987 if not client:
988 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000989 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000990 else:
991 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000992 self.write("Python %s on %s\n%s\n%s" %
993 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000994 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000995 import tkinter
996 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000997 return True
David Scherer7aced172000-08-15 01:13:23 +0000998
999 def readline(self):
1000 save = self.reading
1001 try:
1002 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001003 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001004 finally:
1005 self.reading = save
1006 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001007 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1008 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001009 self.resetoutput()
1010 if self.canceled:
1011 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001012 if not use_subprocess:
1013 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001014 if self.endoffile:
1015 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001016 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001017 return line
1018
1019 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001020 return True
David Scherer7aced172000-08-15 01:13:23 +00001021
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001022 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001023 try:
1024 if self.text.compare("sel.first", "!=", "sel.last"):
1025 return # Active selection -- always use default binding
1026 except:
1027 pass
1028 if not (self.executing or self.reading):
1029 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001030 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001031 self.showprompt()
1032 return "break"
1033 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001034 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001035 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001036 if self.interp.getdebugger():
1037 self.interp.restart_subprocess()
1038 else:
1039 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001040 if self.reading:
1041 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001042 return "break"
1043
1044 def eof_callback(self, event):
1045 if self.executing and not self.reading:
1046 return # Let the default binding (delete next char) take over
1047 if not (self.text.compare("iomark", "==", "insert") and
1048 self.text.compare("insert", "==", "end-1c")):
1049 return # Let the default binding (delete next char) take over
1050 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001051 self.resetoutput()
1052 self.close()
1053 else:
1054 self.canceled = 0
1055 self.endoffile = 1
1056 self.top.quit()
1057 return "break"
1058
David Scherer7aced172000-08-15 01:13:23 +00001059 def linefeed_callback(self, event):
1060 # Insert a linefeed without entering anything (still autoindented)
1061 if self.reading:
1062 self.text.insert("insert", "\n")
1063 self.text.see("insert")
1064 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001065 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001066 return "break"
1067
1068 def enter_callback(self, event):
1069 if self.executing and not self.reading:
1070 return # Let the default binding (insert '\n') take over
1071 # If some text is selected, recall the selection
1072 # (but only if this before the I/O mark)
1073 try:
1074 sel = self.text.get("sel.first", "sel.last")
1075 if sel:
1076 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001077 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001078 return "break"
1079 except:
1080 pass
1081 # If we're strictly before the line containing iomark, recall
1082 # the current line, less a leading prompt, less leading or
1083 # trailing whitespace
1084 if self.text.compare("insert", "<", "iomark linestart"):
1085 # Check if there's a relevant stdin range -- if so, use it
1086 prev = self.text.tag_prevrange("stdin", "insert")
1087 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001088 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001089 return "break"
1090 next = self.text.tag_nextrange("stdin", "insert")
1091 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001092 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001093 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001094 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001095 indices = self.text.tag_nextrange("console", "insert linestart")
1096 if indices and \
1097 self.text.compare(indices[0], "<=", "insert linestart"):
1098 self.recall(self.text.get(indices[1], "insert lineend"), event)
1099 else:
1100 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001101 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001102 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001103 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001104 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001105 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001106 # If we're in the current input and there's only whitespace
1107 # beyond the cursor, erase that whitespace first
1108 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001109 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001110 self.text.delete("insert", "end-1c")
1111 # If we're in the current input before its last line,
1112 # insert a newline right at the insert point
1113 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001114 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001115 return "break"
1116 # We're in the last line; append a newline and submit it
1117 self.text.mark_set("insert", "end-1c")
1118 if self.reading:
1119 self.text.insert("insert", "\n")
1120 self.text.see("insert")
1121 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001122 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001123 self.text.tag_add("stdin", "iomark", "end-1c")
1124 self.text.update_idletasks()
1125 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001126 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001127 else:
1128 self.runit()
1129 return "break"
1130
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001131 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001132 # remove leading and trailing empty or whitespace lines
1133 s = re.sub(r'^\s*\n', '' , s)
1134 s = re.sub(r'\n\s*$', '', s)
1135 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001136 self.text.undo_block_start()
1137 try:
1138 self.text.tag_remove("sel", "1.0", "end")
1139 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001140 prefix = self.text.get("insert linestart", "insert")
1141 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001142 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001143 prefix = self.text.get("insert linestart", "insert")
1144 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001145 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001146 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1147 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001148 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001149 if line.startswith(orig_base_indent):
1150 # replace orig base indentation with new indentation
1151 line = new_base_indent + line[len(orig_base_indent):]
1152 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001153 finally:
1154 self.text.see("insert")
1155 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001156
1157 def runit(self):
1158 line = self.text.get("iomark", "end-1c")
1159 # Strip off last newline and surrounding whitespace.
1160 # (To allow you to hit return twice to end a statement.)
1161 i = len(line)
1162 while i > 0 and line[i-1] in " \t":
1163 i = i-1
1164 if i > 0 and line[i-1] == "\n":
1165 i = i-1
1166 while i > 0 and line[i-1] in " \t":
1167 i = i-1
1168 line = line[:i]
1169 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001170
David Scherer7aced172000-08-15 01:13:23 +00001171 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001172 if self.interp.rpcclt:
1173 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001174 try:
1175 sys.last_traceback
1176 except:
1177 tkMessageBox.showerror("No stack trace",
1178 "There is no stack trace yet.\n"
1179 "(sys.last_traceback is not defined)",
1180 master=self.text)
1181 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001182 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001183 sv = StackBrowser(self.root, self.flist)
1184
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001185 def view_restart_mark(self, event=None):
1186 self.text.see("iomark")
1187 self.text.see("restart")
1188
1189 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001190 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001191
David Scherer7aced172000-08-15 01:13:23 +00001192 def showprompt(self):
1193 self.resetoutput()
1194 try:
1195 s = str(sys.ps1)
1196 except:
1197 s = ""
1198 self.console.write(s)
1199 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001200 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001201 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001202
1203 def resetoutput(self):
1204 source = self.text.get("iomark", "end-1c")
1205 if self.history:
1206 self.history.history_store(source)
1207 if self.text.get("end-2c") != "\n":
1208 self.text.insert("end-1c", "\n")
1209 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001210 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001211
1212 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001213 try:
1214 self.text.mark_gravity("iomark", "right")
1215 OutputWindow.write(self, s, tags, "iomark")
1216 self.text.mark_gravity("iomark", "left")
1217 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001218 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1219 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001220 if self.canceled:
1221 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001222 if not use_subprocess:
1223 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001224
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001225class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001226
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001227 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001228 self.shell = shell
1229 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001230 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001231
1232 def write(self, s):
1233 self.shell.write(s, self.tags)
1234
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001235 def writelines(self, lines):
1236 for line in lines:
1237 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001238
1239 def flush(self):
1240 pass
1241
1242 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001243 return True
David Scherer7aced172000-08-15 01:13:23 +00001244
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001245
David Scherer7aced172000-08-15 01:13:23 +00001246usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001247
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001248USAGE: idle [-deins] [-t title] [file]*
1249 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1250 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001251
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001252 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001253 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001254
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001255The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001256
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001257 -e open an edit window
1258 -i open a shell window
1259
1260The following options imply -i and will open a shell:
1261
1262 -c cmd run the command in a shell, or
1263 -r file run script from file
1264
1265 -d enable the debugger
1266 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1267 -t title set title of shell window
1268
1269A default edit window will be bypassed when -c, -r, or - are used.
1270
1271[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1272
1273Examples:
1274
1275idle
1276 Open an edit window or shell depending on IDLE's configuration.
1277
1278idle foo.py foobar.py
1279 Edit the files, also open a shell if configured to start with shell.
1280
1281idle -est "Baz" foo.py
1282 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1283 window with the title "Baz".
1284
Neal Norwitz752abd02008-05-13 04:55:24 +00001285idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001286 Open a shell window and run the command, passing "-c" in sys.argv[0]
1287 and "foo" in sys.argv[1].
1288
1289idle -d -s -r foo.py "Hello World"
1290 Open a shell window, run a startup script, enable the debugger, and
1291 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1292 sys.argv[1].
1293
Neal Norwitz752abd02008-05-13 04:55:24 +00001294echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001295 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1296 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001297"""
1298
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001299def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001300 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001301
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001302 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001303 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001304 enable_edit = False
1305 debug = False
1306 cmd = None
1307 script = None
1308 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001309 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001310 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001311 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001312 sys.stderr.write("Error: %s\n" % str(msg))
1313 sys.stderr.write(usage_msg)
1314 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001315 for o, a in opts:
1316 if o == '-c':
1317 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001318 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001319 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001320 debug = True
1321 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001323 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001324 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001325 if o == '-h':
1326 sys.stdout.write(usage_msg)
1327 sys.exit()
1328 if o == '-i':
1329 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001330 if o == '-n':
1331 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 if o == '-r':
1333 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 if os.path.isfile(script):
1335 pass
1336 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001337 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001338 sys.exit()
1339 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001340 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 startup = True
1342 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001343 if o == '-t':
1344 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 enable_shell = True
1346 if args and args[0] == '-':
1347 cmd = sys.stdin.read()
1348 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001349 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001350 for i in range(len(sys.path)):
1351 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001352 if args and args[0] == '-':
1353 sys.argv = [''] + args[1:]
1354 elif cmd:
1355 sys.argv = ['-c'] + args
1356 elif script:
1357 sys.argv = [script] + args
1358 elif args:
1359 enable_edit = True
1360 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001361 for filename in args:
1362 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 for dir in pathx:
1364 dir = os.path.abspath(dir)
1365 if not dir in sys.path:
1366 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001367 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001368 dir = os.getcwd()
1369 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001370 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 # check the IDLE settings configuration (but command line overrides)
1372 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001373 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001374 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001376 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001377
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001378 fixwordbreaks(root)
1379 root.withdraw()
1380 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001381 macosxSupport.setupApp(root, flist)
1382
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001383 if enable_edit:
1384 if not (cmd or script):
1385 for filename in args:
1386 flist.open(filename)
1387 if not args:
1388 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001389 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001390 shell = flist.open_shell()
1391 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001392 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001393
1394 if macosxSupport.runningAsOSXApp() and flist.dict:
1395 # On OSX: when the user has double-clicked on a file that causes
1396 # IDLE to be launched the shell window will open just in front of
1397 # the file she wants to see. Lower the interpreter window when
1398 # there are open files.
1399 shell.top.lower()
1400
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001401 shell = flist.pyshell
1402 # handle remaining options:
1403 if debug:
1404 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001405 if startup:
1406 filename = os.environ.get("IDLESTARTUP") or \
1407 os.environ.get("PYTHONSTARTUP")
1408 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001409 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001410 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 shell.interp.runcommand("""if 1:
1412 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001413 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001414 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001415 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 if cmd:
1417 shell.interp.execsource(cmd)
1418 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001419 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001420 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001421
Ned Deily4ce92b22011-01-15 04:37:12 +00001422 # Check for problematic OS X Tk versions and print a warning message
1423 # in the IDLE shell window; this is less intrusive than always opening
1424 # a separate window.
1425 tkversionwarning = macosxSupport.tkVersionWarning(root)
1426 if tkversionwarning:
1427 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1428
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001429 root.mainloop()
1430 root.destroy()
1431
David Scherer7aced172000-08-15 01:13:23 +00001432if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001433 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001434 main()