blob: 2bf97a589ec14b16c94877500d5dd192a3bbeae7 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
David Scherer7aced172000-08-15 01:13:23 +000014
15import linecache
16from code import InteractiveInterpreter
17
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000018try:
Georg Brandl6634bf22008-05-20 07:13:37 +000019 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022 "Your Python may not be configured for Tk. **"
23 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000024import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000025
Florent Xiclunad630c042010-04-02 07:24:52 +000026from idlelib.EditorWindow import EditorWindow, fixwordbreaks
27from idlelib.FileList import FileList
28from idlelib.ColorDelegator import ColorDelegator
29from idlelib.UndoDelegator import UndoDelegator
30from idlelib.OutputWindow import OutputWindow
31from idlelib.configHandler import idleConf
32from idlelib import idlever
33from idlelib import rpc
34from idlelib import Debugger
35from idlelib import RemoteDebugger
36from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000037
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000038IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +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. Kaisera00050f2003-05-08 20:26:55 +000042try:
43 from signal import SIGTERM
44except ImportError:
45 SIGTERM = 15
46
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000047# Override warnings module to write to warning_stream. Initialize to send IDLE
48# internal warnings to the console. ScriptBinding.check_syntax() will
49# temporarily redirect the stream to the shell window to display warnings when
50# checking user's code.
51global warning_stream
52warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000053try:
54 import warnings
55except ImportError:
56 pass
57else:
Benjamin Petersonb76444b2008-10-16 19:40:14 +000058 def idle_showwarning(message, category, filename, lineno,
59 file=None, line=None):
Guilherme Polof198ac22009-08-14 14:03:07 +000060 if file is None:
61 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000062 try:
Guilherme Polof198ac22009-08-14 14:03:07 +000063 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaran13502b12011-07-03 17:38:53 -070064 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 except IOError:
66 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000067 warnings.showwarning = idle_showwarning
Guilherme Polof198ac22009-08-14 14:03:07 +000068 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000069 """Format warnings the IDLE way"""
70 s = "\nWarning (from warnings module):\n"
71 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000072 if line is None:
73 line = linecache.getline(filename, lineno)
74 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000075 if line:
76 s += " %s\n" % line
77 s += "%s: %s\n>>> " % (category.__name__, message)
78 return s
79 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000080
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000081def extended_linecache_checkcache(filename=None,
82 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000083 """Extend linecache.checkcache to preserve the <pyshell#...> entries
84
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000085 Rather than repeating the linecache code, patch it to save the
86 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +000087 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000088
89 orig_checkcache is bound at definition time to the original
90 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000091 """
David Scherer7aced172000-08-15 01:13:23 +000092 cache = linecache.cache
93 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +000094 for key in list(cache):
95 if key[:1] + key[-1:] == '<>':
96 save[key] = cache.pop(key)
97 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000098 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000099
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000100# Patch linecache.checkcache():
101linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000102
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103
David Scherer7aced172000-08-15 01:13:23 +0000104class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000105 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106
David Scherer7aced172000-08-15 01:13:23 +0000107 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000109 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000110 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000111 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000112 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
113
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000114 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
115 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000116 # whenever a file is changed, restore breakpoints
117 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000118 def filename_changed_hook(old_hook=self.io.filename_change_hook,
119 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000120 self.restore_file_breaks()
121 old_hook()
122 self.io.set_filename_change_hook(filename_changed_hook)
123
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000124 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
125 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000126
Chui Teya2adb0f2002-11-04 22:14:54 +0000127 def set_breakpoint(self, lineno):
128 text = self.text
129 filename = self.io.filename
130 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
131 try:
132 i = self.breakpoints.index(lineno)
133 except ValueError: # only add if missing, i.e. do once
134 self.breakpoints.append(lineno)
135 try: # update the subprocess debugger
136 debug = self.flist.pyshell.interp.debugger
137 debug.set_breakpoint_here(filename, lineno)
138 except: # but debugger may not be active right now....
139 pass
140
David Scherer7aced172000-08-15 01:13:23 +0000141 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000142 text = self.text
143 filename = self.io.filename
144 if not filename:
145 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000146 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000147 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000148 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000149
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000150 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000151 text = self.text
152 filename = self.io.filename
153 if not filename:
154 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000155 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000156 lineno = int(float(text.index("insert")))
157 try:
158 self.breakpoints.remove(lineno)
159 except:
160 pass
161 text.tag_remove("BREAK", "insert linestart",\
162 "insert lineend +1char")
163 try:
164 debug = self.flist.pyshell.interp.debugger
165 debug.clear_breakpoint_here(filename, lineno)
166 except:
167 pass
168
169 def clear_file_breaks(self):
170 if self.breakpoints:
171 text = self.text
172 filename = self.io.filename
173 if not filename:
174 text.bell()
175 return
176 self.breakpoints = []
177 text.tag_remove("BREAK", "1.0", END)
178 try:
179 debug = self.flist.pyshell.interp.debugger
180 debug.clear_file_breaks(filename)
181 except:
182 pass
183
Chui Teya2adb0f2002-11-04 22:14:54 +0000184 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000185 "Save breakpoints when file is saved"
186 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
187 # be run. The breaks are saved at that time. If we introduce
188 # a temporary file save feature the save breaks functionality
189 # needs to be re-verified, since the breaks at the time the
190 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000191 # permanent save of the file. Currently, a break introduced
192 # after a save will be effective, but not persistent.
193 # This is necessary to keep the saved breaks synched with the
194 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000195 #
196 # Breakpoints are set as tagged ranges in the text. Certain
197 # kinds of edits cause these ranges to be deleted: Inserting
198 # or deleting a line just before a breakpoint, and certain
199 # deletions prior to a breakpoint. These issues need to be
200 # investigated and understood. It's not clear if they are
201 # Tk issues or IDLE issues, or whether they can actually
202 # be fixed. Since a modified file has to be saved before it is
203 # run, and since self.breakpoints (from which the subprocess
204 # debugger is loaded) is updated during the save, the visible
205 # breaks stay synched with the subprocess even if one of these
206 # unexpected breakpoint deletions occurs.
207 breaks = self.breakpoints
208 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000209 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800210 with open(self.breakpointPath,"r") as old_file:
211 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000212 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000213 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800214 try:
215 with open(self.breakpointPath,"w") as new_file:
216 for line in lines:
217 if not line.startswith(filename + '='):
218 new_file.write(line)
219 self.update_breakpoints()
220 breaks = self.breakpoints
221 if breaks:
222 new_file.write(filename + '=' + str(breaks) + '\n')
223 except IOError as err:
224 if not getattr(self.root, "breakpoint_error_displayed", False):
225 self.root.breakpoint_error_displayed = True
226 tkMessageBox.showerror(title='IDLE Error',
227 message='Unable to update breakpoint list:\n%s'
228 % str(err),
229 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000230
231 def restore_file_breaks(self):
232 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000233 filename = self.io.filename
234 if filename is None:
235 return
Chui Tey69371d62002-11-04 23:39:45 +0000236 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000237 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000238 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000239 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000240 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000241 for breakpoint_linenumber in breakpoint_linenumbers:
242 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000243
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000244 def update_breakpoints(self):
245 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000246 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247 ranges = text.tag_ranges("BREAK")
248 linenumber_list = self.ranges_to_linenumbers(ranges)
249 self.breakpoints = linenumber_list
250
251 def ranges_to_linenumbers(self, ranges):
252 lines = []
253 for index in range(0, len(ranges), 2):
254 lineno = int(float(ranges[index]))
255 end = int(float(ranges[index+1]))
256 while lineno < end:
257 lines.append(lineno)
258 lineno += 1
259 return lines
260
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000261# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000262# def saved_change_hook(self):
263# "Extend base method - clear breaks if module is modified"
264# if not self.get_saved():
265# self.clear_file_breaks()
266# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000267
268 def _close(self):
269 "Extend base method - clear breaks when module is closed"
270 self.clear_file_breaks()
271 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000272
David Scherer7aced172000-08-15 01:13:23 +0000273
274class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000275 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000276
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000277 # override FileList's class variable, instances return PyShellEditorWindow
278 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000279 EditorWindow = PyShellEditorWindow
280
281 pyshell = None
282
283 def open_shell(self, event=None):
284 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000285 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000286 else:
287 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000288 if self.pyshell:
289 if not self.pyshell.begin():
290 return None
David Scherer7aced172000-08-15 01:13:23 +0000291 return self.pyshell
292
293
294class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000295 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000296
Steven M. Gavab77d3432002-03-02 07:16:21 +0000297 def __init__(self):
298 ColorDelegator.__init__(self)
299 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000300
301 def recolorize_main(self):
302 self.tag_remove("TODO", "1.0", "iomark")
303 self.tag_add("SYNC", "1.0", "iomark")
304 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000305
Steven M. Gavab77d3432002-03-02 07:16:21 +0000306 def LoadTagDefs(self):
307 ColorDelegator.LoadTagDefs(self)
308 theme = idleConf.GetOption('main','Theme','name')
309 self.tagdefs.update({
310 "stdin": {'background':None,'foreground':None},
311 "stdout": idleConf.GetHighlight(theme, "stdout"),
312 "stderr": idleConf.GetHighlight(theme, "stderr"),
313 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000314 })
David Scherer7aced172000-08-15 01:13:23 +0000315
Ned Deily5e247b72012-05-31 09:17:29 -0700316 def removecolors(self):
317 # Don't remove shell color tags before "iomark"
318 for tag in self.tagdefs:
319 self.tag_remove(tag, "iomark", "end")
320
David Scherer7aced172000-08-15 01:13:23 +0000321class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000322 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000323
324 def insert(self, index, chars, tags=None):
325 try:
326 if self.delegate.compare(index, "<", "iomark"):
327 self.delegate.bell()
328 return
329 except TclError:
330 pass
331 UndoDelegator.insert(self, index, chars, tags)
332
333 def delete(self, index1, index2=None):
334 try:
335 if self.delegate.compare(index1, "<", "iomark"):
336 self.delegate.bell()
337 return
338 except TclError:
339 pass
340 UndoDelegator.delete(self, index1, index2)
341
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000342
343class MyRPCClient(rpc.RPCClient):
344
345 def handle_EOF(self):
346 "Override the base class - just re-raise EOFError"
347 raise EOFError
348
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000349
David Scherer7aced172000-08-15 01:13:23 +0000350class ModifiedInterpreter(InteractiveInterpreter):
351
352 def __init__(self, tkconsole):
353 self.tkconsole = tkconsole
354 locals = sys.modules['__main__'].__dict__
355 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000356 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000357 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000358 self.subprocess_arglist = None
359 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700360 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000361
Chui Tey5d2af632002-05-26 13:36:41 +0000362 rpcclt = None
363 rpcpid = None
364
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000365 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000366 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000367 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000368 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000369 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000370
Tony Lowndsf53dec22002-12-20 04:24:43 +0000371 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000372 assert (self.port!=0), (
373 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000374 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000375 if 1/2 > 0: # account for new division
376 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000377 # Maybe IDLE is installed and is being accessed via sys.path,
378 # or maybe it's not installed and the idle.py script is being
379 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000380 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
381 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000382 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000383 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000384 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000385 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000386 if sys.platform[:3] == 'win' and ' ' in sys.executable:
387 # handle embedded space in path by quoting the argument
388 decorated_exec = '"%s"' % sys.executable
389 else:
390 decorated_exec = sys.executable
391 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000392
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000393 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000394 addr = (HOST, self.port)
395 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000396 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000397 time.sleep(i)
398 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000399 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000400 break
401 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000402 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000403 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000404 self.display_port_binding_error()
405 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000406 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
407 self.port = self.rpcclt.listening_sock.getsockname()[1]
408 # if PORT was not 0, probably working with a remote execution server
409 if PORT != 0:
410 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
411 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
412 # on Windows since the implementation allows two active sockets on
413 # the same address!
414 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
415 socket.SO_REUSEADDR, 1)
416 self.spawn_subprocess()
417 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000418 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000419 self.rpcclt.listening_sock.settimeout(10)
420 try:
421 self.rpcclt.accept()
422 except socket.timeout, err:
423 self.display_no_subprocess_error()
424 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000425 self.rpcclt.register("stdin", self.tkconsole)
426 self.rpcclt.register("stdout", self.tkconsole.stdout)
427 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000428 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000429 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000430 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500431 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000432 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000433 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000434
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500435 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000436 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000437 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000438 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000439 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000440 debug = self.getdebugger()
441 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000442 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000443 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000444 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
445 except:
446 pass
447 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000448 self.rpcclt.close()
449 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000450 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000451 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000452 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000453 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000454 try:
455 self.rpcclt.accept()
456 except socket.timeout, err:
457 self.display_no_subprocess_error()
458 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500459 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000460 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000461 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000462 if was_executing:
463 console.write('\n')
464 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000465 halfbar = ((int(console.width) - 16) // 2) * '='
466 console.write(halfbar + ' RESTART ' + halfbar)
467 console.text.mark_set("restart", "end-1c")
468 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000469 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000470 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000471 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000472 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000473 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000474 # reload remote debugger breakpoints for all PyShellEditWindows
475 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700476 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000477 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000478 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000479
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000480 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000481 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000482
483 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000485
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000486 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000487 try:
488 self.rpcclt.close()
489 except AttributeError: # no socket
490 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000491 self.unix_terminate()
492 self.tkconsole.executing = False
493 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000494
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 def unix_terminate(self):
496 "UNIX: make sure subprocess is terminated and collect status"
497 if hasattr(os, 'kill'):
498 try:
499 os.kill(self.rpcpid, SIGTERM)
500 except OSError:
501 # process already terminated:
502 return
503 else:
504 try:
505 os.waitpid(self.rpcpid, 0)
506 except OSError:
507 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000508
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500509 def transfer_path(self, with_cwd=False):
510 if with_cwd: # Issue 13506
511 path = [''] # include Current Working Directory
512 path.extend(sys.path)
513 else:
514 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500515
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000516 self.runcommand("""if 1:
517 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000518 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000519 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500520 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000521
Chui Tey5d2af632002-05-26 13:36:41 +0000522 active_seq = None
523
524 def poll_subprocess(self):
525 clt = self.rpcclt
526 if clt is None:
527 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000528 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000529 response = clt.pollresponse(self.active_seq, wait=0.05)
530 except (EOFError, IOError, KeyboardInterrupt):
531 # lost connection or subprocess terminated itself, restart
532 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000533 if self.tkconsole.closing:
534 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000535 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000536 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000537 if response:
538 self.tkconsole.resetoutput()
539 self.active_seq = None
540 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000541 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000542 if how == "OK":
543 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000544 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000545 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000546 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
547 self.remote_stack_viewer()
548 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000549 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
550 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000551 print >>console, errmsg, what
552 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000553 try:
554 self.tkconsole.endexecuting()
555 except AttributeError: # shell may have closed
556 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000557 # Reschedule myself
558 if not self.tkconsole.closing:
559 self.tkconsole.text.after(self.tkconsole.pollinterval,
560 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000561
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000562 debugger = None
563
564 def setdebugger(self, debugger):
565 self.debugger = debugger
566
567 def getdebugger(self):
568 return self.debugger
569
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000570 def open_remote_stack_viewer(self):
571 """Initiate the remote stack viewer from a separate thread.
572
573 This method is called from the subprocess, and by returning from this
574 method we allow the subprocess to unblock. After a bit the shell
575 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000576 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000577 the RPC mechanism.
578
579 """
580 self.tkconsole.text.after(300, self.remote_stack_viewer)
581 return
582
Chui Tey5d2af632002-05-26 13:36:41 +0000583 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000584 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000585 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000586 if oid is None:
587 self.tkconsole.root.bell()
588 return
589 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000590 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000591 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000592 theme = idleConf.GetOption('main','Theme','name')
593 background = idleConf.GetHighlight(theme, 'normal')['background']
594 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000595 sc.frame.pack(expand=1, fill="both")
596 node = TreeNode(sc.canvas, None, item)
597 node.expand()
598 # XXX Should GC the remote tree when closing the window
599
David Scherer7aced172000-08-15 01:13:23 +0000600 gid = 0
601
602 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000603 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000604 filename = self.stuffsource(source)
605 self.execfile(filename, source)
606
607 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000608 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000609 if source is None:
610 source = open(filename, "r").read()
611 try:
612 code = compile(source, filename, "exec")
613 except (OverflowError, SyntaxError):
614 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000615 tkerr = self.tkconsole.stderr
616 print>>tkerr, '*** Error in script or command!\n'
617 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000618 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000619 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000620 else:
621 self.runcode(code)
622
623 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000624 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000625 filename = self.stuffsource(source)
626 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000627 self.save_warnings_filters = warnings.filters[:]
628 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000629 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000630 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000631 try:
632 source = source.encode(IOBinding.encoding)
633 except UnicodeError:
634 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000635 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000636 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000637 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000638 # InteractiveInterpreter.runsource() calls its runcode() method,
639 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000640 return InteractiveInterpreter.runsource(self, source, filename)
641 finally:
642 if self.save_warnings_filters is not None:
643 warnings.filters[:] = self.save_warnings_filters
644 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000645
646 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000647 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000648 filename = "<pyshell#%d>" % self.gid
649 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000650 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000651 linecache.cache[filename] = len(source)+1, 0, lines, filename
652 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000653
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000654 def prepend_syspath(self, filename):
655 "Prepend sys.path with file's directory if not already included"
656 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000657 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000658 import sys as _sys
659 from os.path import dirname as _dirname
660 _dir = _dirname(_filename)
661 if not _dir in _sys.path:
662 _sys.path.insert(0, _dir)
663 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000664 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000665
David Scherer7aced172000-08-15 01:13:23 +0000666 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000667 """Extend base class method: Add Colorizing
668
669 Color the offending position instead of printing it and pointing at it
670 with a caret.
671
672 """
David Scherer7aced172000-08-15 01:13:23 +0000673 text = self.tkconsole.text
674 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000675 if stuff:
676 msg, lineno, offset, line = stuff
677 if lineno == 1:
678 pos = "iomark + %d chars" % (offset-1)
679 else:
680 pos = "iomark linestart + %d lines + %d chars" % \
681 (lineno-1, offset-1)
682 text.tag_add("ERROR", pos)
683 text.see(pos)
684 char = text.get(pos)
685 if char and char in IDENTCHARS:
686 text.tag_add("ERROR", pos + " wordstart", pos)
687 self.tkconsole.resetoutput()
688 self.write("SyntaxError: %s\n" % str(msg))
689 else:
David Scherer7aced172000-08-15 01:13:23 +0000690 self.tkconsole.resetoutput()
691 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000692 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000693
694 def unpackerror(self):
695 type, value, tb = sys.exc_info()
696 ok = type is SyntaxError
697 if ok:
698 try:
699 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000700 if not offset:
701 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000702 except:
703 ok = 0
704 if ok:
705 return msg, lineno, offset, line
706 else:
707 return None
708
709 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000710 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000711 self.tkconsole.resetoutput()
712 self.checklinecache()
713 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000714 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
715 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000716
717 def checklinecache(self):
718 c = linecache.cache
719 for key in c.keys():
720 if key[:1] + key[-1:] != "<>":
721 del c[key]
722
Chui Tey5d2af632002-05-26 13:36:41 +0000723 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000724 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000725 # The code better not raise an exception!
726 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000727 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000728 return 0
729 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000730 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000731 else:
732 exec code in self.locals
733 return 1
734
David Scherer7aced172000-08-15 01:13:23 +0000735 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000736 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000737 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000738 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000739 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000740 if self.save_warnings_filters is not None:
741 warnings.filters[:] = self.save_warnings_filters
742 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000743 debugger = self.debugger
744 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000745 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000746 if not debugger and self.rpcclt is not None:
747 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
748 (code,), {})
749 elif debugger:
750 debugger.run(code, self.locals)
751 else:
752 exec code in self.locals
753 except SystemExit:
754 if not self.tkconsole.closing:
755 if tkMessageBox.askyesno(
756 "Exit?",
757 "Do you want to exit altogether?",
758 default="yes",
759 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000760 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000761 else:
762 self.showtraceback()
763 else:
764 raise
765 except:
766 if use_subprocess:
767 print >>self.tkconsole.stderr, \
768 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000769 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000770 self.tkconsole.endexecuting()
771 else:
772 if self.tkconsole.canceled:
773 self.tkconsole.canceled = False
774 print >>self.tkconsole.stderr, "KeyboardInterrupt"
775 else:
776 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000777 finally:
778 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000779 try:
780 self.tkconsole.endexecuting()
781 except AttributeError: # shell may have closed
782 pass
David Scherer7aced172000-08-15 01:13:23 +0000783
784 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000785 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000786 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000787
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000788 def display_port_binding_error(self):
789 tkMessageBox.showerror(
790 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000791 "IDLE can't bind to a TCP/IP port, which is necessary to "
792 "communicate with its Python execution server. This might be "
793 "because no networking is installed on this computer. "
794 "Run IDLE with the -n command line switch to start without a "
795 "subprocess and refer to Help/IDLE Help 'Running without a "
796 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000797 master=self.tkconsole.text)
798
799 def display_no_subprocess_error(self):
800 tkMessageBox.showerror(
801 "Subprocess Startup Error",
802 "IDLE's subprocess didn't make connection. Either IDLE can't "
803 "start a subprocess or personal firewall software is blocking "
804 "the connection.",
805 master=self.tkconsole.text)
806
807 def display_executing_dialog(self):
808 tkMessageBox.showerror(
809 "Already executing",
810 "The Python Shell window is already executing a command; "
811 "please wait until it is finished.",
812 master=self.tkconsole.text)
813
814
David Scherer7aced172000-08-15 01:13:23 +0000815class PyShell(OutputWindow):
816
817 shell_title = "Python Shell"
818
819 # Override classes
820 ColorDelegator = ModifiedColorDelegator
821 UndoDelegator = ModifiedUndoDelegator
822
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000823 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000824 menu_specs = [
825 ("file", "_File"),
826 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000827 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000828 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000829 ("windows", "_Windows"),
830 ("help", "_Help"),
831 ]
David Scherer7aced172000-08-15 01:13:23 +0000832
Ronald Oussoren19302d92006-06-11 14:33:36 +0000833 if macosxSupport.runningAsOSXApp():
834 del menu_specs[-3]
835 menu_specs[-2] = ("windows", "_Window")
836
837
David Scherer7aced172000-08-15 01:13:23 +0000838 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000839 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000840
841 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000842 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000843 ms = self.menu_specs
844 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000845 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000846 self.interp = ModifiedInterpreter(self)
847 if flist is None:
848 root = Tk()
849 fixwordbreaks(root)
850 root.withdraw()
851 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000852 #
David Scherer7aced172000-08-15 01:13:23 +0000853 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000854 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000855## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
856 self.usetabs = True
857 # indentwidth must be 8 when using tabs. See note in EditorWindow:
858 self.indentwidth = 8
859 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000860 #
David Scherer7aced172000-08-15 01:13:23 +0000861 text = self.text
862 text.configure(wrap="char")
863 text.bind("<<newline-and-indent>>", self.enter_callback)
864 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
865 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000866 text.bind("<<end-of-file>>", self.eof_callback)
867 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000868 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000869 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000870 if use_subprocess:
871 text.bind("<<view-restart>>", self.view_restart_mark)
872 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000873 #
David Scherer7aced172000-08-15 01:13:23 +0000874 self.save_stdout = sys.stdout
875 self.save_stderr = sys.stderr
876 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000877 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000878 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
879 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
880 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000881 if not use_subprocess:
882 sys.stdout = self.stdout
883 sys.stderr = self.stderr
884 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000885 #
David Scherer7aced172000-08-15 01:13:23 +0000886 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000887 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000888 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000889
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000890 def get_standard_extension_names(self):
891 return idleConf.GetExtensions(shell_only=True)
892
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000893 reading = False
894 executing = False
895 canceled = False
896 endoffile = False
897 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000898
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000899 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000900 global warning_stream
901 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000902
903 def get_warning_stream(self):
904 return warning_stream
905
David Scherer7aced172000-08-15 01:13:23 +0000906 def toggle_debugger(self, event=None):
907 if self.executing:
908 tkMessageBox.showerror("Don't debug now",
909 "You can only toggle the debugger when idle",
910 master=self.text)
911 self.set_debugger_indicator()
912 return "break"
913 else:
914 db = self.interp.getdebugger()
915 if db:
916 self.close_debugger()
917 else:
918 self.open_debugger()
919
920 def set_debugger_indicator(self):
921 db = self.interp.getdebugger()
922 self.setvar("<<toggle-debugger>>", not not db)
923
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000924 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000925 pass # All we need is the variable
926
927 def close_debugger(self):
928 db = self.interp.getdebugger()
929 if db:
930 self.interp.setdebugger(None)
931 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000932 if self.interp.rpcclt:
933 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000934 self.resetoutput()
935 self.console.write("[DEBUG OFF]\n")
936 sys.ps1 = ">>> "
937 self.showprompt()
938 self.set_debugger_indicator()
939
940 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000941 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000942 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
943 self)
944 else:
945 dbg_gui = Debugger.Debugger(self)
946 self.interp.setdebugger(dbg_gui)
947 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000948 sys.ps1 = "[DEBUG ON]\n>>> "
949 self.showprompt()
950 self.set_debugger_indicator()
951
David Scherer7aced172000-08-15 01:13:23 +0000952 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000953 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000954 self.resetoutput()
955 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000956
957 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000958 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000959 self.executing = 0
960 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000961 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000962
963 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000964 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000965 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000966 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000967 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000968 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000969 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000970 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000971 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000972 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000973 if self.reading:
974 self.top.quit()
975 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000976 self.closing = True
977 # Wait for poll_subprocess() rescheduling to stop
978 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000979
980 def close2(self):
981 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000982
983 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000984 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000985 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000986 if use_subprocess:
987 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000988 # Restore std streams
989 sys.stdout = self.save_stdout
990 sys.stderr = self.save_stderr
991 sys.stdin = self.save_stdin
992 # Break cycles
993 self.interp = None
994 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000995 self.flist.pyshell = None
996 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000997 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000998
999 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001000 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001001 return True
David Scherer7aced172000-08-15 01:13:23 +00001002
1003 def short_title(self):
1004 return self.shell_title
1005
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001006 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001007 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001008
David Scherer7aced172000-08-15 01:13:23 +00001009 def begin(self):
1010 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001011 if use_subprocess:
1012 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001013 client = self.interp.start_subprocess()
1014 if not client:
1015 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001016 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001017 else:
1018 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001019 self.write("Python %s on %s\n%s\n%s" %
1020 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001021 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001022 import Tkinter
1023 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001024 return True
David Scherer7aced172000-08-15 01:13:23 +00001025
1026 def readline(self):
1027 save = self.reading
1028 try:
1029 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001030 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001031 finally:
1032 self.reading = save
1033 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001034 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1035 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001036 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001037 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001038 try:
1039 line = line.encode(IOBinding.encoding)
1040 except UnicodeError:
1041 pass
David Scherer7aced172000-08-15 01:13:23 +00001042 self.resetoutput()
1043 if self.canceled:
1044 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001045 if not use_subprocess:
1046 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001047 if self.endoffile:
1048 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001049 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001050 return line
1051
1052 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001053 return True
David Scherer7aced172000-08-15 01:13:23 +00001054
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001055 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001056 try:
1057 if self.text.compare("sel.first", "!=", "sel.last"):
1058 return # Active selection -- always use default binding
1059 except:
1060 pass
1061 if not (self.executing or self.reading):
1062 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001063 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001064 self.showprompt()
1065 return "break"
1066 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001067 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001069 if self.interp.getdebugger():
1070 self.interp.restart_subprocess()
1071 else:
1072 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001073 if self.reading:
1074 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001075 return "break"
1076
1077 def eof_callback(self, event):
1078 if self.executing and not self.reading:
1079 return # Let the default binding (delete next char) take over
1080 if not (self.text.compare("iomark", "==", "insert") and
1081 self.text.compare("insert", "==", "end-1c")):
1082 return # Let the default binding (delete next char) take over
1083 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001084 self.resetoutput()
1085 self.close()
1086 else:
1087 self.canceled = 0
1088 self.endoffile = 1
1089 self.top.quit()
1090 return "break"
1091
David Scherer7aced172000-08-15 01:13:23 +00001092 def linefeed_callback(self, event):
1093 # Insert a linefeed without entering anything (still autoindented)
1094 if self.reading:
1095 self.text.insert("insert", "\n")
1096 self.text.see("insert")
1097 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001098 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001099 return "break"
1100
1101 def enter_callback(self, event):
1102 if self.executing and not self.reading:
1103 return # Let the default binding (insert '\n') take over
1104 # If some text is selected, recall the selection
1105 # (but only if this before the I/O mark)
1106 try:
1107 sel = self.text.get("sel.first", "sel.last")
1108 if sel:
1109 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001110 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001111 return "break"
1112 except:
1113 pass
1114 # If we're strictly before the line containing iomark, recall
1115 # the current line, less a leading prompt, less leading or
1116 # trailing whitespace
1117 if self.text.compare("insert", "<", "iomark linestart"):
1118 # Check if there's a relevant stdin range -- if so, use it
1119 prev = self.text.tag_prevrange("stdin", "insert")
1120 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001121 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001122 return "break"
1123 next = self.text.tag_nextrange("stdin", "insert")
1124 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001125 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001126 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001127 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001128 indices = self.text.tag_nextrange("console", "insert linestart")
1129 if indices and \
1130 self.text.compare(indices[0], "<=", "insert linestart"):
1131 self.recall(self.text.get(indices[1], "insert lineend"), event)
1132 else:
1133 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001134 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001135 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001136 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001137 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001138 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001139 # If we're in the current input and there's only whitespace
1140 # beyond the cursor, erase that whitespace first
1141 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001142 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001143 self.text.delete("insert", "end-1c")
1144 # If we're in the current input before its last line,
1145 # insert a newline right at the insert point
1146 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001147 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001148 return "break"
1149 # We're in the last line; append a newline and submit it
1150 self.text.mark_set("insert", "end-1c")
1151 if self.reading:
1152 self.text.insert("insert", "\n")
1153 self.text.see("insert")
1154 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001155 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001156 self.text.tag_add("stdin", "iomark", "end-1c")
1157 self.text.update_idletasks()
1158 if self.reading:
1159 self.top.quit() # Break out of recursive mainloop() in raw_input()
1160 else:
1161 self.runit()
1162 return "break"
1163
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001164 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001165 # remove leading and trailing empty or whitespace lines
1166 s = re.sub(r'^\s*\n', '' , s)
1167 s = re.sub(r'\n\s*$', '', s)
1168 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001169 self.text.undo_block_start()
1170 try:
1171 self.text.tag_remove("sel", "1.0", "end")
1172 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001173 prefix = self.text.get("insert linestart", "insert")
1174 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001175 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001176 prefix = self.text.get("insert linestart", "insert")
1177 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001178 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001179 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1180 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001181 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001182 if line.startswith(orig_base_indent):
1183 # replace orig base indentation with new indentation
1184 line = new_base_indent + line[len(orig_base_indent):]
1185 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001186 finally:
1187 self.text.see("insert")
1188 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001189
1190 def runit(self):
1191 line = self.text.get("iomark", "end-1c")
1192 # Strip off last newline and surrounding whitespace.
1193 # (To allow you to hit return twice to end a statement.)
1194 i = len(line)
1195 while i > 0 and line[i-1] in " \t":
1196 i = i-1
1197 if i > 0 and line[i-1] == "\n":
1198 i = i-1
1199 while i > 0 and line[i-1] in " \t":
1200 i = i-1
1201 line = line[:i]
1202 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001203
David Scherer7aced172000-08-15 01:13:23 +00001204 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001205 if self.interp.rpcclt:
1206 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001207 try:
1208 sys.last_traceback
1209 except:
1210 tkMessageBox.showerror("No stack trace",
1211 "There is no stack trace yet.\n"
1212 "(sys.last_traceback is not defined)",
1213 master=self.text)
1214 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001215 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001216 sv = StackBrowser(self.root, self.flist)
1217
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001218 def view_restart_mark(self, event=None):
1219 self.text.see("iomark")
1220 self.text.see("restart")
1221
1222 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001223 "Callback for Run/Restart Shell Cntl-F6"
1224 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001225
David Scherer7aced172000-08-15 01:13:23 +00001226 def showprompt(self):
1227 self.resetoutput()
1228 try:
1229 s = str(sys.ps1)
1230 except:
1231 s = ""
1232 self.console.write(s)
1233 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001234 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001235 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001236
1237 def resetoutput(self):
1238 source = self.text.get("iomark", "end-1c")
1239 if self.history:
1240 self.history.history_store(source)
1241 if self.text.get("end-2c") != "\n":
1242 self.text.insert("end-1c", "\n")
1243 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001244 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001245 sys.stdout.softspace = 0
1246
1247 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001248 try:
1249 self.text.mark_gravity("iomark", "right")
1250 OutputWindow.write(self, s, tags, "iomark")
1251 self.text.mark_gravity("iomark", "left")
1252 except:
1253 pass
David Scherer7aced172000-08-15 01:13:23 +00001254 if self.canceled:
1255 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001256 if not use_subprocess:
1257 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001258
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001259class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001260
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001261 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001262 self.shell = shell
1263 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001264 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001265 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001266
1267 def write(self, s):
Terry Jan Reedyf8fc6742012-07-09 17:57:13 -04001268 if not isinstance(s, (basestring, bytearray)):
1269 raise TypeError('must be string, not ' + type(s).__name__)
David Scherer7aced172000-08-15 01:13:23 +00001270 self.shell.write(s, self.tags)
1271
Florent Xiclunad630c042010-04-02 07:24:52 +00001272 def writelines(self, lines):
1273 for line in lines:
1274 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001275
1276 def flush(self):
1277 pass
1278
1279 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001280 return True
David Scherer7aced172000-08-15 01:13:23 +00001281
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001282
David Scherer7aced172000-08-15 01:13:23 +00001283usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001284
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001285USAGE: idle [-deins] [-t title] [file]*
1286 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1287 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001288
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001289 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001290 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001291
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001292The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001293
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001294 -e open an edit window
1295 -i open a shell window
1296
1297The following options imply -i and will open a shell:
1298
1299 -c cmd run the command in a shell, or
1300 -r file run script from file
1301
1302 -d enable the debugger
1303 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1304 -t title set title of shell window
1305
1306A default edit window will be bypassed when -c, -r, or - are used.
1307
1308[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1309
1310Examples:
1311
1312idle
1313 Open an edit window or shell depending on IDLE's configuration.
1314
1315idle foo.py foobar.py
1316 Edit the files, also open a shell if configured to start with shell.
1317
1318idle -est "Baz" foo.py
1319 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1320 window with the title "Baz".
1321
1322idle -c "import sys; print sys.argv" "foo"
1323 Open a shell window and run the command, passing "-c" in sys.argv[0]
1324 and "foo" in sys.argv[1].
1325
1326idle -d -s -r foo.py "Hello World"
1327 Open a shell window, run a startup script, enable the debugger, and
1328 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1329 sys.argv[1].
1330
1331echo "import sys; print sys.argv" | idle - "foobar"
1332 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1333 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001334"""
1335
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001336def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001337 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001338
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001339 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001340 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 enable_edit = False
1342 debug = False
1343 cmd = None
1344 script = None
1345 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001346 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001347 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001348 except getopt.error, msg:
1349 sys.stderr.write("Error: %s\n" % str(msg))
1350 sys.stderr.write(usage_msg)
1351 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001352 for o, a in opts:
1353 if o == '-c':
1354 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001355 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001356 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 debug = True
1358 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001359 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001360 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001361 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001362 if o == '-h':
1363 sys.stdout.write(usage_msg)
1364 sys.exit()
1365 if o == '-i':
1366 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001367 if o == '-n':
1368 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001369 if o == '-r':
1370 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 if os.path.isfile(script):
1372 pass
1373 else:
1374 print "No script file: ", script
1375 sys.exit()
1376 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001377 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 startup = True
1379 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 if o == '-t':
1381 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 enable_shell = True
1383 if args and args[0] == '-':
1384 cmd = sys.stdin.read()
1385 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001387 for i in range(len(sys.path)):
1388 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 if args and args[0] == '-':
1390 sys.argv = [''] + args[1:]
1391 elif cmd:
1392 sys.argv = ['-c'] + args
1393 elif script:
1394 sys.argv = [script] + args
1395 elif args:
1396 enable_edit = True
1397 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001398 for filename in args:
1399 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001400 for dir in pathx:
1401 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001402 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001404 else:
1405 dir = os.getcwd()
1406 if not dir in sys.path:
1407 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001408 # check the IDLE settings configuration (but command line overrides)
1409 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001410 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001413 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001414
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001415 fixwordbreaks(root)
1416 root.withdraw()
1417 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001418 macosxSupport.setupApp(root, flist)
1419
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001420 if enable_edit:
1421 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001422 for filename in args[:]:
1423 if flist.open(filename) is None:
1424 # filename is a directory actually, disconsider it
1425 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 if not args:
1427 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001428 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001429 shell = flist.open_shell()
1430 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001431 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001432
1433 if macosxSupport.runningAsOSXApp() and flist.dict:
1434 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001435 # IDLE to be launched the shell window will open just in front of
1436 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001437 # there are open files.
1438 shell.top.lower()
1439
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001440 shell = flist.pyshell
1441 # handle remaining options:
1442 if debug:
1443 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001444 if startup:
1445 filename = os.environ.get("IDLESTARTUP") or \
1446 os.environ.get("PYTHONSTARTUP")
1447 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001449 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001450 shell.interp.runcommand("""if 1:
1451 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001452 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001453 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001454 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001455 if cmd:
1456 shell.interp.execsource(cmd)
1457 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001458 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001459 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001460
Ned Deily2a6f4b32011-01-30 00:18:47 +00001461 # Check for problematic OS X Tk versions and print a warning message
1462 # in the IDLE shell window; this is less intrusive than always opening
1463 # a separate window.
1464 tkversionwarning = macosxSupport.tkVersionWarning(root)
1465 if tkversionwarning:
1466 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1467
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001468 while flist.inversedict: # keep IDLE running while files are open.
1469 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001470 root.destroy()
1471
David Scherer7aced172000-08-15 01:13:23 +00001472if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001473 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001474 main()