blob: 86e4eedf873dc2b69ea2be1d9df5f663ab8a62c3 [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:
Ned Deily55f87572011-11-05 22:36:44 -0700471 self.rpcclt.listening_sock.close()
472 except AttributeError: # no socket
473 pass
474 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000475 self.rpcclt.close()
476 except AttributeError: # no socket
477 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700478 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 self.tkconsole.executing = False
480 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000481
Ned Deilye5cad232011-08-02 18:47:13 -0700482 def terminate_subprocess(self):
483 "Make sure subprocess is terminated"
484 try:
485 self.rpcsubproc.kill()
486 except OSError:
487 # process already terminated
488 return
489 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700491 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000492 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000494
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000495 def transfer_path(self):
496 self.runcommand("""if 1:
497 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000498 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000499 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000500 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000501
Chui Tey5d2af632002-05-26 13:36:41 +0000502 active_seq = None
503
504 def poll_subprocess(self):
505 clt = self.rpcclt
506 if clt is None:
507 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000508 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000509 response = clt.pollresponse(self.active_seq, wait=0.05)
510 except (EOFError, IOError, KeyboardInterrupt):
511 # lost connection or subprocess terminated itself, restart
512 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000513 if self.tkconsole.closing:
514 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000515 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000516 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000517 if response:
518 self.tkconsole.resetoutput()
519 self.active_seq = None
520 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000521 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000522 if how == "OK":
523 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000524 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000525 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000526 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
527 self.remote_stack_viewer()
528 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000529 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000530 print(errmsg, what, file=sys.__stderr__)
531 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000532 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000533 try:
534 self.tkconsole.endexecuting()
535 except AttributeError: # shell may have closed
536 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000537 # Reschedule myself
538 if not self.tkconsole.closing:
539 self.tkconsole.text.after(self.tkconsole.pollinterval,
540 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000541
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000542 debugger = None
543
544 def setdebugger(self, debugger):
545 self.debugger = debugger
546
547 def getdebugger(self):
548 return self.debugger
549
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000550 def open_remote_stack_viewer(self):
551 """Initiate the remote stack viewer from a separate thread.
552
553 This method is called from the subprocess, and by returning from this
554 method we allow the subprocess to unblock. After a bit the shell
555 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000556 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000557 the RPC mechanism.
558
559 """
560 self.tkconsole.text.after(300, self.remote_stack_viewer)
561 return
562
Chui Tey5d2af632002-05-26 13:36:41 +0000563 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000564 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000565 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000566 if oid is None:
567 self.tkconsole.root.bell()
568 return
569 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000570 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000571 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000572 theme = idleConf.GetOption('main','Theme','name')
573 background = idleConf.GetHighlight(theme, 'normal')['background']
574 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000575 sc.frame.pack(expand=1, fill="both")
576 node = TreeNode(sc.canvas, None, item)
577 node.expand()
578 # XXX Should GC the remote tree when closing the window
579
David Scherer7aced172000-08-15 01:13:23 +0000580 gid = 0
581
582 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000583 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000584 filename = self.stuffsource(source)
585 self.execfile(filename, source)
586
587 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000588 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000589 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200590 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200591 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000592 try:
593 code = compile(source, filename, "exec")
594 except (OverflowError, SyntaxError):
595 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000596 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000597 print('*** Error in script or command!\n', file=tkerr)
598 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000599 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000600 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000601 else:
602 self.runcode(code)
603
604 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000605 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000606 filename = self.stuffsource(source)
607 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000608 self.save_warnings_filters = warnings.filters[:]
609 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000610 # at the moment, InteractiveInterpreter expects str
611 assert isinstance(source, str)
612 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000613 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000614 # try:
615 # source = source.encode(IOBinding.encoding)
616 # except UnicodeError:
617 # self.tkconsole.resetoutput()
618 # self.write("Unsupported characters in input\n")
619 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000620 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000621 # InteractiveInterpreter.runsource() calls its runcode() method,
622 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000623 return InteractiveInterpreter.runsource(self, source, filename)
624 finally:
625 if self.save_warnings_filters is not None:
626 warnings.filters[:] = self.save_warnings_filters
627 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000628
629 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000630 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000631 filename = "<pyshell#%d>" % self.gid
632 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000633 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000634 linecache.cache[filename] = len(source)+1, 0, lines, filename
635 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000636
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000637 def prepend_syspath(self, filename):
638 "Prepend sys.path with file's directory if not already included"
639 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000640 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000641 import sys as _sys
642 from os.path import dirname as _dirname
643 _dir = _dirname(_filename)
644 if not _dir in _sys.path:
645 _sys.path.insert(0, _dir)
646 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000647 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000648
David Scherer7aced172000-08-15 01:13:23 +0000649 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000650 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000651
652 Color the offending position instead of printing it and pointing at it
653 with a caret.
654
655 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000656 tkconsole = self.tkconsole
657 text = tkconsole.text
658 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000659 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700660 msg = getattr(value, 'msg', '') or value or "<no detail available>"
661 lineno = getattr(value, 'lineno', '') or 1
662 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000663 if offset == 0:
664 lineno += 1 #mark end of offending line
665 if lineno == 1:
666 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000667 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000668 pos = "iomark linestart + %d lines + %d chars" % \
669 (lineno-1, offset-1)
670 tkconsole.colorize_syntax_error(text, pos)
671 tkconsole.resetoutput()
672 self.write("SyntaxError: %s\n" % msg)
673 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000674
675 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000676 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000677 self.tkconsole.resetoutput()
678 self.checklinecache()
679 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000680 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
681 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000682
683 def checklinecache(self):
684 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000685 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000686 if key[:1] + key[-1:] != "<>":
687 del c[key]
688
Chui Tey5d2af632002-05-26 13:36:41 +0000689 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000690 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000691 # The code better not raise an exception!
692 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000693 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000694 return 0
695 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000696 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000697 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000698 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000699 return 1
700
David Scherer7aced172000-08-15 01:13:23 +0000701 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000702 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000703 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000704 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000705 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000706 if self.save_warnings_filters is not None:
707 warnings.filters[:] = self.save_warnings_filters
708 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000709 debugger = self.debugger
710 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000711 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000712 if not debugger and self.rpcclt is not None:
713 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
714 (code,), {})
715 elif debugger:
716 debugger.run(code, self.locals)
717 else:
718 exec(code, self.locals)
719 except SystemExit:
720 if not self.tkconsole.closing:
721 if tkMessageBox.askyesno(
722 "Exit?",
723 "Do you want to exit altogether?",
724 default="yes",
725 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000726 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000727 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000728 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000729 else:
730 raise
731 except:
732 if use_subprocess:
733 print("IDLE internal error in runcode()",
734 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000735 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000736 self.tkconsole.endexecuting()
737 else:
738 if self.tkconsole.canceled:
739 self.tkconsole.canceled = False
740 print("KeyboardInterrupt", file=self.tkconsole.stderr)
741 else:
742 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000743 finally:
744 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000745 try:
746 self.tkconsole.endexecuting()
747 except AttributeError: # shell may have closed
748 pass
David Scherer7aced172000-08-15 01:13:23 +0000749
750 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000751 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000752 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000753
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000754 def display_port_binding_error(self):
755 tkMessageBox.showerror(
756 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000757 "IDLE can't bind to a TCP/IP port, which is necessary to "
758 "communicate with its Python execution server. This might be "
759 "because no networking is installed on this computer. "
760 "Run IDLE with the -n command line switch to start without a "
761 "subprocess and refer to Help/IDLE Help 'Running without a "
762 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000763 master=self.tkconsole.text)
764
765 def display_no_subprocess_error(self):
766 tkMessageBox.showerror(
767 "Subprocess Startup Error",
768 "IDLE's subprocess didn't make connection. Either IDLE can't "
769 "start a subprocess or personal firewall software is blocking "
770 "the connection.",
771 master=self.tkconsole.text)
772
773 def display_executing_dialog(self):
774 tkMessageBox.showerror(
775 "Already executing",
776 "The Python Shell window is already executing a command; "
777 "please wait until it is finished.",
778 master=self.tkconsole.text)
779
780
David Scherer7aced172000-08-15 01:13:23 +0000781class PyShell(OutputWindow):
782
783 shell_title = "Python Shell"
784
785 # Override classes
786 ColorDelegator = ModifiedColorDelegator
787 UndoDelegator = ModifiedUndoDelegator
788
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000789 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000790 menu_specs = [
791 ("file", "_File"),
792 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000793 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000794 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000795 ("windows", "_Windows"),
796 ("help", "_Help"),
797 ]
David Scherer7aced172000-08-15 01:13:23 +0000798
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000799 if macosxSupport.runningAsOSXApp():
800 del menu_specs[-3]
801 menu_specs[-2] = ("windows", "_Window")
802
803
David Scherer7aced172000-08-15 01:13:23 +0000804 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000805 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000806
807 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000808 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000809 ms = self.menu_specs
810 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000811 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000812 self.interp = ModifiedInterpreter(self)
813 if flist is None:
814 root = Tk()
815 fixwordbreaks(root)
816 root.withdraw()
817 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000818 #
David Scherer7aced172000-08-15 01:13:23 +0000819 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000820 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000821## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
822 self.usetabs = True
823 # indentwidth must be 8 when using tabs. See note in EditorWindow:
824 self.indentwidth = 8
825 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000826 #
David Scherer7aced172000-08-15 01:13:23 +0000827 text = self.text
828 text.configure(wrap="char")
829 text.bind("<<newline-and-indent>>", self.enter_callback)
830 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
831 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000832 text.bind("<<end-of-file>>", self.eof_callback)
833 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000834 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000835 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000836 self.color = color = self.ColorDelegator()
837 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000838 if use_subprocess:
839 text.bind("<<view-restart>>", self.view_restart_mark)
840 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000841 #
David Scherer7aced172000-08-15 01:13:23 +0000842 self.save_stdout = sys.stdout
843 self.save_stderr = sys.stderr
844 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000845 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000846 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
847 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
848 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000849 if not use_subprocess:
850 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000851 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000852 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000853 try:
854 # page help() text to shell.
855 import pydoc # import must be done here to capture i/o rebinding.
856 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
857 pydoc.pager = pydoc.plainpager
858 except:
859 sys.stderr = sys.__stderr__
860 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000861 #
David Scherer7aced172000-08-15 01:13:23 +0000862 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000863 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000864 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000865
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000866 def get_standard_extension_names(self):
867 return idleConf.GetExtensions(shell_only=True)
868
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000869 reading = False
870 executing = False
871 canceled = False
872 endoffile = False
873 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000874
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000875 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000876 global warning_stream
877 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000878
879 def get_warning_stream(self):
880 return warning_stream
881
David Scherer7aced172000-08-15 01:13:23 +0000882 def toggle_debugger(self, event=None):
883 if self.executing:
884 tkMessageBox.showerror("Don't debug now",
885 "You can only toggle the debugger when idle",
886 master=self.text)
887 self.set_debugger_indicator()
888 return "break"
889 else:
890 db = self.interp.getdebugger()
891 if db:
892 self.close_debugger()
893 else:
894 self.open_debugger()
895
896 def set_debugger_indicator(self):
897 db = self.interp.getdebugger()
898 self.setvar("<<toggle-debugger>>", not not db)
899
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000900 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000901 pass # All we need is the variable
902
903 def close_debugger(self):
904 db = self.interp.getdebugger()
905 if db:
906 self.interp.setdebugger(None)
907 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000908 if self.interp.rpcclt:
909 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000910 self.resetoutput()
911 self.console.write("[DEBUG OFF]\n")
912 sys.ps1 = ">>> "
913 self.showprompt()
914 self.set_debugger_indicator()
915
916 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000917 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000918 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
919 self)
920 else:
921 dbg_gui = Debugger.Debugger(self)
922 self.interp.setdebugger(dbg_gui)
923 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000924 sys.ps1 = "[DEBUG ON]\n>>> "
925 self.showprompt()
926 self.set_debugger_indicator()
927
David Scherer7aced172000-08-15 01:13:23 +0000928 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000929 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000930 self.resetoutput()
931 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000932
933 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000934 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000935 self.executing = 0
936 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000937 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000938
939 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000940 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000941 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000942 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000943 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000944 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000945 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000946 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000947 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000948 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000949 if self.reading:
950 self.top.quit()
951 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000952 self.closing = True
953 # Wait for poll_subprocess() rescheduling to stop
954 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000955
956 def close2(self):
957 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000958
959 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000960 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000961 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000962 if use_subprocess:
963 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000964 # Restore std streams
965 sys.stdout = self.save_stdout
966 sys.stderr = self.save_stderr
967 sys.stdin = self.save_stdin
968 # Break cycles
969 self.interp = None
970 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000971 self.flist.pyshell = None
972 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000973 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000974
975 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000976 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000977 return True
David Scherer7aced172000-08-15 01:13:23 +0000978
979 def short_title(self):
980 return self.shell_title
981
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000982 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000983 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000984
David Scherer7aced172000-08-15 01:13:23 +0000985 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000986 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000987 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000988 if use_subprocess:
989 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000990 client = self.interp.start_subprocess()
991 if not client:
992 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000993 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000994 else:
995 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000996 self.write("Python %s on %s\n%s\n%s" %
997 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000998 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000999 import tkinter
1000 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001001 return True
David Scherer7aced172000-08-15 01:13:23 +00001002
1003 def readline(self):
1004 save = self.reading
1005 try:
1006 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001007 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001008 finally:
1009 self.reading = save
1010 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001011 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1012 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001013 self.resetoutput()
1014 if self.canceled:
1015 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001016 if not use_subprocess:
1017 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001018 if self.endoffile:
1019 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001020 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001021 return line
1022
1023 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001024 return True
David Scherer7aced172000-08-15 01:13:23 +00001025
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001026 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001027 try:
1028 if self.text.compare("sel.first", "!=", "sel.last"):
1029 return # Active selection -- always use default binding
1030 except:
1031 pass
1032 if not (self.executing or self.reading):
1033 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001034 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001035 self.showprompt()
1036 return "break"
1037 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001038 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001039 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001040 if self.interp.getdebugger():
1041 self.interp.restart_subprocess()
1042 else:
1043 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 if self.reading:
1045 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001046 return "break"
1047
1048 def eof_callback(self, event):
1049 if self.executing and not self.reading:
1050 return # Let the default binding (delete next char) take over
1051 if not (self.text.compare("iomark", "==", "insert") and
1052 self.text.compare("insert", "==", "end-1c")):
1053 return # Let the default binding (delete next char) take over
1054 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001055 self.resetoutput()
1056 self.close()
1057 else:
1058 self.canceled = 0
1059 self.endoffile = 1
1060 self.top.quit()
1061 return "break"
1062
David Scherer7aced172000-08-15 01:13:23 +00001063 def linefeed_callback(self, event):
1064 # Insert a linefeed without entering anything (still autoindented)
1065 if self.reading:
1066 self.text.insert("insert", "\n")
1067 self.text.see("insert")
1068 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001069 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001070 return "break"
1071
1072 def enter_callback(self, event):
1073 if self.executing and not self.reading:
1074 return # Let the default binding (insert '\n') take over
1075 # If some text is selected, recall the selection
1076 # (but only if this before the I/O mark)
1077 try:
1078 sel = self.text.get("sel.first", "sel.last")
1079 if sel:
1080 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001081 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001082 return "break"
1083 except:
1084 pass
1085 # If we're strictly before the line containing iomark, recall
1086 # the current line, less a leading prompt, less leading or
1087 # trailing whitespace
1088 if self.text.compare("insert", "<", "iomark linestart"):
1089 # Check if there's a relevant stdin range -- if so, use it
1090 prev = self.text.tag_prevrange("stdin", "insert")
1091 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001092 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001093 return "break"
1094 next = self.text.tag_nextrange("stdin", "insert")
1095 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001096 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001097 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001098 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001099 indices = self.text.tag_nextrange("console", "insert linestart")
1100 if indices and \
1101 self.text.compare(indices[0], "<=", "insert linestart"):
1102 self.recall(self.text.get(indices[1], "insert lineend"), event)
1103 else:
1104 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001105 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001106 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001107 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001108 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001109 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001110 # If we're in the current input and there's only whitespace
1111 # beyond the cursor, erase that whitespace first
1112 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001113 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001114 self.text.delete("insert", "end-1c")
1115 # If we're in the current input before its last line,
1116 # insert a newline right at the insert point
1117 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001118 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001119 return "break"
1120 # We're in the last line; append a newline and submit it
1121 self.text.mark_set("insert", "end-1c")
1122 if self.reading:
1123 self.text.insert("insert", "\n")
1124 self.text.see("insert")
1125 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001126 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001127 self.text.tag_add("stdin", "iomark", "end-1c")
1128 self.text.update_idletasks()
1129 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001130 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001131 else:
1132 self.runit()
1133 return "break"
1134
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001135 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001136 # remove leading and trailing empty or whitespace lines
1137 s = re.sub(r'^\s*\n', '' , s)
1138 s = re.sub(r'\n\s*$', '', s)
1139 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001140 self.text.undo_block_start()
1141 try:
1142 self.text.tag_remove("sel", "1.0", "end")
1143 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001144 prefix = self.text.get("insert linestart", "insert")
1145 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001146 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001147 prefix = self.text.get("insert linestart", "insert")
1148 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001149 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001150 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1151 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001152 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001153 if line.startswith(orig_base_indent):
1154 # replace orig base indentation with new indentation
1155 line = new_base_indent + line[len(orig_base_indent):]
1156 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001157 finally:
1158 self.text.see("insert")
1159 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001160
1161 def runit(self):
1162 line = self.text.get("iomark", "end-1c")
1163 # Strip off last newline and surrounding whitespace.
1164 # (To allow you to hit return twice to end a statement.)
1165 i = len(line)
1166 while i > 0 and line[i-1] in " \t":
1167 i = i-1
1168 if i > 0 and line[i-1] == "\n":
1169 i = i-1
1170 while i > 0 and line[i-1] in " \t":
1171 i = i-1
1172 line = line[:i]
1173 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001174
David Scherer7aced172000-08-15 01:13:23 +00001175 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001176 if self.interp.rpcclt:
1177 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001178 try:
1179 sys.last_traceback
1180 except:
1181 tkMessageBox.showerror("No stack trace",
1182 "There is no stack trace yet.\n"
1183 "(sys.last_traceback is not defined)",
1184 master=self.text)
1185 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001186 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001187 sv = StackBrowser(self.root, self.flist)
1188
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001189 def view_restart_mark(self, event=None):
1190 self.text.see("iomark")
1191 self.text.see("restart")
1192
1193 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001194 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001195
David Scherer7aced172000-08-15 01:13:23 +00001196 def showprompt(self):
1197 self.resetoutput()
1198 try:
1199 s = str(sys.ps1)
1200 except:
1201 s = ""
1202 self.console.write(s)
1203 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001204 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001205 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001206
1207 def resetoutput(self):
1208 source = self.text.get("iomark", "end-1c")
1209 if self.history:
1210 self.history.history_store(source)
1211 if self.text.get("end-2c") != "\n":
1212 self.text.insert("end-1c", "\n")
1213 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001214 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001215
1216 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001217 try:
1218 self.text.mark_gravity("iomark", "right")
1219 OutputWindow.write(self, s, tags, "iomark")
1220 self.text.mark_gravity("iomark", "left")
1221 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001222 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1223 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001224 if self.canceled:
1225 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001226 if not use_subprocess:
1227 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001228
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001229class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001230
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001231 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001232 self.shell = shell
1233 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001234 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001235
1236 def write(self, s):
1237 self.shell.write(s, self.tags)
1238
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001239 def writelines(self, lines):
1240 for line in lines:
1241 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001242
1243 def flush(self):
1244 pass
1245
1246 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001247 return True
David Scherer7aced172000-08-15 01:13:23 +00001248
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001249
David Scherer7aced172000-08-15 01:13:23 +00001250usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001251
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001252USAGE: idle [-deins] [-t title] [file]*
1253 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1254 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001255
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001256 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001257 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001258
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001259The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001260
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001261 -e open an edit window
1262 -i open a shell window
1263
1264The following options imply -i and will open a shell:
1265
1266 -c cmd run the command in a shell, or
1267 -r file run script from file
1268
1269 -d enable the debugger
1270 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1271 -t title set title of shell window
1272
1273A default edit window will be bypassed when -c, -r, or - are used.
1274
1275[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1276
1277Examples:
1278
1279idle
1280 Open an edit window or shell depending on IDLE's configuration.
1281
1282idle foo.py foobar.py
1283 Edit the files, also open a shell if configured to start with shell.
1284
1285idle -est "Baz" foo.py
1286 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1287 window with the title "Baz".
1288
Neal Norwitz752abd02008-05-13 04:55:24 +00001289idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001290 Open a shell window and run the command, passing "-c" in sys.argv[0]
1291 and "foo" in sys.argv[1].
1292
1293idle -d -s -r foo.py "Hello World"
1294 Open a shell window, run a startup script, enable the debugger, and
1295 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1296 sys.argv[1].
1297
Neal Norwitz752abd02008-05-13 04:55:24 +00001298echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001299 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1300 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001301"""
1302
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001303def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001304 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001305
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001306 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001307 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001308 enable_edit = False
1309 debug = False
1310 cmd = None
1311 script = None
1312 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001313 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001314 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001315 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001316 sys.stderr.write("Error: %s\n" % str(msg))
1317 sys.stderr.write(usage_msg)
1318 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001319 for o, a in opts:
1320 if o == '-c':
1321 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001322 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001323 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324 debug = True
1325 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001326 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001327 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001328 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001329 if o == '-h':
1330 sys.stdout.write(usage_msg)
1331 sys.exit()
1332 if o == '-i':
1333 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001334 if o == '-n':
1335 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001336 if o == '-r':
1337 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001338 if os.path.isfile(script):
1339 pass
1340 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001341 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001342 sys.exit()
1343 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001344 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 startup = True
1346 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001347 if o == '-t':
1348 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001349 enable_shell = True
1350 if args and args[0] == '-':
1351 cmd = sys.stdin.read()
1352 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001354 for i in range(len(sys.path)):
1355 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001356 if args and args[0] == '-':
1357 sys.argv = [''] + args[1:]
1358 elif cmd:
1359 sys.argv = ['-c'] + args
1360 elif script:
1361 sys.argv = [script] + args
1362 elif args:
1363 enable_edit = True
1364 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001365 for filename in args:
1366 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 for dir in pathx:
1368 dir = os.path.abspath(dir)
1369 if not dir in sys.path:
1370 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001371 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001372 dir = os.getcwd()
1373 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001374 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 # check the IDLE settings configuration (but command line overrides)
1376 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001377 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001381
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001382 fixwordbreaks(root)
1383 root.withdraw()
1384 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385 macosxSupport.setupApp(root, flist)
1386
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 if enable_edit:
1388 if not (cmd or script):
1389 for filename in args:
1390 flist.open(filename)
1391 if not args:
1392 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001393 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001394 shell = flist.open_shell()
1395 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001396 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001397
1398 if macosxSupport.runningAsOSXApp() and flist.dict:
1399 # On OSX: when the user has double-clicked on a file that causes
1400 # IDLE to be launched the shell window will open just in front of
1401 # the file she wants to see. Lower the interpreter window when
1402 # there are open files.
1403 shell.top.lower()
1404
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001405 shell = flist.pyshell
1406 # handle remaining options:
1407 if debug:
1408 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001409 if startup:
1410 filename = os.environ.get("IDLESTARTUP") or \
1411 os.environ.get("PYTHONSTARTUP")
1412 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001414 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415 shell.interp.runcommand("""if 1:
1416 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001417 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001419 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001420 if cmd:
1421 shell.interp.execsource(cmd)
1422 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001423 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001425
Ned Deily4ce92b22011-01-15 04:37:12 +00001426 # Check for problematic OS X Tk versions and print a warning message
1427 # in the IDLE shell window; this is less intrusive than always opening
1428 # a separate window.
1429 tkversionwarning = macosxSupport.tkVersionWarning(root)
1430 if tkversionwarning:
1431 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1432
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001433 root.mainloop()
1434 root.destroy()
1435
David Scherer7aced172000-08-15 01:13:23 +00001436if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001437 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001438 main()