blob: ce83f190158922bd267c91004d2ed434f7f7b5e2 [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:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000210 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000211 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000212 lines = []
213 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000216 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000217 self.update_breakpoints()
218 breaks = self.breakpoints
219 if breaks:
220 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000221 new_file.close()
222
223 def restore_file_breaks(self):
224 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000225 filename = self.io.filename
226 if filename is None:
227 return
Chui Tey69371d62002-11-04 23:39:45 +0000228 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000229 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000230 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000231 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000232 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000233 for breakpoint_linenumber in breakpoint_linenumbers:
234 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000235
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000236 def update_breakpoints(self):
237 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000238 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000239 ranges = text.tag_ranges("BREAK")
240 linenumber_list = self.ranges_to_linenumbers(ranges)
241 self.breakpoints = linenumber_list
242
243 def ranges_to_linenumbers(self, ranges):
244 lines = []
245 for index in range(0, len(ranges), 2):
246 lineno = int(float(ranges[index]))
247 end = int(float(ranges[index+1]))
248 while lineno < end:
249 lines.append(lineno)
250 lineno += 1
251 return lines
252
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000253# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000254# def saved_change_hook(self):
255# "Extend base method - clear breaks if module is modified"
256# if not self.get_saved():
257# self.clear_file_breaks()
258# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000259
260 def _close(self):
261 "Extend base method - clear breaks when module is closed"
262 self.clear_file_breaks()
263 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000264
David Scherer7aced172000-08-15 01:13:23 +0000265
266class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000267 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000268
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000269 # override FileList's class variable, instances return PyShellEditorWindow
270 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000271 EditorWindow = PyShellEditorWindow
272
273 pyshell = None
274
275 def open_shell(self, event=None):
276 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000277 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000278 else:
279 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000280 if self.pyshell:
281 if not self.pyshell.begin():
282 return None
David Scherer7aced172000-08-15 01:13:23 +0000283 return self.pyshell
284
285
286class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000287 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000288
Steven M. Gavab77d3432002-03-02 07:16:21 +0000289 def __init__(self):
290 ColorDelegator.__init__(self)
291 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000292
293 def recolorize_main(self):
294 self.tag_remove("TODO", "1.0", "iomark")
295 self.tag_add("SYNC", "1.0", "iomark")
296 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000297
Steven M. Gavab77d3432002-03-02 07:16:21 +0000298 def LoadTagDefs(self):
299 ColorDelegator.LoadTagDefs(self)
300 theme = idleConf.GetOption('main','Theme','name')
301 self.tagdefs.update({
302 "stdin": {'background':None,'foreground':None},
303 "stdout": idleConf.GetHighlight(theme, "stdout"),
304 "stderr": idleConf.GetHighlight(theme, "stderr"),
305 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000306 })
David Scherer7aced172000-08-15 01:13:23 +0000307
David Scherer7aced172000-08-15 01:13:23 +0000308class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000309 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000310
311 def insert(self, index, chars, tags=None):
312 try:
313 if self.delegate.compare(index, "<", "iomark"):
314 self.delegate.bell()
315 return
316 except TclError:
317 pass
318 UndoDelegator.insert(self, index, chars, tags)
319
320 def delete(self, index1, index2=None):
321 try:
322 if self.delegate.compare(index1, "<", "iomark"):
323 self.delegate.bell()
324 return
325 except TclError:
326 pass
327 UndoDelegator.delete(self, index1, index2)
328
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000329
330class MyRPCClient(rpc.RPCClient):
331
332 def handle_EOF(self):
333 "Override the base class - just re-raise EOFError"
334 raise EOFError
335
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000336
David Scherer7aced172000-08-15 01:13:23 +0000337class ModifiedInterpreter(InteractiveInterpreter):
338
339 def __init__(self, tkconsole):
340 self.tkconsole = tkconsole
341 locals = sys.modules['__main__'].__dict__
342 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000343 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000344 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000345 self.subprocess_arglist = None
346 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700347 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000348
Chui Tey5d2af632002-05-26 13:36:41 +0000349 rpcclt = None
350 rpcpid = None
351
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000352 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000353 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000354 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000355 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000356 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000357
Tony Lowndsf53dec22002-12-20 04:24:43 +0000358 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000359 assert (self.port!=0), (
360 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000361 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000362 if 1/2 > 0: # account for new division
363 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000364 # Maybe IDLE is installed and is being accessed via sys.path,
365 # or maybe it's not installed and the idle.py script is being
366 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000367 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
368 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000369 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000370 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000371 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000372 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000373 if sys.platform[:3] == 'win' and ' ' in sys.executable:
374 # handle embedded space in path by quoting the argument
375 decorated_exec = '"%s"' % sys.executable
376 else:
377 decorated_exec = sys.executable
378 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000379
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000380 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000381 addr = (HOST, self.port)
382 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000383 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000384 time.sleep(i)
385 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000386 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000387 break
388 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000389 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000390 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000391 self.display_port_binding_error()
392 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000393 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
394 self.port = self.rpcclt.listening_sock.getsockname()[1]
395 # if PORT was not 0, probably working with a remote execution server
396 if PORT != 0:
397 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
398 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
399 # on Windows since the implementation allows two active sockets on
400 # the same address!
401 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
402 socket.SO_REUSEADDR, 1)
403 self.spawn_subprocess()
404 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000405 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000406 self.rpcclt.listening_sock.settimeout(10)
407 try:
408 self.rpcclt.accept()
409 except socket.timeout, err:
410 self.display_no_subprocess_error()
411 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000412 self.rpcclt.register("stdin", self.tkconsole)
413 self.rpcclt.register("stdout", self.tkconsole.stdout)
414 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000415 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000416 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000417 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000418 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000419 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000420 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000421
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000422 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000423 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000424 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000425 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000426 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000427 debug = self.getdebugger()
428 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000429 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000430 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000431 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
432 except:
433 pass
434 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000435 self.rpcclt.close()
436 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000437 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000438 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000439 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000440 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000441 try:
442 self.rpcclt.accept()
443 except socket.timeout, err:
444 self.display_no_subprocess_error()
445 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000446 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000447 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000448 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000449 if was_executing:
450 console.write('\n')
451 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000452 halfbar = ((int(console.width) - 16) // 2) * '='
453 console.write(halfbar + ' RESTART ' + halfbar)
454 console.text.mark_set("restart", "end-1c")
455 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000456 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000457 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000458 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000459 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000460 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000461 # reload remote debugger breakpoints for all PyShellEditWindows
462 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700463 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000464 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000465 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000466
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000467 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000468 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000469
470 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000471 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000472
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000473 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000474 try:
475 self.rpcclt.close()
476 except AttributeError: # no socket
477 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000478 self.unix_terminate()
479 self.tkconsole.executing = False
480 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000481
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 def unix_terminate(self):
483 "UNIX: make sure subprocess is terminated and collect status"
484 if hasattr(os, 'kill'):
485 try:
486 os.kill(self.rpcpid, SIGTERM)
487 except OSError:
488 # process already terminated:
489 return
490 else:
491 try:
492 os.waitpid(self.rpcpid, 0)
493 except OSError:
494 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000495
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000496 def transfer_path(self):
497 self.runcommand("""if 1:
498 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000499 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000500 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000501 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000502
Chui Tey5d2af632002-05-26 13:36:41 +0000503 active_seq = None
504
505 def poll_subprocess(self):
506 clt = self.rpcclt
507 if clt is None:
508 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000509 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000510 response = clt.pollresponse(self.active_seq, wait=0.05)
511 except (EOFError, IOError, KeyboardInterrupt):
512 # lost connection or subprocess terminated itself, restart
513 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000514 if self.tkconsole.closing:
515 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000516 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000517 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000518 if response:
519 self.tkconsole.resetoutput()
520 self.active_seq = None
521 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000522 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000523 if how == "OK":
524 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000525 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000526 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000527 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
528 self.remote_stack_viewer()
529 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000530 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
531 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000532 print >>console, errmsg, what
533 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000534 try:
535 self.tkconsole.endexecuting()
536 except AttributeError: # shell may have closed
537 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000538 # Reschedule myself
539 if not self.tkconsole.closing:
540 self.tkconsole.text.after(self.tkconsole.pollinterval,
541 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000542
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000543 debugger = None
544
545 def setdebugger(self, debugger):
546 self.debugger = debugger
547
548 def getdebugger(self):
549 return self.debugger
550
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000551 def open_remote_stack_viewer(self):
552 """Initiate the remote stack viewer from a separate thread.
553
554 This method is called from the subprocess, and by returning from this
555 method we allow the subprocess to unblock. After a bit the shell
556 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000557 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000558 the RPC mechanism.
559
560 """
561 self.tkconsole.text.after(300, self.remote_stack_viewer)
562 return
563
Chui Tey5d2af632002-05-26 13:36:41 +0000564 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000565 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000566 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000567 if oid is None:
568 self.tkconsole.root.bell()
569 return
570 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000571 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000572 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000573 theme = idleConf.GetOption('main','Theme','name')
574 background = idleConf.GetHighlight(theme, 'normal')['background']
575 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000576 sc.frame.pack(expand=1, fill="both")
577 node = TreeNode(sc.canvas, None, item)
578 node.expand()
579 # XXX Should GC the remote tree when closing the window
580
David Scherer7aced172000-08-15 01:13:23 +0000581 gid = 0
582
583 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000584 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000585 filename = self.stuffsource(source)
586 self.execfile(filename, source)
587
588 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000589 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000590 if source is None:
591 source = open(filename, "r").read()
592 try:
593 code = compile(source, filename, "exec")
594 except (OverflowError, SyntaxError):
595 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000596 tkerr = self.tkconsole.stderr
597 print>>tkerr, '*** Error in script or command!\n'
598 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000599 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000600 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000601 else:
602 self.runcode(code)
603
604 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000605 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000606 filename = self.stuffsource(source)
607 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000608 self.save_warnings_filters = warnings.filters[:]
609 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000610 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000611 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000612 try:
613 source = source.encode(IOBinding.encoding)
614 except UnicodeError:
615 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000616 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000617 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000618 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000619 # InteractiveInterpreter.runsource() calls its runcode() method,
620 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000621 return InteractiveInterpreter.runsource(self, source, filename)
622 finally:
623 if self.save_warnings_filters is not None:
624 warnings.filters[:] = self.save_warnings_filters
625 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000626
627 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000628 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000629 filename = "<pyshell#%d>" % self.gid
630 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000631 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000632 linecache.cache[filename] = len(source)+1, 0, lines, filename
633 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000634
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000635 def prepend_syspath(self, filename):
636 "Prepend sys.path with file's directory if not already included"
637 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000638 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000639 import sys as _sys
640 from os.path import dirname as _dirname
641 _dir = _dirname(_filename)
642 if not _dir in _sys.path:
643 _sys.path.insert(0, _dir)
644 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000645 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000646
David Scherer7aced172000-08-15 01:13:23 +0000647 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000648 """Extend base class method: Add Colorizing
649
650 Color the offending position instead of printing it and pointing at it
651 with a caret.
652
653 """
David Scherer7aced172000-08-15 01:13:23 +0000654 text = self.tkconsole.text
655 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000656 if stuff:
657 msg, lineno, offset, line = stuff
658 if lineno == 1:
659 pos = "iomark + %d chars" % (offset-1)
660 else:
661 pos = "iomark linestart + %d lines + %d chars" % \
662 (lineno-1, offset-1)
663 text.tag_add("ERROR", pos)
664 text.see(pos)
665 char = text.get(pos)
666 if char and char in IDENTCHARS:
667 text.tag_add("ERROR", pos + " wordstart", pos)
668 self.tkconsole.resetoutput()
669 self.write("SyntaxError: %s\n" % str(msg))
670 else:
David Scherer7aced172000-08-15 01:13:23 +0000671 self.tkconsole.resetoutput()
672 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000673 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000674
675 def unpackerror(self):
676 type, value, tb = sys.exc_info()
677 ok = type is SyntaxError
678 if ok:
679 try:
680 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000681 if not offset:
682 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000683 except:
684 ok = 0
685 if ok:
686 return msg, lineno, offset, line
687 else:
688 return None
689
690 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000691 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000692 self.tkconsole.resetoutput()
693 self.checklinecache()
694 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000695 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
696 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000697
698 def checklinecache(self):
699 c = linecache.cache
700 for key in c.keys():
701 if key[:1] + key[-1:] != "<>":
702 del c[key]
703
Chui Tey5d2af632002-05-26 13:36:41 +0000704 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000705 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000706 # The code better not raise an exception!
707 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000708 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000709 return 0
710 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000711 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000712 else:
713 exec code in self.locals
714 return 1
715
David Scherer7aced172000-08-15 01:13:23 +0000716 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000717 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000718 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000719 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000720 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000721 if self.save_warnings_filters is not None:
722 warnings.filters[:] = self.save_warnings_filters
723 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000724 debugger = self.debugger
725 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000726 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000727 if not debugger and self.rpcclt is not None:
728 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
729 (code,), {})
730 elif debugger:
731 debugger.run(code, self.locals)
732 else:
733 exec code in self.locals
734 except SystemExit:
735 if not self.tkconsole.closing:
736 if tkMessageBox.askyesno(
737 "Exit?",
738 "Do you want to exit altogether?",
739 default="yes",
740 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000741 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000742 else:
743 self.showtraceback()
744 else:
745 raise
746 except:
747 if use_subprocess:
748 print >>self.tkconsole.stderr, \
749 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000750 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000751 self.tkconsole.endexecuting()
752 else:
753 if self.tkconsole.canceled:
754 self.tkconsole.canceled = False
755 print >>self.tkconsole.stderr, "KeyboardInterrupt"
756 else:
757 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000758 finally:
759 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000760 try:
761 self.tkconsole.endexecuting()
762 except AttributeError: # shell may have closed
763 pass
David Scherer7aced172000-08-15 01:13:23 +0000764
765 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000766 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000767 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000768
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000769 def display_port_binding_error(self):
770 tkMessageBox.showerror(
771 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000772 "IDLE can't bind to a TCP/IP port, which is necessary to "
773 "communicate with its Python execution server. This might be "
774 "because no networking is installed on this computer. "
775 "Run IDLE with the -n command line switch to start without a "
776 "subprocess and refer to Help/IDLE Help 'Running without a "
777 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000778 master=self.tkconsole.text)
779
780 def display_no_subprocess_error(self):
781 tkMessageBox.showerror(
782 "Subprocess Startup Error",
783 "IDLE's subprocess didn't make connection. Either IDLE can't "
784 "start a subprocess or personal firewall software is blocking "
785 "the connection.",
786 master=self.tkconsole.text)
787
788 def display_executing_dialog(self):
789 tkMessageBox.showerror(
790 "Already executing",
791 "The Python Shell window is already executing a command; "
792 "please wait until it is finished.",
793 master=self.tkconsole.text)
794
795
David Scherer7aced172000-08-15 01:13:23 +0000796class PyShell(OutputWindow):
797
798 shell_title = "Python Shell"
799
800 # Override classes
801 ColorDelegator = ModifiedColorDelegator
802 UndoDelegator = ModifiedUndoDelegator
803
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000804 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000805 menu_specs = [
806 ("file", "_File"),
807 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000808 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000809 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000810 ("windows", "_Windows"),
811 ("help", "_Help"),
812 ]
David Scherer7aced172000-08-15 01:13:23 +0000813
Ronald Oussoren19302d92006-06-11 14:33:36 +0000814 if macosxSupport.runningAsOSXApp():
815 del menu_specs[-3]
816 menu_specs[-2] = ("windows", "_Window")
817
818
David Scherer7aced172000-08-15 01:13:23 +0000819 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000820 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000821
822 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000823 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000824 ms = self.menu_specs
825 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000826 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000827 self.interp = ModifiedInterpreter(self)
828 if flist is None:
829 root = Tk()
830 fixwordbreaks(root)
831 root.withdraw()
832 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000833 #
David Scherer7aced172000-08-15 01:13:23 +0000834 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000835 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000836## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
837 self.usetabs = True
838 # indentwidth must be 8 when using tabs. See note in EditorWindow:
839 self.indentwidth = 8
840 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000841 #
David Scherer7aced172000-08-15 01:13:23 +0000842 text = self.text
843 text.configure(wrap="char")
844 text.bind("<<newline-and-indent>>", self.enter_callback)
845 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
846 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000847 text.bind("<<end-of-file>>", self.eof_callback)
848 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000849 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000850 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000851 if use_subprocess:
852 text.bind("<<view-restart>>", self.view_restart_mark)
853 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000854 #
David Scherer7aced172000-08-15 01:13:23 +0000855 self.save_stdout = sys.stdout
856 self.save_stderr = sys.stderr
857 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000858 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000859 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
860 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
861 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000862 if not use_subprocess:
863 sys.stdout = self.stdout
864 sys.stderr = self.stderr
865 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000866 #
David Scherer7aced172000-08-15 01:13:23 +0000867 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000868 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000869 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000870
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000871 def get_standard_extension_names(self):
872 return idleConf.GetExtensions(shell_only=True)
873
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000874 reading = False
875 executing = False
876 canceled = False
877 endoffile = False
878 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000879
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000880 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000881 global warning_stream
882 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000883
884 def get_warning_stream(self):
885 return warning_stream
886
David Scherer7aced172000-08-15 01:13:23 +0000887 def toggle_debugger(self, event=None):
888 if self.executing:
889 tkMessageBox.showerror("Don't debug now",
890 "You can only toggle the debugger when idle",
891 master=self.text)
892 self.set_debugger_indicator()
893 return "break"
894 else:
895 db = self.interp.getdebugger()
896 if db:
897 self.close_debugger()
898 else:
899 self.open_debugger()
900
901 def set_debugger_indicator(self):
902 db = self.interp.getdebugger()
903 self.setvar("<<toggle-debugger>>", not not db)
904
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000905 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000906 pass # All we need is the variable
907
908 def close_debugger(self):
909 db = self.interp.getdebugger()
910 if db:
911 self.interp.setdebugger(None)
912 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000913 if self.interp.rpcclt:
914 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000915 self.resetoutput()
916 self.console.write("[DEBUG OFF]\n")
917 sys.ps1 = ">>> "
918 self.showprompt()
919 self.set_debugger_indicator()
920
921 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000922 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000923 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
924 self)
925 else:
926 dbg_gui = Debugger.Debugger(self)
927 self.interp.setdebugger(dbg_gui)
928 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000929 sys.ps1 = "[DEBUG ON]\n>>> "
930 self.showprompt()
931 self.set_debugger_indicator()
932
David Scherer7aced172000-08-15 01:13:23 +0000933 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000934 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000935 self.resetoutput()
936 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000937
938 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000939 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000940 self.executing = 0
941 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000942 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000943
944 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000945 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000946 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000947 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000948 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000949 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000950 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000951 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000952 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000953 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000954 if self.reading:
955 self.top.quit()
956 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000957 self.closing = True
958 # Wait for poll_subprocess() rescheduling to stop
959 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000960
961 def close2(self):
962 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000963
964 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000965 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000966 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000967 if use_subprocess:
968 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000969 # Restore std streams
970 sys.stdout = self.save_stdout
971 sys.stderr = self.save_stderr
972 sys.stdin = self.save_stdin
973 # Break cycles
974 self.interp = None
975 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000976 self.flist.pyshell = None
977 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000978 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000979
980 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000981 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000982 return True
David Scherer7aced172000-08-15 01:13:23 +0000983
984 def short_title(self):
985 return self.shell_title
986
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000987 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000988 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000989
David Scherer7aced172000-08-15 01:13:23 +0000990 def begin(self):
991 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000992 if use_subprocess:
993 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000994 client = self.interp.start_subprocess()
995 if not client:
996 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000997 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000998 else:
999 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001000 self.write("Python %s on %s\n%s\n%s" %
1001 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001002 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001003 import Tkinter
1004 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001005 return True
David Scherer7aced172000-08-15 01:13:23 +00001006
1007 def readline(self):
1008 save = self.reading
1009 try:
1010 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001011 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001012 finally:
1013 self.reading = save
1014 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001015 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1016 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001017 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001018 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001019 try:
1020 line = line.encode(IOBinding.encoding)
1021 except UnicodeError:
1022 pass
David Scherer7aced172000-08-15 01:13:23 +00001023 self.resetoutput()
1024 if self.canceled:
1025 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001026 if not use_subprocess:
1027 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001028 if self.endoffile:
1029 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001030 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001031 return line
1032
1033 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001034 return True
David Scherer7aced172000-08-15 01:13:23 +00001035
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001036 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001037 try:
1038 if self.text.compare("sel.first", "!=", "sel.last"):
1039 return # Active selection -- always use default binding
1040 except:
1041 pass
1042 if not (self.executing or self.reading):
1043 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001044 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001045 self.showprompt()
1046 return "break"
1047 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001048 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001049 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001050 if self.interp.getdebugger():
1051 self.interp.restart_subprocess()
1052 else:
1053 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001054 if self.reading:
1055 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001056 return "break"
1057
1058 def eof_callback(self, event):
1059 if self.executing and not self.reading:
1060 return # Let the default binding (delete next char) take over
1061 if not (self.text.compare("iomark", "==", "insert") and
1062 self.text.compare("insert", "==", "end-1c")):
1063 return # Let the default binding (delete next char) take over
1064 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001065 self.resetoutput()
1066 self.close()
1067 else:
1068 self.canceled = 0
1069 self.endoffile = 1
1070 self.top.quit()
1071 return "break"
1072
David Scherer7aced172000-08-15 01:13:23 +00001073 def linefeed_callback(self, event):
1074 # Insert a linefeed without entering anything (still autoindented)
1075 if self.reading:
1076 self.text.insert("insert", "\n")
1077 self.text.see("insert")
1078 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001079 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001080 return "break"
1081
1082 def enter_callback(self, event):
1083 if self.executing and not self.reading:
1084 return # Let the default binding (insert '\n') take over
1085 # If some text is selected, recall the selection
1086 # (but only if this before the I/O mark)
1087 try:
1088 sel = self.text.get("sel.first", "sel.last")
1089 if sel:
1090 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001091 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001092 return "break"
1093 except:
1094 pass
1095 # If we're strictly before the line containing iomark, recall
1096 # the current line, less a leading prompt, less leading or
1097 # trailing whitespace
1098 if self.text.compare("insert", "<", "iomark linestart"):
1099 # Check if there's a relevant stdin range -- if so, use it
1100 prev = self.text.tag_prevrange("stdin", "insert")
1101 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001102 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001103 return "break"
1104 next = self.text.tag_nextrange("stdin", "insert")
1105 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001106 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001107 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001108 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001109 indices = self.text.tag_nextrange("console", "insert linestart")
1110 if indices and \
1111 self.text.compare(indices[0], "<=", "insert linestart"):
1112 self.recall(self.text.get(indices[1], "insert lineend"), event)
1113 else:
1114 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001115 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001116 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001117 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001118 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001119 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001120 # If we're in the current input and there's only whitespace
1121 # beyond the cursor, erase that whitespace first
1122 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001123 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001124 self.text.delete("insert", "end-1c")
1125 # If we're in the current input before its last line,
1126 # insert a newline right at the insert point
1127 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001128 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001129 return "break"
1130 # We're in the last line; append a newline and submit it
1131 self.text.mark_set("insert", "end-1c")
1132 if self.reading:
1133 self.text.insert("insert", "\n")
1134 self.text.see("insert")
1135 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001136 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001137 self.text.tag_add("stdin", "iomark", "end-1c")
1138 self.text.update_idletasks()
1139 if self.reading:
1140 self.top.quit() # Break out of recursive mainloop() in raw_input()
1141 else:
1142 self.runit()
1143 return "break"
1144
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001145 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001146 # remove leading and trailing empty or whitespace lines
1147 s = re.sub(r'^\s*\n', '' , s)
1148 s = re.sub(r'\n\s*$', '', s)
1149 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001150 self.text.undo_block_start()
1151 try:
1152 self.text.tag_remove("sel", "1.0", "end")
1153 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001154 prefix = self.text.get("insert linestart", "insert")
1155 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001156 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001157 prefix = self.text.get("insert linestart", "insert")
1158 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001159 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001160 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1161 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001162 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001163 if line.startswith(orig_base_indent):
1164 # replace orig base indentation with new indentation
1165 line = new_base_indent + line[len(orig_base_indent):]
1166 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001167 finally:
1168 self.text.see("insert")
1169 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001170
1171 def runit(self):
1172 line = self.text.get("iomark", "end-1c")
1173 # Strip off last newline and surrounding whitespace.
1174 # (To allow you to hit return twice to end a statement.)
1175 i = len(line)
1176 while i > 0 and line[i-1] in " \t":
1177 i = i-1
1178 if i > 0 and line[i-1] == "\n":
1179 i = i-1
1180 while i > 0 and line[i-1] in " \t":
1181 i = i-1
1182 line = line[:i]
1183 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001184
David Scherer7aced172000-08-15 01:13:23 +00001185 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001186 if self.interp.rpcclt:
1187 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001188 try:
1189 sys.last_traceback
1190 except:
1191 tkMessageBox.showerror("No stack trace",
1192 "There is no stack trace yet.\n"
1193 "(sys.last_traceback is not defined)",
1194 master=self.text)
1195 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001196 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001197 sv = StackBrowser(self.root, self.flist)
1198
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001199 def view_restart_mark(self, event=None):
1200 self.text.see("iomark")
1201 self.text.see("restart")
1202
1203 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001204 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001205
David Scherer7aced172000-08-15 01:13:23 +00001206 def showprompt(self):
1207 self.resetoutput()
1208 try:
1209 s = str(sys.ps1)
1210 except:
1211 s = ""
1212 self.console.write(s)
1213 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001214 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001215 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001216
1217 def resetoutput(self):
1218 source = self.text.get("iomark", "end-1c")
1219 if self.history:
1220 self.history.history_store(source)
1221 if self.text.get("end-2c") != "\n":
1222 self.text.insert("end-1c", "\n")
1223 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001224 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001225 sys.stdout.softspace = 0
1226
1227 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001228 try:
1229 self.text.mark_gravity("iomark", "right")
1230 OutputWindow.write(self, s, tags, "iomark")
1231 self.text.mark_gravity("iomark", "left")
1232 except:
1233 pass
David Scherer7aced172000-08-15 01:13:23 +00001234 if self.canceled:
1235 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001236 if not use_subprocess:
1237 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001238
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001239class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001240
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001241 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001242 self.shell = shell
1243 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001244 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001245 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001246
1247 def write(self, s):
1248 self.shell.write(s, self.tags)
1249
Florent Xiclunad630c042010-04-02 07:24:52 +00001250 def writelines(self, lines):
1251 for line in lines:
1252 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001253
1254 def flush(self):
1255 pass
1256
1257 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001258 return True
David Scherer7aced172000-08-15 01:13:23 +00001259
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001260
David Scherer7aced172000-08-15 01:13:23 +00001261usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001262
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001263USAGE: idle [-deins] [-t title] [file]*
1264 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1265 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001266
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001267 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001268 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001269
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001270The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001271
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001272 -e open an edit window
1273 -i open a shell window
1274
1275The following options imply -i and will open a shell:
1276
1277 -c cmd run the command in a shell, or
1278 -r file run script from file
1279
1280 -d enable the debugger
1281 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1282 -t title set title of shell window
1283
1284A default edit window will be bypassed when -c, -r, or - are used.
1285
1286[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1287
1288Examples:
1289
1290idle
1291 Open an edit window or shell depending on IDLE's configuration.
1292
1293idle foo.py foobar.py
1294 Edit the files, also open a shell if configured to start with shell.
1295
1296idle -est "Baz" foo.py
1297 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1298 window with the title "Baz".
1299
1300idle -c "import sys; print sys.argv" "foo"
1301 Open a shell window and run the command, passing "-c" in sys.argv[0]
1302 and "foo" in sys.argv[1].
1303
1304idle -d -s -r foo.py "Hello World"
1305 Open a shell window, run a startup script, enable the debugger, and
1306 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1307 sys.argv[1].
1308
1309echo "import sys; print sys.argv" | idle - "foobar"
1310 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1311 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001312"""
1313
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001314def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001316
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001317 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001318 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001319 enable_edit = False
1320 debug = False
1321 cmd = None
1322 script = None
1323 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001324 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001325 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001326 except getopt.error, msg:
1327 sys.stderr.write("Error: %s\n" % str(msg))
1328 sys.stderr.write(usage_msg)
1329 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001330 for o, a in opts:
1331 if o == '-c':
1332 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001333 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001334 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001335 debug = True
1336 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001337 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001338 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001339 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001340 if o == '-h':
1341 sys.stdout.write(usage_msg)
1342 sys.exit()
1343 if o == '-i':
1344 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001345 if o == '-n':
1346 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001347 if o == '-r':
1348 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001349 if os.path.isfile(script):
1350 pass
1351 else:
1352 print "No script file: ", script
1353 sys.exit()
1354 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001355 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001356 startup = True
1357 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001358 if o == '-t':
1359 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001360 enable_shell = True
1361 if args and args[0] == '-':
1362 cmd = sys.stdin.read()
1363 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001365 for i in range(len(sys.path)):
1366 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 if args and args[0] == '-':
1368 sys.argv = [''] + args[1:]
1369 elif cmd:
1370 sys.argv = ['-c'] + args
1371 elif script:
1372 sys.argv = [script] + args
1373 elif args:
1374 enable_edit = True
1375 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001376 for filename in args:
1377 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 for dir in pathx:
1379 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001380 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001382 else:
1383 dir = os.getcwd()
1384 if not dir in sys.path:
1385 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 # check the IDLE settings configuration (but command line overrides)
1387 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001388 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001390 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001392
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001393 fixwordbreaks(root)
1394 root.withdraw()
1395 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001396 macosxSupport.setupApp(root, flist)
1397
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001398 if enable_edit:
1399 if not (cmd or script):
1400 for filename in args:
1401 flist.open(filename)
1402 if not args:
1403 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001404 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001405 shell = flist.open_shell()
1406 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001407 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001408
1409 if macosxSupport.runningAsOSXApp() and flist.dict:
1410 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001411 # IDLE to be launched the shell window will open just in front of
1412 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001413 # there are open files.
1414 shell.top.lower()
1415
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 shell = flist.pyshell
1417 # handle remaining options:
1418 if debug:
1419 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001420 if startup:
1421 filename = os.environ.get("IDLESTARTUP") or \
1422 os.environ.get("PYTHONSTARTUP")
1423 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001425 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 shell.interp.runcommand("""if 1:
1427 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001428 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001429 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001430 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 if cmd:
1432 shell.interp.execsource(cmd)
1433 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001434 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001435 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001436
Ned Deily2a6f4b32011-01-30 00:18:47 +00001437 # Check for problematic OS X Tk versions and print a warning message
1438 # in the IDLE shell window; this is less intrusive than always opening
1439 # a separate window.
1440 tkversionwarning = macosxSupport.tkVersionWarning(root)
1441 if tkversionwarning:
1442 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1443
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001444 root.mainloop()
1445 root.destroy()
1446
David Scherer7aced172000-08-15 01:13:23 +00001447if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001448 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001449 main()