blob: 96efcecb54fa06d923be1a035cf49c4471ad6534 [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)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000426 self.transfer_path()
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
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000430 def restart_subprocess(self):
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
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000454 self.transfer_path()
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
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000504 def transfer_path(self):
505 self.runcommand("""if 1:
506 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000507 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000508 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000509 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000510
Chui Tey5d2af632002-05-26 13:36:41 +0000511 active_seq = None
512
513 def poll_subprocess(self):
514 clt = self.rpcclt
515 if clt is None:
516 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000517 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000518 response = clt.pollresponse(self.active_seq, wait=0.05)
519 except (EOFError, IOError, KeyboardInterrupt):
520 # lost connection or subprocess terminated itself, restart
521 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000522 if self.tkconsole.closing:
523 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000524 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000525 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000526 if response:
527 self.tkconsole.resetoutput()
528 self.active_seq = None
529 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000530 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000531 if how == "OK":
532 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000533 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000534 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000535 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
536 self.remote_stack_viewer()
537 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000538 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
539 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000540 print >>console, errmsg, what
541 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000542 try:
543 self.tkconsole.endexecuting()
544 except AttributeError: # shell may have closed
545 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000546 # Reschedule myself
547 if not self.tkconsole.closing:
548 self.tkconsole.text.after(self.tkconsole.pollinterval,
549 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000550
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000551 debugger = None
552
553 def setdebugger(self, debugger):
554 self.debugger = debugger
555
556 def getdebugger(self):
557 return self.debugger
558
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000559 def open_remote_stack_viewer(self):
560 """Initiate the remote stack viewer from a separate thread.
561
562 This method is called from the subprocess, and by returning from this
563 method we allow the subprocess to unblock. After a bit the shell
564 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000565 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000566 the RPC mechanism.
567
568 """
569 self.tkconsole.text.after(300, self.remote_stack_viewer)
570 return
571
Chui Tey5d2af632002-05-26 13:36:41 +0000572 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000573 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000574 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000575 if oid is None:
576 self.tkconsole.root.bell()
577 return
578 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000579 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000580 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000581 theme = idleConf.GetOption('main','Theme','name')
582 background = idleConf.GetHighlight(theme, 'normal')['background']
583 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000584 sc.frame.pack(expand=1, fill="both")
585 node = TreeNode(sc.canvas, None, item)
586 node.expand()
587 # XXX Should GC the remote tree when closing the window
588
David Scherer7aced172000-08-15 01:13:23 +0000589 gid = 0
590
591 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000592 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000593 filename = self.stuffsource(source)
594 self.execfile(filename, source)
595
596 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000597 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000598 if source is None:
599 source = open(filename, "r").read()
600 try:
601 code = compile(source, filename, "exec")
602 except (OverflowError, SyntaxError):
603 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000604 tkerr = self.tkconsole.stderr
605 print>>tkerr, '*** Error in script or command!\n'
606 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000607 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000608 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000609 else:
610 self.runcode(code)
611
612 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000613 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000614 filename = self.stuffsource(source)
615 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000616 self.save_warnings_filters = warnings.filters[:]
617 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000618 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000619 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000620 try:
621 source = source.encode(IOBinding.encoding)
622 except UnicodeError:
623 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000624 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000625 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000626 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000627 # InteractiveInterpreter.runsource() calls its runcode() method,
628 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000629 return InteractiveInterpreter.runsource(self, source, filename)
630 finally:
631 if self.save_warnings_filters is not None:
632 warnings.filters[:] = self.save_warnings_filters
633 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000634
635 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000636 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000637 filename = "<pyshell#%d>" % self.gid
638 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000639 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000640 linecache.cache[filename] = len(source)+1, 0, lines, filename
641 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000642
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000643 def prepend_syspath(self, filename):
644 "Prepend sys.path with file's directory if not already included"
645 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000646 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000647 import sys as _sys
648 from os.path import dirname as _dirname
649 _dir = _dirname(_filename)
650 if not _dir in _sys.path:
651 _sys.path.insert(0, _dir)
652 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000653 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000654
David Scherer7aced172000-08-15 01:13:23 +0000655 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000656 """Extend base class method: Add Colorizing
657
658 Color the offending position instead of printing it and pointing at it
659 with a caret.
660
661 """
David Scherer7aced172000-08-15 01:13:23 +0000662 text = self.tkconsole.text
663 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000664 if stuff:
665 msg, lineno, offset, line = stuff
666 if lineno == 1:
667 pos = "iomark + %d chars" % (offset-1)
668 else:
669 pos = "iomark linestart + %d lines + %d chars" % \
670 (lineno-1, offset-1)
671 text.tag_add("ERROR", pos)
672 text.see(pos)
673 char = text.get(pos)
674 if char and char in IDENTCHARS:
675 text.tag_add("ERROR", pos + " wordstart", pos)
676 self.tkconsole.resetoutput()
677 self.write("SyntaxError: %s\n" % str(msg))
678 else:
David Scherer7aced172000-08-15 01:13:23 +0000679 self.tkconsole.resetoutput()
680 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000681 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000682
683 def unpackerror(self):
684 type, value, tb = sys.exc_info()
685 ok = type is SyntaxError
686 if ok:
687 try:
688 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000689 if not offset:
690 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000691 except:
692 ok = 0
693 if ok:
694 return msg, lineno, offset, line
695 else:
696 return None
697
698 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000699 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000700 self.tkconsole.resetoutput()
701 self.checklinecache()
702 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000703 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
704 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000705
706 def checklinecache(self):
707 c = linecache.cache
708 for key in c.keys():
709 if key[:1] + key[-1:] != "<>":
710 del c[key]
711
Chui Tey5d2af632002-05-26 13:36:41 +0000712 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000713 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000714 # The code better not raise an exception!
715 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000716 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000717 return 0
718 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000719 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000720 else:
721 exec code in self.locals
722 return 1
723
David Scherer7aced172000-08-15 01:13:23 +0000724 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000725 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000726 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000727 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000728 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000729 if self.save_warnings_filters is not None:
730 warnings.filters[:] = self.save_warnings_filters
731 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000732 debugger = self.debugger
733 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000734 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000735 if not debugger and self.rpcclt is not None:
736 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
737 (code,), {})
738 elif debugger:
739 debugger.run(code, self.locals)
740 else:
741 exec code in self.locals
742 except SystemExit:
743 if not self.tkconsole.closing:
744 if tkMessageBox.askyesno(
745 "Exit?",
746 "Do you want to exit altogether?",
747 default="yes",
748 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000749 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000750 else:
751 self.showtraceback()
752 else:
753 raise
754 except:
755 if use_subprocess:
756 print >>self.tkconsole.stderr, \
757 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000758 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000759 self.tkconsole.endexecuting()
760 else:
761 if self.tkconsole.canceled:
762 self.tkconsole.canceled = False
763 print >>self.tkconsole.stderr, "KeyboardInterrupt"
764 else:
765 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000766 finally:
767 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000768 try:
769 self.tkconsole.endexecuting()
770 except AttributeError: # shell may have closed
771 pass
David Scherer7aced172000-08-15 01:13:23 +0000772
773 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000774 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000775 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000776
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000777 def display_port_binding_error(self):
778 tkMessageBox.showerror(
779 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000780 "IDLE can't bind to a TCP/IP port, which is necessary to "
781 "communicate with its Python execution server. This might be "
782 "because no networking is installed on this computer. "
783 "Run IDLE with the -n command line switch to start without a "
784 "subprocess and refer to Help/IDLE Help 'Running without a "
785 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000786 master=self.tkconsole.text)
787
788 def display_no_subprocess_error(self):
789 tkMessageBox.showerror(
790 "Subprocess Startup Error",
791 "IDLE's subprocess didn't make connection. Either IDLE can't "
792 "start a subprocess or personal firewall software is blocking "
793 "the connection.",
794 master=self.tkconsole.text)
795
796 def display_executing_dialog(self):
797 tkMessageBox.showerror(
798 "Already executing",
799 "The Python Shell window is already executing a command; "
800 "please wait until it is finished.",
801 master=self.tkconsole.text)
802
803
David Scherer7aced172000-08-15 01:13:23 +0000804class PyShell(OutputWindow):
805
806 shell_title = "Python Shell"
807
808 # Override classes
809 ColorDelegator = ModifiedColorDelegator
810 UndoDelegator = ModifiedUndoDelegator
811
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000812 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000813 menu_specs = [
814 ("file", "_File"),
815 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000816 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000817 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000818 ("windows", "_Windows"),
819 ("help", "_Help"),
820 ]
David Scherer7aced172000-08-15 01:13:23 +0000821
Ronald Oussoren19302d92006-06-11 14:33:36 +0000822 if macosxSupport.runningAsOSXApp():
823 del menu_specs[-3]
824 menu_specs[-2] = ("windows", "_Window")
825
826
David Scherer7aced172000-08-15 01:13:23 +0000827 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000828 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000829
830 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000831 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000832 ms = self.menu_specs
833 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000834 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000835 self.interp = ModifiedInterpreter(self)
836 if flist is None:
837 root = Tk()
838 fixwordbreaks(root)
839 root.withdraw()
840 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000841 #
David Scherer7aced172000-08-15 01:13:23 +0000842 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000843 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000844## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
845 self.usetabs = True
846 # indentwidth must be 8 when using tabs. See note in EditorWindow:
847 self.indentwidth = 8
848 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000849 #
David Scherer7aced172000-08-15 01:13:23 +0000850 text = self.text
851 text.configure(wrap="char")
852 text.bind("<<newline-and-indent>>", self.enter_callback)
853 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
854 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000855 text.bind("<<end-of-file>>", self.eof_callback)
856 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000857 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000858 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000859 if use_subprocess:
860 text.bind("<<view-restart>>", self.view_restart_mark)
861 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000862 #
David Scherer7aced172000-08-15 01:13:23 +0000863 self.save_stdout = sys.stdout
864 self.save_stderr = sys.stderr
865 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000866 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000867 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
868 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
869 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000870 if not use_subprocess:
871 sys.stdout = self.stdout
872 sys.stderr = self.stderr
873 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000874 #
David Scherer7aced172000-08-15 01:13:23 +0000875 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000876 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000877 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000878
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000879 def get_standard_extension_names(self):
880 return idleConf.GetExtensions(shell_only=True)
881
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000882 reading = False
883 executing = False
884 canceled = False
885 endoffile = False
886 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000887
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000888 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000889 global warning_stream
890 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000891
892 def get_warning_stream(self):
893 return warning_stream
894
David Scherer7aced172000-08-15 01:13:23 +0000895 def toggle_debugger(self, event=None):
896 if self.executing:
897 tkMessageBox.showerror("Don't debug now",
898 "You can only toggle the debugger when idle",
899 master=self.text)
900 self.set_debugger_indicator()
901 return "break"
902 else:
903 db = self.interp.getdebugger()
904 if db:
905 self.close_debugger()
906 else:
907 self.open_debugger()
908
909 def set_debugger_indicator(self):
910 db = self.interp.getdebugger()
911 self.setvar("<<toggle-debugger>>", not not db)
912
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000913 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000914 pass # All we need is the variable
915
916 def close_debugger(self):
917 db = self.interp.getdebugger()
918 if db:
919 self.interp.setdebugger(None)
920 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000921 if self.interp.rpcclt:
922 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000923 self.resetoutput()
924 self.console.write("[DEBUG OFF]\n")
925 sys.ps1 = ">>> "
926 self.showprompt()
927 self.set_debugger_indicator()
928
929 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000930 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000931 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
932 self)
933 else:
934 dbg_gui = Debugger.Debugger(self)
935 self.interp.setdebugger(dbg_gui)
936 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000937 sys.ps1 = "[DEBUG ON]\n>>> "
938 self.showprompt()
939 self.set_debugger_indicator()
940
David Scherer7aced172000-08-15 01:13:23 +0000941 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000942 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000943 self.resetoutput()
944 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000945
946 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000947 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000948 self.executing = 0
949 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000950 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000951
952 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000953 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000954 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000955 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000956 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000957 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000958 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000959 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000960 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000961 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000962 if self.reading:
963 self.top.quit()
964 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000965 self.closing = True
966 # Wait for poll_subprocess() rescheduling to stop
967 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000968
969 def close2(self):
970 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000971
972 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000973 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000974 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000975 if use_subprocess:
976 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000977 # Restore std streams
978 sys.stdout = self.save_stdout
979 sys.stderr = self.save_stderr
980 sys.stdin = self.save_stdin
981 # Break cycles
982 self.interp = None
983 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000984 self.flist.pyshell = None
985 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000986 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000987
988 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000989 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000990 return True
David Scherer7aced172000-08-15 01:13:23 +0000991
992 def short_title(self):
993 return self.shell_title
994
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000995 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000996 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000997
David Scherer7aced172000-08-15 01:13:23 +0000998 def begin(self):
999 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001000 if use_subprocess:
1001 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001002 client = self.interp.start_subprocess()
1003 if not client:
1004 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001005 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001006 else:
1007 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001008 self.write("Python %s on %s\n%s\n%s" %
1009 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001010 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001011 import Tkinter
1012 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001013 return True
David Scherer7aced172000-08-15 01:13:23 +00001014
1015 def readline(self):
1016 save = self.reading
1017 try:
1018 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001019 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001020 finally:
1021 self.reading = save
1022 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001023 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1024 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001025 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001026 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001027 try:
1028 line = line.encode(IOBinding.encoding)
1029 except UnicodeError:
1030 pass
David Scherer7aced172000-08-15 01:13:23 +00001031 self.resetoutput()
1032 if self.canceled:
1033 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001034 if not use_subprocess:
1035 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001036 if self.endoffile:
1037 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001038 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001039 return line
1040
1041 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001042 return True
David Scherer7aced172000-08-15 01:13:23 +00001043
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001044 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001045 try:
1046 if self.text.compare("sel.first", "!=", "sel.last"):
1047 return # Active selection -- always use default binding
1048 except:
1049 pass
1050 if not (self.executing or self.reading):
1051 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001052 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001053 self.showprompt()
1054 return "break"
1055 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001056 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001057 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001058 if self.interp.getdebugger():
1059 self.interp.restart_subprocess()
1060 else:
1061 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001062 if self.reading:
1063 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001064 return "break"
1065
1066 def eof_callback(self, event):
1067 if self.executing and not self.reading:
1068 return # Let the default binding (delete next char) take over
1069 if not (self.text.compare("iomark", "==", "insert") and
1070 self.text.compare("insert", "==", "end-1c")):
1071 return # Let the default binding (delete next char) take over
1072 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001073 self.resetoutput()
1074 self.close()
1075 else:
1076 self.canceled = 0
1077 self.endoffile = 1
1078 self.top.quit()
1079 return "break"
1080
David Scherer7aced172000-08-15 01:13:23 +00001081 def linefeed_callback(self, event):
1082 # Insert a linefeed without entering anything (still autoindented)
1083 if self.reading:
1084 self.text.insert("insert", "\n")
1085 self.text.see("insert")
1086 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001087 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001088 return "break"
1089
1090 def enter_callback(self, event):
1091 if self.executing and not self.reading:
1092 return # Let the default binding (insert '\n') take over
1093 # If some text is selected, recall the selection
1094 # (but only if this before the I/O mark)
1095 try:
1096 sel = self.text.get("sel.first", "sel.last")
1097 if sel:
1098 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001099 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001100 return "break"
1101 except:
1102 pass
1103 # If we're strictly before the line containing iomark, recall
1104 # the current line, less a leading prompt, less leading or
1105 # trailing whitespace
1106 if self.text.compare("insert", "<", "iomark linestart"):
1107 # Check if there's a relevant stdin range -- if so, use it
1108 prev = self.text.tag_prevrange("stdin", "insert")
1109 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001110 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001111 return "break"
1112 next = self.text.tag_nextrange("stdin", "insert")
1113 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001114 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001115 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001116 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001117 indices = self.text.tag_nextrange("console", "insert linestart")
1118 if indices and \
1119 self.text.compare(indices[0], "<=", "insert linestart"):
1120 self.recall(self.text.get(indices[1], "insert lineend"), event)
1121 else:
1122 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001123 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001124 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001125 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001126 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001127 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001128 # If we're in the current input and there's only whitespace
1129 # beyond the cursor, erase that whitespace first
1130 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001131 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001132 self.text.delete("insert", "end-1c")
1133 # If we're in the current input before its last line,
1134 # insert a newline right at the insert point
1135 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001136 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001137 return "break"
1138 # We're in the last line; append a newline and submit it
1139 self.text.mark_set("insert", "end-1c")
1140 if self.reading:
1141 self.text.insert("insert", "\n")
1142 self.text.see("insert")
1143 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001144 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001145 self.text.tag_add("stdin", "iomark", "end-1c")
1146 self.text.update_idletasks()
1147 if self.reading:
1148 self.top.quit() # Break out of recursive mainloop() in raw_input()
1149 else:
1150 self.runit()
1151 return "break"
1152
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001153 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001154 # remove leading and trailing empty or whitespace lines
1155 s = re.sub(r'^\s*\n', '' , s)
1156 s = re.sub(r'\n\s*$', '', s)
1157 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001158 self.text.undo_block_start()
1159 try:
1160 self.text.tag_remove("sel", "1.0", "end")
1161 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001162 prefix = self.text.get("insert linestart", "insert")
1163 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001164 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001165 prefix = self.text.get("insert linestart", "insert")
1166 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001167 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001168 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1169 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001170 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001171 if line.startswith(orig_base_indent):
1172 # replace orig base indentation with new indentation
1173 line = new_base_indent + line[len(orig_base_indent):]
1174 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001175 finally:
1176 self.text.see("insert")
1177 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001178
1179 def runit(self):
1180 line = self.text.get("iomark", "end-1c")
1181 # Strip off last newline and surrounding whitespace.
1182 # (To allow you to hit return twice to end a statement.)
1183 i = len(line)
1184 while i > 0 and line[i-1] in " \t":
1185 i = i-1
1186 if i > 0 and line[i-1] == "\n":
1187 i = i-1
1188 while i > 0 and line[i-1] in " \t":
1189 i = i-1
1190 line = line[:i]
1191 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001192
David Scherer7aced172000-08-15 01:13:23 +00001193 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001194 if self.interp.rpcclt:
1195 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001196 try:
1197 sys.last_traceback
1198 except:
1199 tkMessageBox.showerror("No stack trace",
1200 "There is no stack trace yet.\n"
1201 "(sys.last_traceback is not defined)",
1202 master=self.text)
1203 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001204 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001205 sv = StackBrowser(self.root, self.flist)
1206
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001207 def view_restart_mark(self, event=None):
1208 self.text.see("iomark")
1209 self.text.see("restart")
1210
1211 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001212 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001213
David Scherer7aced172000-08-15 01:13:23 +00001214 def showprompt(self):
1215 self.resetoutput()
1216 try:
1217 s = str(sys.ps1)
1218 except:
1219 s = ""
1220 self.console.write(s)
1221 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001222 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001223 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001224
1225 def resetoutput(self):
1226 source = self.text.get("iomark", "end-1c")
1227 if self.history:
1228 self.history.history_store(source)
1229 if self.text.get("end-2c") != "\n":
1230 self.text.insert("end-1c", "\n")
1231 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001232 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001233 sys.stdout.softspace = 0
1234
1235 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001236 try:
1237 self.text.mark_gravity("iomark", "right")
1238 OutputWindow.write(self, s, tags, "iomark")
1239 self.text.mark_gravity("iomark", "left")
1240 except:
1241 pass
David Scherer7aced172000-08-15 01:13:23 +00001242 if self.canceled:
1243 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001244 if not use_subprocess:
1245 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001246
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001247class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001248
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001249 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001250 self.shell = shell
1251 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001252 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001253 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001254
1255 def write(self, s):
1256 self.shell.write(s, self.tags)
1257
Florent Xiclunad630c042010-04-02 07:24:52 +00001258 def writelines(self, lines):
1259 for line in lines:
1260 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001261
1262 def flush(self):
1263 pass
1264
1265 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001266 return True
David Scherer7aced172000-08-15 01:13:23 +00001267
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001268
David Scherer7aced172000-08-15 01:13:23 +00001269usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001270
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001271USAGE: idle [-deins] [-t title] [file]*
1272 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1273 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001274
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001275 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001276 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001277
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001278The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001279
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001280 -e open an edit window
1281 -i open a shell window
1282
1283The following options imply -i and will open a shell:
1284
1285 -c cmd run the command in a shell, or
1286 -r file run script from file
1287
1288 -d enable the debugger
1289 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1290 -t title set title of shell window
1291
1292A default edit window will be bypassed when -c, -r, or - are used.
1293
1294[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1295
1296Examples:
1297
1298idle
1299 Open an edit window or shell depending on IDLE's configuration.
1300
1301idle foo.py foobar.py
1302 Edit the files, also open a shell if configured to start with shell.
1303
1304idle -est "Baz" foo.py
1305 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1306 window with the title "Baz".
1307
1308idle -c "import sys; print sys.argv" "foo"
1309 Open a shell window and run the command, passing "-c" in sys.argv[0]
1310 and "foo" in sys.argv[1].
1311
1312idle -d -s -r foo.py "Hello World"
1313 Open a shell window, run a startup script, enable the debugger, and
1314 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1315 sys.argv[1].
1316
1317echo "import sys; print sys.argv" | idle - "foobar"
1318 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1319 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001320"""
1321
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001323 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001324
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001325 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001326 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001327 enable_edit = False
1328 debug = False
1329 cmd = None
1330 script = None
1331 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001333 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001334 except getopt.error, msg:
1335 sys.stderr.write("Error: %s\n" % str(msg))
1336 sys.stderr.write(usage_msg)
1337 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001338 for o, a in opts:
1339 if o == '-c':
1340 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001342 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 debug = True
1344 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001345 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001346 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001347 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 if o == '-h':
1349 sys.stdout.write(usage_msg)
1350 sys.exit()
1351 if o == '-i':
1352 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001353 if o == '-n':
1354 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001355 if o == '-r':
1356 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 if os.path.isfile(script):
1358 pass
1359 else:
1360 print "No script file: ", script
1361 sys.exit()
1362 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001363 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 startup = True
1365 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001366 if o == '-t':
1367 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 enable_shell = True
1369 if args and args[0] == '-':
1370 cmd = sys.stdin.read()
1371 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001372 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 for i in range(len(sys.path)):
1374 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 if args and args[0] == '-':
1376 sys.argv = [''] + args[1:]
1377 elif cmd:
1378 sys.argv = ['-c'] + args
1379 elif script:
1380 sys.argv = [script] + args
1381 elif args:
1382 enable_edit = True
1383 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001384 for filename in args:
1385 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 for dir in pathx:
1387 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001388 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001390 else:
1391 dir = os.getcwd()
1392 if not dir in sys.path:
1393 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001394 # check the IDLE settings configuration (but command line overrides)
1395 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001396 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001397 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001398 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001399 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001400
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001401 fixwordbreaks(root)
1402 root.withdraw()
1403 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001404 macosxSupport.setupApp(root, flist)
1405
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001406 if enable_edit:
1407 if not (cmd or script):
1408 for filename in args:
1409 flist.open(filename)
1410 if not args:
1411 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001412 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001413 shell = flist.open_shell()
1414 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001415 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001416
1417 if macosxSupport.runningAsOSXApp() and flist.dict:
1418 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001419 # IDLE to be launched the shell window will open just in front of
1420 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001421 # there are open files.
1422 shell.top.lower()
1423
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 shell = flist.pyshell
1425 # handle remaining options:
1426 if debug:
1427 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001428 if startup:
1429 filename = os.environ.get("IDLESTARTUP") or \
1430 os.environ.get("PYTHONSTARTUP")
1431 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001432 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001433 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 shell.interp.runcommand("""if 1:
1435 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001436 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001437 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001438 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001439 if cmd:
1440 shell.interp.execsource(cmd)
1441 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001442 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001443 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001444
Ned Deily2a6f4b32011-01-30 00:18:47 +00001445 # Check for problematic OS X Tk versions and print a warning message
1446 # in the IDLE shell window; this is less intrusive than always opening
1447 # a separate window.
1448 tkversionwarning = macosxSupport.tkVersionWarning(root)
1449 if tkversionwarning:
1450 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1451
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001452 root.mainloop()
1453 root.destroy()
1454
David Scherer7aced172000-08-15 01:13:23 +00001455if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001456 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001457 main()