blob: eeb33e1c75088fae6cec3cc577f46a901fafc4bf [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
David Scherer7aced172000-08-15 01:13:23 +0000316class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000317 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000318
319 def insert(self, index, chars, tags=None):
320 try:
321 if self.delegate.compare(index, "<", "iomark"):
322 self.delegate.bell()
323 return
324 except TclError:
325 pass
326 UndoDelegator.insert(self, index, chars, tags)
327
328 def delete(self, index1, index2=None):
329 try:
330 if self.delegate.compare(index1, "<", "iomark"):
331 self.delegate.bell()
332 return
333 except TclError:
334 pass
335 UndoDelegator.delete(self, index1, index2)
336
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000337
338class MyRPCClient(rpc.RPCClient):
339
340 def handle_EOF(self):
341 "Override the base class - just re-raise EOFError"
342 raise EOFError
343
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000344
David Scherer7aced172000-08-15 01:13:23 +0000345class ModifiedInterpreter(InteractiveInterpreter):
346
347 def __init__(self, tkconsole):
348 self.tkconsole = tkconsole
349 locals = sys.modules['__main__'].__dict__
350 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000351 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000352 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000353 self.subprocess_arglist = None
354 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700355 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000356
Chui Tey5d2af632002-05-26 13:36:41 +0000357 rpcclt = None
358 rpcpid = None
359
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000360 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000361 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000362 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000363 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000364 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000365
Tony Lowndsf53dec22002-12-20 04:24:43 +0000366 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000367 assert (self.port!=0), (
368 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000369 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000370 if 1/2 > 0: # account for new division
371 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000372 # Maybe IDLE is installed and is being accessed via sys.path,
373 # or maybe it's not installed and the idle.py script is being
374 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000375 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
376 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000377 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000378 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000379 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000380 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000381 if sys.platform[:3] == 'win' and ' ' in sys.executable:
382 # handle embedded space in path by quoting the argument
383 decorated_exec = '"%s"' % sys.executable
384 else:
385 decorated_exec = sys.executable
386 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000387
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000388 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000389 addr = (HOST, self.port)
390 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000391 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000392 time.sleep(i)
393 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000394 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000395 break
396 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000397 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000398 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000399 self.display_port_binding_error()
400 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000401 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
402 self.port = self.rpcclt.listening_sock.getsockname()[1]
403 # if PORT was not 0, probably working with a remote execution server
404 if PORT != 0:
405 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
406 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
407 # on Windows since the implementation allows two active sockets on
408 # the same address!
409 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
410 socket.SO_REUSEADDR, 1)
411 self.spawn_subprocess()
412 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000413 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000414 self.rpcclt.listening_sock.settimeout(10)
415 try:
416 self.rpcclt.accept()
417 except socket.timeout, err:
418 self.display_no_subprocess_error()
419 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000420 self.rpcclt.register("stdin", self.tkconsole)
421 self.rpcclt.register("stdout", self.tkconsole.stdout)
422 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000423 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000424 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000425 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500426 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000427 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000428 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000429
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500430 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000431 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000432 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000433 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000434 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000435 debug = self.getdebugger()
436 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000437 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000438 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000439 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
440 except:
441 pass
442 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000443 self.rpcclt.close()
444 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000445 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000446 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000447 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000448 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000449 try:
450 self.rpcclt.accept()
451 except socket.timeout, err:
452 self.display_no_subprocess_error()
453 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500454 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000455 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000456 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000457 if was_executing:
458 console.write('\n')
459 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000460 halfbar = ((int(console.width) - 16) // 2) * '='
461 console.write(halfbar + ' RESTART ' + halfbar)
462 console.text.mark_set("restart", "end-1c")
463 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000464 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000465 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000466 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000467 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000468 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000469 # reload remote debugger breakpoints for all PyShellEditWindows
470 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700471 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000472 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000473 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000474
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000475 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000476 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477
478 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000480
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000481 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000482 try:
483 self.rpcclt.close()
484 except AttributeError: # no socket
485 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000486 self.unix_terminate()
487 self.tkconsole.executing = False
488 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000489
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 def unix_terminate(self):
491 "UNIX: make sure subprocess is terminated and collect status"
492 if hasattr(os, 'kill'):
493 try:
494 os.kill(self.rpcpid, SIGTERM)
495 except OSError:
496 # process already terminated:
497 return
498 else:
499 try:
500 os.waitpid(self.rpcpid, 0)
501 except OSError:
502 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000503
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500504 def transfer_path(self, with_cwd=False):
505 if with_cwd: # Issue 13506
506 path = [''] # include Current Working Directory
507 path.extend(sys.path)
508 else:
509 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500510
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000511 self.runcommand("""if 1:
512 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000513 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000514 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500515 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000516
Chui Tey5d2af632002-05-26 13:36:41 +0000517 active_seq = None
518
519 def poll_subprocess(self):
520 clt = self.rpcclt
521 if clt is None:
522 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000523 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000524 response = clt.pollresponse(self.active_seq, wait=0.05)
525 except (EOFError, IOError, KeyboardInterrupt):
526 # lost connection or subprocess terminated itself, restart
527 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000528 if self.tkconsole.closing:
529 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000530 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000531 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000532 if response:
533 self.tkconsole.resetoutput()
534 self.active_seq = None
535 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000536 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000537 if how == "OK":
538 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000539 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000540 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000541 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
542 self.remote_stack_viewer()
543 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000544 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
545 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000546 print >>console, errmsg, what
547 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000548 try:
549 self.tkconsole.endexecuting()
550 except AttributeError: # shell may have closed
551 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000552 # Reschedule myself
553 if not self.tkconsole.closing:
554 self.tkconsole.text.after(self.tkconsole.pollinterval,
555 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000556
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000557 debugger = None
558
559 def setdebugger(self, debugger):
560 self.debugger = debugger
561
562 def getdebugger(self):
563 return self.debugger
564
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000565 def open_remote_stack_viewer(self):
566 """Initiate the remote stack viewer from a separate thread.
567
568 This method is called from the subprocess, and by returning from this
569 method we allow the subprocess to unblock. After a bit the shell
570 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000571 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000572 the RPC mechanism.
573
574 """
575 self.tkconsole.text.after(300, self.remote_stack_viewer)
576 return
577
Chui Tey5d2af632002-05-26 13:36:41 +0000578 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000579 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000580 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000581 if oid is None:
582 self.tkconsole.root.bell()
583 return
584 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000585 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000586 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000587 theme = idleConf.GetOption('main','Theme','name')
588 background = idleConf.GetHighlight(theme, 'normal')['background']
589 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000590 sc.frame.pack(expand=1, fill="both")
591 node = TreeNode(sc.canvas, None, item)
592 node.expand()
593 # XXX Should GC the remote tree when closing the window
594
David Scherer7aced172000-08-15 01:13:23 +0000595 gid = 0
596
597 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000598 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000599 filename = self.stuffsource(source)
600 self.execfile(filename, source)
601
602 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000603 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000604 if source is None:
605 source = open(filename, "r").read()
606 try:
607 code = compile(source, filename, "exec")
608 except (OverflowError, SyntaxError):
609 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000610 tkerr = self.tkconsole.stderr
611 print>>tkerr, '*** Error in script or command!\n'
612 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000613 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000614 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000615 else:
616 self.runcode(code)
617
618 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000619 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000620 filename = self.stuffsource(source)
621 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000622 self.save_warnings_filters = warnings.filters[:]
623 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000624 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000625 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000626 try:
627 source = source.encode(IOBinding.encoding)
628 except UnicodeError:
629 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000630 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000631 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000632 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000633 # InteractiveInterpreter.runsource() calls its runcode() method,
634 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000635 return InteractiveInterpreter.runsource(self, source, filename)
636 finally:
637 if self.save_warnings_filters is not None:
638 warnings.filters[:] = self.save_warnings_filters
639 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000640
641 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000642 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000643 filename = "<pyshell#%d>" % self.gid
644 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000645 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000646 linecache.cache[filename] = len(source)+1, 0, lines, filename
647 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000648
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000649 def prepend_syspath(self, filename):
650 "Prepend sys.path with file's directory if not already included"
651 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000652 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000653 import sys as _sys
654 from os.path import dirname as _dirname
655 _dir = _dirname(_filename)
656 if not _dir in _sys.path:
657 _sys.path.insert(0, _dir)
658 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000659 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000660
David Scherer7aced172000-08-15 01:13:23 +0000661 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000662 """Extend base class method: Add Colorizing
663
664 Color the offending position instead of printing it and pointing at it
665 with a caret.
666
667 """
David Scherer7aced172000-08-15 01:13:23 +0000668 text = self.tkconsole.text
669 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000670 if stuff:
671 msg, lineno, offset, line = stuff
672 if lineno == 1:
673 pos = "iomark + %d chars" % (offset-1)
674 else:
675 pos = "iomark linestart + %d lines + %d chars" % \
676 (lineno-1, offset-1)
677 text.tag_add("ERROR", pos)
678 text.see(pos)
679 char = text.get(pos)
680 if char and char in IDENTCHARS:
681 text.tag_add("ERROR", pos + " wordstart", pos)
682 self.tkconsole.resetoutput()
683 self.write("SyntaxError: %s\n" % str(msg))
684 else:
David Scherer7aced172000-08-15 01:13:23 +0000685 self.tkconsole.resetoutput()
686 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000687 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000688
689 def unpackerror(self):
690 type, value, tb = sys.exc_info()
691 ok = type is SyntaxError
692 if ok:
693 try:
694 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000695 if not offset:
696 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000697 except:
698 ok = 0
699 if ok:
700 return msg, lineno, offset, line
701 else:
702 return None
703
704 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000705 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000706 self.tkconsole.resetoutput()
707 self.checklinecache()
708 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000709 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
710 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000711
712 def checklinecache(self):
713 c = linecache.cache
714 for key in c.keys():
715 if key[:1] + key[-1:] != "<>":
716 del c[key]
717
Chui Tey5d2af632002-05-26 13:36:41 +0000718 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000719 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000720 # The code better not raise an exception!
721 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000722 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000723 return 0
724 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000725 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000726 else:
727 exec code in self.locals
728 return 1
729
David Scherer7aced172000-08-15 01:13:23 +0000730 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000731 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000732 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000733 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000734 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000735 if self.save_warnings_filters is not None:
736 warnings.filters[:] = self.save_warnings_filters
737 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000738 debugger = self.debugger
739 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000740 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000741 if not debugger and self.rpcclt is not None:
742 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
743 (code,), {})
744 elif debugger:
745 debugger.run(code, self.locals)
746 else:
747 exec code in self.locals
748 except SystemExit:
749 if not self.tkconsole.closing:
750 if tkMessageBox.askyesno(
751 "Exit?",
752 "Do you want to exit altogether?",
753 default="yes",
754 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000755 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000756 else:
757 self.showtraceback()
758 else:
759 raise
760 except:
761 if use_subprocess:
762 print >>self.tkconsole.stderr, \
763 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000764 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000765 self.tkconsole.endexecuting()
766 else:
767 if self.tkconsole.canceled:
768 self.tkconsole.canceled = False
769 print >>self.tkconsole.stderr, "KeyboardInterrupt"
770 else:
771 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000772 finally:
773 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000774 try:
775 self.tkconsole.endexecuting()
776 except AttributeError: # shell may have closed
777 pass
David Scherer7aced172000-08-15 01:13:23 +0000778
779 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000780 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000781 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000782
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000783 def display_port_binding_error(self):
784 tkMessageBox.showerror(
785 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000786 "IDLE can't bind to a TCP/IP port, which is necessary to "
787 "communicate with its Python execution server. This might be "
788 "because no networking is installed on this computer. "
789 "Run IDLE with the -n command line switch to start without a "
790 "subprocess and refer to Help/IDLE Help 'Running without a "
791 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000792 master=self.tkconsole.text)
793
794 def display_no_subprocess_error(self):
795 tkMessageBox.showerror(
796 "Subprocess Startup Error",
797 "IDLE's subprocess didn't make connection. Either IDLE can't "
798 "start a subprocess or personal firewall software is blocking "
799 "the connection.",
800 master=self.tkconsole.text)
801
802 def display_executing_dialog(self):
803 tkMessageBox.showerror(
804 "Already executing",
805 "The Python Shell window is already executing a command; "
806 "please wait until it is finished.",
807 master=self.tkconsole.text)
808
809
David Scherer7aced172000-08-15 01:13:23 +0000810class PyShell(OutputWindow):
811
812 shell_title = "Python Shell"
813
814 # Override classes
815 ColorDelegator = ModifiedColorDelegator
816 UndoDelegator = ModifiedUndoDelegator
817
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000818 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000819 menu_specs = [
820 ("file", "_File"),
821 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000822 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000823 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000824 ("windows", "_Windows"),
825 ("help", "_Help"),
826 ]
David Scherer7aced172000-08-15 01:13:23 +0000827
Ronald Oussoren19302d92006-06-11 14:33:36 +0000828 if macosxSupport.runningAsOSXApp():
829 del menu_specs[-3]
830 menu_specs[-2] = ("windows", "_Window")
831
832
David Scherer7aced172000-08-15 01:13:23 +0000833 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000834 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000835
836 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000837 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000838 ms = self.menu_specs
839 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000840 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000841 self.interp = ModifiedInterpreter(self)
842 if flist is None:
843 root = Tk()
844 fixwordbreaks(root)
845 root.withdraw()
846 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000847 #
David Scherer7aced172000-08-15 01:13:23 +0000848 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000849 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000850## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
851 self.usetabs = True
852 # indentwidth must be 8 when using tabs. See note in EditorWindow:
853 self.indentwidth = 8
854 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000855 #
David Scherer7aced172000-08-15 01:13:23 +0000856 text = self.text
857 text.configure(wrap="char")
858 text.bind("<<newline-and-indent>>", self.enter_callback)
859 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
860 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000861 text.bind("<<end-of-file>>", self.eof_callback)
862 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000863 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000864 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000865 if use_subprocess:
866 text.bind("<<view-restart>>", self.view_restart_mark)
867 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000868 #
David Scherer7aced172000-08-15 01:13:23 +0000869 self.save_stdout = sys.stdout
870 self.save_stderr = sys.stderr
871 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000872 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000873 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
874 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
875 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000876 if not use_subprocess:
877 sys.stdout = self.stdout
878 sys.stderr = self.stderr
879 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000880 #
David Scherer7aced172000-08-15 01:13:23 +0000881 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000882 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000883 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000884
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000885 def get_standard_extension_names(self):
886 return idleConf.GetExtensions(shell_only=True)
887
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000888 reading = False
889 executing = False
890 canceled = False
891 endoffile = False
892 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000893
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000894 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000895 global warning_stream
896 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000897
898 def get_warning_stream(self):
899 return warning_stream
900
David Scherer7aced172000-08-15 01:13:23 +0000901 def toggle_debugger(self, event=None):
902 if self.executing:
903 tkMessageBox.showerror("Don't debug now",
904 "You can only toggle the debugger when idle",
905 master=self.text)
906 self.set_debugger_indicator()
907 return "break"
908 else:
909 db = self.interp.getdebugger()
910 if db:
911 self.close_debugger()
912 else:
913 self.open_debugger()
914
915 def set_debugger_indicator(self):
916 db = self.interp.getdebugger()
917 self.setvar("<<toggle-debugger>>", not not db)
918
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000919 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000920 pass # All we need is the variable
921
922 def close_debugger(self):
923 db = self.interp.getdebugger()
924 if db:
925 self.interp.setdebugger(None)
926 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000927 if self.interp.rpcclt:
928 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000929 self.resetoutput()
930 self.console.write("[DEBUG OFF]\n")
931 sys.ps1 = ">>> "
932 self.showprompt()
933 self.set_debugger_indicator()
934
935 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000936 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000937 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
938 self)
939 else:
940 dbg_gui = Debugger.Debugger(self)
941 self.interp.setdebugger(dbg_gui)
942 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000943 sys.ps1 = "[DEBUG ON]\n>>> "
944 self.showprompt()
945 self.set_debugger_indicator()
946
David Scherer7aced172000-08-15 01:13:23 +0000947 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000948 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000949 self.resetoutput()
950 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000951
952 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000953 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000954 self.executing = 0
955 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000956 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000957
958 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000959 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000960 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000961 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000962 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000963 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000964 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000965 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000966 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000967 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000968 if self.reading:
969 self.top.quit()
970 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000971 self.closing = True
972 # Wait for poll_subprocess() rescheduling to stop
973 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000974
975 def close2(self):
976 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000977
978 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000979 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000980 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000981 if use_subprocess:
982 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000983 # Restore std streams
984 sys.stdout = self.save_stdout
985 sys.stderr = self.save_stderr
986 sys.stdin = self.save_stdin
987 # Break cycles
988 self.interp = None
989 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000990 self.flist.pyshell = None
991 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000992 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000993
994 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000995 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000996 return True
David Scherer7aced172000-08-15 01:13:23 +0000997
998 def short_title(self):
999 return self.shell_title
1000
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001001 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001002 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001003
David Scherer7aced172000-08-15 01:13:23 +00001004 def begin(self):
1005 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001006 if use_subprocess:
1007 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001008 client = self.interp.start_subprocess()
1009 if not client:
1010 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001011 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001012 else:
1013 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001014 self.write("Python %s on %s\n%s\n%s" %
1015 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001016 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001017 import Tkinter
1018 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001019 return True
David Scherer7aced172000-08-15 01:13:23 +00001020
1021 def readline(self):
1022 save = self.reading
1023 try:
1024 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001025 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001026 finally:
1027 self.reading = save
1028 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001029 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1030 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001031 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001032 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001033 try:
1034 line = line.encode(IOBinding.encoding)
1035 except UnicodeError:
1036 pass
David Scherer7aced172000-08-15 01:13:23 +00001037 self.resetoutput()
1038 if self.canceled:
1039 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001040 if not use_subprocess:
1041 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001042 if self.endoffile:
1043 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001045 return line
1046
1047 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001048 return True
David Scherer7aced172000-08-15 01:13:23 +00001049
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001050 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001051 try:
1052 if self.text.compare("sel.first", "!=", "sel.last"):
1053 return # Active selection -- always use default binding
1054 except:
1055 pass
1056 if not (self.executing or self.reading):
1057 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001058 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001059 self.showprompt()
1060 return "break"
1061 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001062 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001063 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001064 if self.interp.getdebugger():
1065 self.interp.restart_subprocess()
1066 else:
1067 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 if self.reading:
1069 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001070 return "break"
1071
1072 def eof_callback(self, event):
1073 if self.executing and not self.reading:
1074 return # Let the default binding (delete next char) take over
1075 if not (self.text.compare("iomark", "==", "insert") and
1076 self.text.compare("insert", "==", "end-1c")):
1077 return # Let the default binding (delete next char) take over
1078 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001079 self.resetoutput()
1080 self.close()
1081 else:
1082 self.canceled = 0
1083 self.endoffile = 1
1084 self.top.quit()
1085 return "break"
1086
David Scherer7aced172000-08-15 01:13:23 +00001087 def linefeed_callback(self, event):
1088 # Insert a linefeed without entering anything (still autoindented)
1089 if self.reading:
1090 self.text.insert("insert", "\n")
1091 self.text.see("insert")
1092 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001093 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001094 return "break"
1095
1096 def enter_callback(self, event):
1097 if self.executing and not self.reading:
1098 return # Let the default binding (insert '\n') take over
1099 # If some text is selected, recall the selection
1100 # (but only if this before the I/O mark)
1101 try:
1102 sel = self.text.get("sel.first", "sel.last")
1103 if sel:
1104 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001105 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001106 return "break"
1107 except:
1108 pass
1109 # If we're strictly before the line containing iomark, recall
1110 # the current line, less a leading prompt, less leading or
1111 # trailing whitespace
1112 if self.text.compare("insert", "<", "iomark linestart"):
1113 # Check if there's a relevant stdin range -- if so, use it
1114 prev = self.text.tag_prevrange("stdin", "insert")
1115 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001116 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001117 return "break"
1118 next = self.text.tag_nextrange("stdin", "insert")
1119 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001120 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001121 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001122 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001123 indices = self.text.tag_nextrange("console", "insert linestart")
1124 if indices and \
1125 self.text.compare(indices[0], "<=", "insert linestart"):
1126 self.recall(self.text.get(indices[1], "insert lineend"), event)
1127 else:
1128 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001129 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001130 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001131 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001132 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001133 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001134 # If we're in the current input and there's only whitespace
1135 # beyond the cursor, erase that whitespace first
1136 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001137 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001138 self.text.delete("insert", "end-1c")
1139 # If we're in the current input before its last line,
1140 # insert a newline right at the insert point
1141 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001142 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001143 return "break"
1144 # We're in the last line; append a newline and submit it
1145 self.text.mark_set("insert", "end-1c")
1146 if self.reading:
1147 self.text.insert("insert", "\n")
1148 self.text.see("insert")
1149 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001150 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001151 self.text.tag_add("stdin", "iomark", "end-1c")
1152 self.text.update_idletasks()
1153 if self.reading:
1154 self.top.quit() # Break out of recursive mainloop() in raw_input()
1155 else:
1156 self.runit()
1157 return "break"
1158
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001159 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001160 # remove leading and trailing empty or whitespace lines
1161 s = re.sub(r'^\s*\n', '' , s)
1162 s = re.sub(r'\n\s*$', '', s)
1163 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001164 self.text.undo_block_start()
1165 try:
1166 self.text.tag_remove("sel", "1.0", "end")
1167 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001168 prefix = self.text.get("insert linestart", "insert")
1169 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001170 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001171 prefix = self.text.get("insert linestart", "insert")
1172 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001173 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001174 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1175 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001176 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001177 if line.startswith(orig_base_indent):
1178 # replace orig base indentation with new indentation
1179 line = new_base_indent + line[len(orig_base_indent):]
1180 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001181 finally:
1182 self.text.see("insert")
1183 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001184
1185 def runit(self):
1186 line = self.text.get("iomark", "end-1c")
1187 # Strip off last newline and surrounding whitespace.
1188 # (To allow you to hit return twice to end a statement.)
1189 i = len(line)
1190 while i > 0 and line[i-1] in " \t":
1191 i = i-1
1192 if i > 0 and line[i-1] == "\n":
1193 i = i-1
1194 while i > 0 and line[i-1] in " \t":
1195 i = i-1
1196 line = line[:i]
1197 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001198
David Scherer7aced172000-08-15 01:13:23 +00001199 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001200 if self.interp.rpcclt:
1201 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001202 try:
1203 sys.last_traceback
1204 except:
1205 tkMessageBox.showerror("No stack trace",
1206 "There is no stack trace yet.\n"
1207 "(sys.last_traceback is not defined)",
1208 master=self.text)
1209 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001210 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001211 sv = StackBrowser(self.root, self.flist)
1212
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001213 def view_restart_mark(self, event=None):
1214 self.text.see("iomark")
1215 self.text.see("restart")
1216
1217 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001218 "Callback for Run/Restart Shell Cntl-F6"
1219 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001220
David Scherer7aced172000-08-15 01:13:23 +00001221 def showprompt(self):
1222 self.resetoutput()
1223 try:
1224 s = str(sys.ps1)
1225 except:
1226 s = ""
1227 self.console.write(s)
1228 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001229 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001230 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001231
1232 def resetoutput(self):
1233 source = self.text.get("iomark", "end-1c")
1234 if self.history:
1235 self.history.history_store(source)
1236 if self.text.get("end-2c") != "\n":
1237 self.text.insert("end-1c", "\n")
1238 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001239 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001240 sys.stdout.softspace = 0
1241
1242 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001243 try:
1244 self.text.mark_gravity("iomark", "right")
1245 OutputWindow.write(self, s, tags, "iomark")
1246 self.text.mark_gravity("iomark", "left")
1247 except:
1248 pass
David Scherer7aced172000-08-15 01:13:23 +00001249 if self.canceled:
1250 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001251 if not use_subprocess:
1252 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001253
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001254class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001255
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001256 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001257 self.shell = shell
1258 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001259 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001260 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001261
1262 def write(self, s):
1263 self.shell.write(s, self.tags)
1264
Florent Xiclunad630c042010-04-02 07:24:52 +00001265 def writelines(self, lines):
1266 for line in lines:
1267 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001268
1269 def flush(self):
1270 pass
1271
1272 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001273 return True
David Scherer7aced172000-08-15 01:13:23 +00001274
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001275
David Scherer7aced172000-08-15 01:13:23 +00001276usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001277
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001278USAGE: idle [-deins] [-t title] [file]*
1279 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1280 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001281
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001282 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001283 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001284
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001285The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001286
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001287 -e open an edit window
1288 -i open a shell window
1289
1290The following options imply -i and will open a shell:
1291
1292 -c cmd run the command in a shell, or
1293 -r file run script from file
1294
1295 -d enable the debugger
1296 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1297 -t title set title of shell window
1298
1299A default edit window will be bypassed when -c, -r, or - are used.
1300
1301[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1302
1303Examples:
1304
1305idle
1306 Open an edit window or shell depending on IDLE's configuration.
1307
1308idle foo.py foobar.py
1309 Edit the files, also open a shell if configured to start with shell.
1310
1311idle -est "Baz" foo.py
1312 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1313 window with the title "Baz".
1314
1315idle -c "import sys; print sys.argv" "foo"
1316 Open a shell window and run the command, passing "-c" in sys.argv[0]
1317 and "foo" in sys.argv[1].
1318
1319idle -d -s -r foo.py "Hello World"
1320 Open a shell window, run a startup script, enable the debugger, and
1321 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1322 sys.argv[1].
1323
1324echo "import sys; print sys.argv" | idle - "foobar"
1325 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1326 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001327"""
1328
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001329def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001331
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001332 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001333 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 enable_edit = False
1335 debug = False
1336 cmd = None
1337 script = None
1338 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001339 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001340 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001341 except getopt.error, msg:
1342 sys.stderr.write("Error: %s\n" % str(msg))
1343 sys.stderr.write(usage_msg)
1344 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001345 for o, a in opts:
1346 if o == '-c':
1347 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001349 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001350 debug = True
1351 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001352 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001354 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001355 if o == '-h':
1356 sys.stdout.write(usage_msg)
1357 sys.exit()
1358 if o == '-i':
1359 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001360 if o == '-n':
1361 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001362 if o == '-r':
1363 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 if os.path.isfile(script):
1365 pass
1366 else:
1367 print "No script file: ", script
1368 sys.exit()
1369 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 startup = True
1372 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 if o == '-t':
1374 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 enable_shell = True
1376 if args and args[0] == '-':
1377 cmd = sys.stdin.read()
1378 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 for i in range(len(sys.path)):
1381 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 if args and args[0] == '-':
1383 sys.argv = [''] + args[1:]
1384 elif cmd:
1385 sys.argv = ['-c'] + args
1386 elif script:
1387 sys.argv = [script] + args
1388 elif args:
1389 enable_edit = True
1390 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 for filename in args:
1392 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001393 for dir in pathx:
1394 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001395 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001396 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001397 else:
1398 dir = os.getcwd()
1399 if not dir in sys.path:
1400 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001401 # check the IDLE settings configuration (but command line overrides)
1402 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001403 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001404 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001405 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001406 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001407
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001408 fixwordbreaks(root)
1409 root.withdraw()
1410 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001411 macosxSupport.setupApp(root, flist)
1412
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 if enable_edit:
1414 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001415 for filename in args[:]:
1416 if flist.open(filename) is None:
1417 # filename is a directory actually, disconsider it
1418 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 if not args:
1420 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001421 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001422 shell = flist.open_shell()
1423 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001424 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001425
1426 if macosxSupport.runningAsOSXApp() and flist.dict:
1427 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001428 # IDLE to be launched the shell window will open just in front of
1429 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001430 # there are open files.
1431 shell.top.lower()
1432
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 shell = flist.pyshell
1434 # handle remaining options:
1435 if debug:
1436 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001437 if startup:
1438 filename = os.environ.get("IDLESTARTUP") or \
1439 os.environ.get("PYTHONSTARTUP")
1440 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001441 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001442 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001443 shell.interp.runcommand("""if 1:
1444 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001445 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001446 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001447 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 if cmd:
1449 shell.interp.execsource(cmd)
1450 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001451 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001452 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001453
Ned Deily2a6f4b32011-01-30 00:18:47 +00001454 # Check for problematic OS X Tk versions and print a warning message
1455 # in the IDLE shell window; this is less intrusive than always opening
1456 # a separate window.
1457 tkversionwarning = macosxSupport.tkVersionWarning(root)
1458 if tkversionwarning:
1459 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1460
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001461 root.mainloop()
1462 root.destroy()
1463
David Scherer7aced172000-08-15 01:13:23 +00001464if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001465 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001466 main()