blob: acae420d9110a5fc4f3279bb2b2e91fa493d4cb9 [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,
Benjamin Petersonb76444b2008-10-16 19:40:14 +000064 lineno, file=file, 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
David Scherer7aced172000-08-15 01:13:23 +0000347
Chui Tey5d2af632002-05-26 13:36:41 +0000348 rpcclt = None
349 rpcpid = None
350
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000351 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000352 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000353 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000354 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000355 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000356
Tony Lowndsf53dec22002-12-20 04:24:43 +0000357 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000358 assert (self.port!=0), (
359 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000360 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000361 if 1/2 > 0: # account for new division
362 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000363 # Maybe IDLE is installed and is being accessed via sys.path,
364 # or maybe it's not installed and the idle.py script is being
365 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000366 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
367 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000368 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000369 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000370 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000371 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000372 if sys.platform[:3] == 'win' and ' ' in sys.executable:
373 # handle embedded space in path by quoting the argument
374 decorated_exec = '"%s"' % sys.executable
375 else:
376 decorated_exec = sys.executable
377 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000378
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000379 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000380 addr = (HOST, self.port)
381 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000382 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000383 time.sleep(i)
384 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000385 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000386 break
387 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000388 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000389 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000390 self.display_port_binding_error()
391 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000392 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
393 self.port = self.rpcclt.listening_sock.getsockname()[1]
394 # if PORT was not 0, probably working with a remote execution server
395 if PORT != 0:
396 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
397 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
398 # on Windows since the implementation allows two active sockets on
399 # the same address!
400 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
401 socket.SO_REUSEADDR, 1)
402 self.spawn_subprocess()
403 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000404 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 self.rpcclt.listening_sock.settimeout(10)
406 try:
407 self.rpcclt.accept()
408 except socket.timeout, err:
409 self.display_no_subprocess_error()
410 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000411 self.rpcclt.register("stdin", self.tkconsole)
412 self.rpcclt.register("stdout", self.tkconsole.stdout)
413 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000414 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000415 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000416 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000417 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000418 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000419 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000420
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000421 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000422 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000423 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000424 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000425 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000426 debug = self.getdebugger()
427 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000428 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000429 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000430 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
431 except:
432 pass
433 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000434 self.rpcclt.close()
435 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000436 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000437 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000438 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000439 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000440 try:
441 self.rpcclt.accept()
442 except socket.timeout, err:
443 self.display_no_subprocess_error()
444 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000445 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000446 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000447 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000448 if was_executing:
449 console.write('\n')
450 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000451 halfbar = ((int(console.width) - 16) // 2) * '='
452 console.write(halfbar + ' RESTART ' + halfbar)
453 console.text.mark_set("restart", "end-1c")
454 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000455 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000456 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000457 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000458 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000459 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000460 # reload remote debugger breakpoints for all PyShellEditWindows
461 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000462 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000463 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000464
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000465 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000466 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000467
468 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000469 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000470
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000471 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000472 try:
473 self.rpcclt.close()
474 except AttributeError: # no socket
475 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000476 self.unix_terminate()
477 self.tkconsole.executing = False
478 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000479
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000480 def unix_terminate(self):
481 "UNIX: make sure subprocess is terminated and collect status"
482 if hasattr(os, 'kill'):
483 try:
484 os.kill(self.rpcpid, SIGTERM)
485 except OSError:
486 # process already terminated:
487 return
488 else:
489 try:
490 os.waitpid(self.rpcpid, 0)
491 except OSError:
492 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000493
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000494 def transfer_path(self):
495 self.runcommand("""if 1:
496 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000497 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000498 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000499 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000500
Chui Tey5d2af632002-05-26 13:36:41 +0000501 active_seq = None
502
503 def poll_subprocess(self):
504 clt = self.rpcclt
505 if clt is None:
506 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000507 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000508 response = clt.pollresponse(self.active_seq, wait=0.05)
509 except (EOFError, IOError, KeyboardInterrupt):
510 # lost connection or subprocess terminated itself, restart
511 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000512 if self.tkconsole.closing:
513 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000514 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000515 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000516 if response:
517 self.tkconsole.resetoutput()
518 self.active_seq = None
519 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000520 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000521 if how == "OK":
522 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000523 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000524 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000525 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
526 self.remote_stack_viewer()
527 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000528 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
529 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000530 print >>console, errmsg, what
531 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000532 try:
533 self.tkconsole.endexecuting()
534 except AttributeError: # shell may have closed
535 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000536 # Reschedule myself
537 if not self.tkconsole.closing:
538 self.tkconsole.text.after(self.tkconsole.pollinterval,
539 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000540
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000541 debugger = None
542
543 def setdebugger(self, debugger):
544 self.debugger = debugger
545
546 def getdebugger(self):
547 return self.debugger
548
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000549 def open_remote_stack_viewer(self):
550 """Initiate the remote stack viewer from a separate thread.
551
552 This method is called from the subprocess, and by returning from this
553 method we allow the subprocess to unblock. After a bit the shell
554 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000555 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000556 the RPC mechanism.
557
558 """
559 self.tkconsole.text.after(300, self.remote_stack_viewer)
560 return
561
Chui Tey5d2af632002-05-26 13:36:41 +0000562 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000563 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000564 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000565 if oid is None:
566 self.tkconsole.root.bell()
567 return
568 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000569 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000570 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000571 theme = idleConf.GetOption('main','Theme','name')
572 background = idleConf.GetHighlight(theme, 'normal')['background']
573 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000574 sc.frame.pack(expand=1, fill="both")
575 node = TreeNode(sc.canvas, None, item)
576 node.expand()
577 # XXX Should GC the remote tree when closing the window
578
David Scherer7aced172000-08-15 01:13:23 +0000579 gid = 0
580
581 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000582 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000583 filename = self.stuffsource(source)
584 self.execfile(filename, source)
585
586 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000587 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000588 if source is None:
589 source = open(filename, "r").read()
590 try:
591 code = compile(source, filename, "exec")
592 except (OverflowError, SyntaxError):
593 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000594 tkerr = self.tkconsole.stderr
595 print>>tkerr, '*** Error in script or command!\n'
596 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000597 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000598 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000599 else:
600 self.runcode(code)
601
602 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000603 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000604 filename = self.stuffsource(source)
605 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000606 self.save_warnings_filters = warnings.filters[:]
607 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000608 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000609 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000610 try:
611 source = source.encode(IOBinding.encoding)
612 except UnicodeError:
613 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000614 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000615 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000616 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000617 # InteractiveInterpreter.runsource() calls its runcode() method,
618 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000619 return InteractiveInterpreter.runsource(self, source, filename)
620 finally:
621 if self.save_warnings_filters is not None:
622 warnings.filters[:] = self.save_warnings_filters
623 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000624
625 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000626 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000627 filename = "<pyshell#%d>" % self.gid
628 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000629 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000630 linecache.cache[filename] = len(source)+1, 0, lines, filename
631 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000632
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000633 def prepend_syspath(self, filename):
634 "Prepend sys.path with file's directory if not already included"
635 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000636 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000637 import sys as _sys
638 from os.path import dirname as _dirname
639 _dir = _dirname(_filename)
640 if not _dir in _sys.path:
641 _sys.path.insert(0, _dir)
642 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000643 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000644
David Scherer7aced172000-08-15 01:13:23 +0000645 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000646 """Extend base class method: Add Colorizing
647
648 Color the offending position instead of printing it and pointing at it
649 with a caret.
650
651 """
David Scherer7aced172000-08-15 01:13:23 +0000652 text = self.tkconsole.text
653 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000654 if stuff:
655 msg, lineno, offset, line = stuff
656 if lineno == 1:
657 pos = "iomark + %d chars" % (offset-1)
658 else:
659 pos = "iomark linestart + %d lines + %d chars" % \
660 (lineno-1, offset-1)
661 text.tag_add("ERROR", pos)
662 text.see(pos)
663 char = text.get(pos)
664 if char and char in IDENTCHARS:
665 text.tag_add("ERROR", pos + " wordstart", pos)
666 self.tkconsole.resetoutput()
667 self.write("SyntaxError: %s\n" % str(msg))
668 else:
David Scherer7aced172000-08-15 01:13:23 +0000669 self.tkconsole.resetoutput()
670 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000671 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000672
673 def unpackerror(self):
674 type, value, tb = sys.exc_info()
675 ok = type is SyntaxError
676 if ok:
677 try:
678 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000679 if not offset:
680 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000681 except:
682 ok = 0
683 if ok:
684 return msg, lineno, offset, line
685 else:
686 return None
687
688 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000689 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000690 self.tkconsole.resetoutput()
691 self.checklinecache()
692 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000693 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
694 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000695
696 def checklinecache(self):
697 c = linecache.cache
698 for key in c.keys():
699 if key[:1] + key[-1:] != "<>":
700 del c[key]
701
Chui Tey5d2af632002-05-26 13:36:41 +0000702 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000703 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000704 # The code better not raise an exception!
705 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000706 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000707 return 0
708 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000709 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000710 else:
711 exec code in self.locals
712 return 1
713
David Scherer7aced172000-08-15 01:13:23 +0000714 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000715 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000716 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000717 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000718 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000719 if self.save_warnings_filters is not None:
720 warnings.filters[:] = self.save_warnings_filters
721 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000722 debugger = self.debugger
723 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000724 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000725 if not debugger and self.rpcclt is not None:
726 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
727 (code,), {})
728 elif debugger:
729 debugger.run(code, self.locals)
730 else:
731 exec code in self.locals
732 except SystemExit:
733 if not self.tkconsole.closing:
734 if tkMessageBox.askyesno(
735 "Exit?",
736 "Do you want to exit altogether?",
737 default="yes",
738 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000739 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000740 else:
741 self.showtraceback()
742 else:
743 raise
744 except:
745 if use_subprocess:
746 print >>self.tkconsole.stderr, \
747 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000748 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000749 self.tkconsole.endexecuting()
750 else:
751 if self.tkconsole.canceled:
752 self.tkconsole.canceled = False
753 print >>self.tkconsole.stderr, "KeyboardInterrupt"
754 else:
755 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000756 finally:
757 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000758 try:
759 self.tkconsole.endexecuting()
760 except AttributeError: # shell may have closed
761 pass
David Scherer7aced172000-08-15 01:13:23 +0000762
763 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000764 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000765 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000766
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000767 def display_port_binding_error(self):
768 tkMessageBox.showerror(
769 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000770 "IDLE can't bind to a TCP/IP port, which is necessary to "
771 "communicate with its Python execution server. This might be "
772 "because no networking is installed on this computer. "
773 "Run IDLE with the -n command line switch to start without a "
774 "subprocess and refer to Help/IDLE Help 'Running without a "
775 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000776 master=self.tkconsole.text)
777
778 def display_no_subprocess_error(self):
779 tkMessageBox.showerror(
780 "Subprocess Startup Error",
781 "IDLE's subprocess didn't make connection. Either IDLE can't "
782 "start a subprocess or personal firewall software is blocking "
783 "the connection.",
784 master=self.tkconsole.text)
785
786 def display_executing_dialog(self):
787 tkMessageBox.showerror(
788 "Already executing",
789 "The Python Shell window is already executing a command; "
790 "please wait until it is finished.",
791 master=self.tkconsole.text)
792
793
David Scherer7aced172000-08-15 01:13:23 +0000794class PyShell(OutputWindow):
795
796 shell_title = "Python Shell"
797
798 # Override classes
799 ColorDelegator = ModifiedColorDelegator
800 UndoDelegator = ModifiedUndoDelegator
801
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000802 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000803 menu_specs = [
804 ("file", "_File"),
805 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000806 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000807 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000808 ("windows", "_Windows"),
809 ("help", "_Help"),
810 ]
David Scherer7aced172000-08-15 01:13:23 +0000811
Ronald Oussoren19302d92006-06-11 14:33:36 +0000812 if macosxSupport.runningAsOSXApp():
813 del menu_specs[-3]
814 menu_specs[-2] = ("windows", "_Window")
815
816
David Scherer7aced172000-08-15 01:13:23 +0000817 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000818 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000819
820 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000821 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000822 ms = self.menu_specs
823 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000824 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000825 self.interp = ModifiedInterpreter(self)
826 if flist is None:
827 root = Tk()
828 fixwordbreaks(root)
829 root.withdraw()
830 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000831 #
David Scherer7aced172000-08-15 01:13:23 +0000832 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000833 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000834## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
835 self.usetabs = True
836 # indentwidth must be 8 when using tabs. See note in EditorWindow:
837 self.indentwidth = 8
838 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000839 #
David Scherer7aced172000-08-15 01:13:23 +0000840 text = self.text
841 text.configure(wrap="char")
842 text.bind("<<newline-and-indent>>", self.enter_callback)
843 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
844 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000845 text.bind("<<end-of-file>>", self.eof_callback)
846 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000847 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000848 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000849 if use_subprocess:
850 text.bind("<<view-restart>>", self.view_restart_mark)
851 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000852 #
David Scherer7aced172000-08-15 01:13:23 +0000853 self.save_stdout = sys.stdout
854 self.save_stderr = sys.stderr
855 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000856 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000857 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
858 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
859 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000860 if not use_subprocess:
861 sys.stdout = self.stdout
862 sys.stderr = self.stderr
863 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000864 #
David Scherer7aced172000-08-15 01:13:23 +0000865 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000866 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000867 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000868
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000869 def get_standard_extension_names(self):
870 return idleConf.GetExtensions(shell_only=True)
871
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000872 reading = False
873 executing = False
874 canceled = False
875 endoffile = False
876 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000877
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000878 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000879 global warning_stream
880 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000881
882 def get_warning_stream(self):
883 return warning_stream
884
David Scherer7aced172000-08-15 01:13:23 +0000885 def toggle_debugger(self, event=None):
886 if self.executing:
887 tkMessageBox.showerror("Don't debug now",
888 "You can only toggle the debugger when idle",
889 master=self.text)
890 self.set_debugger_indicator()
891 return "break"
892 else:
893 db = self.interp.getdebugger()
894 if db:
895 self.close_debugger()
896 else:
897 self.open_debugger()
898
899 def set_debugger_indicator(self):
900 db = self.interp.getdebugger()
901 self.setvar("<<toggle-debugger>>", not not db)
902
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000903 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000904 pass # All we need is the variable
905
906 def close_debugger(self):
907 db = self.interp.getdebugger()
908 if db:
909 self.interp.setdebugger(None)
910 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000911 if self.interp.rpcclt:
912 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000913 self.resetoutput()
914 self.console.write("[DEBUG OFF]\n")
915 sys.ps1 = ">>> "
916 self.showprompt()
917 self.set_debugger_indicator()
918
919 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000920 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000921 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
922 self)
923 else:
924 dbg_gui = Debugger.Debugger(self)
925 self.interp.setdebugger(dbg_gui)
926 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000927 sys.ps1 = "[DEBUG ON]\n>>> "
928 self.showprompt()
929 self.set_debugger_indicator()
930
David Scherer7aced172000-08-15 01:13:23 +0000931 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000932 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000933 self.resetoutput()
934 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000935
936 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000937 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000938 self.executing = 0
939 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000940 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000941
942 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000943 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000944 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000945 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000946 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000947 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000948 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000949 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000950 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000951 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000952 if self.reading:
953 self.top.quit()
954 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000955 self.closing = True
956 # Wait for poll_subprocess() rescheduling to stop
957 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000958
959 def close2(self):
960 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000961
962 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000963 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000964 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000965 if use_subprocess:
966 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000967 # Restore std streams
968 sys.stdout = self.save_stdout
969 sys.stderr = self.save_stderr
970 sys.stdin = self.save_stdin
971 # Break cycles
972 self.interp = None
973 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000974 self.flist.pyshell = None
975 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000976 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000977
978 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000979 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000980 return True
David Scherer7aced172000-08-15 01:13:23 +0000981
982 def short_title(self):
983 return self.shell_title
984
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000985 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000986 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000987
David Scherer7aced172000-08-15 01:13:23 +0000988 def begin(self):
989 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000990 if use_subprocess:
991 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000992 client = self.interp.start_subprocess()
993 if not client:
994 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000995 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000996 else:
997 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +0000998 self.write("Python %s on %s\n%s\n%s" %
999 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001000 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001001 import Tkinter
1002 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001003 return True
David Scherer7aced172000-08-15 01:13:23 +00001004
1005 def readline(self):
1006 save = self.reading
1007 try:
1008 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001009 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001010 finally:
1011 self.reading = save
1012 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001013 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1014 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001015 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001016 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001017 try:
1018 line = line.encode(IOBinding.encoding)
1019 except UnicodeError:
1020 pass
David Scherer7aced172000-08-15 01:13:23 +00001021 self.resetoutput()
1022 if self.canceled:
1023 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001024 if not use_subprocess:
1025 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001026 if self.endoffile:
1027 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001028 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001029 return line
1030
1031 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001032 return True
David Scherer7aced172000-08-15 01:13:23 +00001033
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001034 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001035 try:
1036 if self.text.compare("sel.first", "!=", "sel.last"):
1037 return # Active selection -- always use default binding
1038 except:
1039 pass
1040 if not (self.executing or self.reading):
1041 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001042 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001043 self.showprompt()
1044 return "break"
1045 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001046 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001047 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001048 if self.interp.getdebugger():
1049 self.interp.restart_subprocess()
1050 else:
1051 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001052 if self.reading:
1053 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001054 return "break"
1055
1056 def eof_callback(self, event):
1057 if self.executing and not self.reading:
1058 return # Let the default binding (delete next char) take over
1059 if not (self.text.compare("iomark", "==", "insert") and
1060 self.text.compare("insert", "==", "end-1c")):
1061 return # Let the default binding (delete next char) take over
1062 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001063 self.resetoutput()
1064 self.close()
1065 else:
1066 self.canceled = 0
1067 self.endoffile = 1
1068 self.top.quit()
1069 return "break"
1070
David Scherer7aced172000-08-15 01:13:23 +00001071 def linefeed_callback(self, event):
1072 # Insert a linefeed without entering anything (still autoindented)
1073 if self.reading:
1074 self.text.insert("insert", "\n")
1075 self.text.see("insert")
1076 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001077 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001078 return "break"
1079
1080 def enter_callback(self, event):
1081 if self.executing and not self.reading:
1082 return # Let the default binding (insert '\n') take over
1083 # If some text is selected, recall the selection
1084 # (but only if this before the I/O mark)
1085 try:
1086 sel = self.text.get("sel.first", "sel.last")
1087 if sel:
1088 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001089 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001090 return "break"
1091 except:
1092 pass
1093 # If we're strictly before the line containing iomark, recall
1094 # the current line, less a leading prompt, less leading or
1095 # trailing whitespace
1096 if self.text.compare("insert", "<", "iomark linestart"):
1097 # Check if there's a relevant stdin range -- if so, use it
1098 prev = self.text.tag_prevrange("stdin", "insert")
1099 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001100 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001101 return "break"
1102 next = self.text.tag_nextrange("stdin", "insert")
1103 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001104 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001105 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001106 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001107 indices = self.text.tag_nextrange("console", "insert linestart")
1108 if indices and \
1109 self.text.compare(indices[0], "<=", "insert linestart"):
1110 self.recall(self.text.get(indices[1], "insert lineend"), event)
1111 else:
1112 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001113 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001114 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001115 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001116 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001117 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001118 # If we're in the current input and there's only whitespace
1119 # beyond the cursor, erase that whitespace first
1120 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001121 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001122 self.text.delete("insert", "end-1c")
1123 # If we're in the current input before its last line,
1124 # insert a newline right at the insert point
1125 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001126 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001127 return "break"
1128 # We're in the last line; append a newline and submit it
1129 self.text.mark_set("insert", "end-1c")
1130 if self.reading:
1131 self.text.insert("insert", "\n")
1132 self.text.see("insert")
1133 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001134 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001135 self.text.tag_add("stdin", "iomark", "end-1c")
1136 self.text.update_idletasks()
1137 if self.reading:
1138 self.top.quit() # Break out of recursive mainloop() in raw_input()
1139 else:
1140 self.runit()
1141 return "break"
1142
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001143 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001144 # remove leading and trailing empty or whitespace lines
1145 s = re.sub(r'^\s*\n', '' , s)
1146 s = re.sub(r'\n\s*$', '', s)
1147 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 self.text.undo_block_start()
1149 try:
1150 self.text.tag_remove("sel", "1.0", "end")
1151 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001152 prefix = self.text.get("insert linestart", "insert")
1153 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001154 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001155 prefix = self.text.get("insert linestart", "insert")
1156 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001157 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001158 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1159 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001160 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001161 if line.startswith(orig_base_indent):
1162 # replace orig base indentation with new indentation
1163 line = new_base_indent + line[len(orig_base_indent):]
1164 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001165 finally:
1166 self.text.see("insert")
1167 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001168
1169 def runit(self):
1170 line = self.text.get("iomark", "end-1c")
1171 # Strip off last newline and surrounding whitespace.
1172 # (To allow you to hit return twice to end a statement.)
1173 i = len(line)
1174 while i > 0 and line[i-1] in " \t":
1175 i = i-1
1176 if i > 0 and line[i-1] == "\n":
1177 i = i-1
1178 while i > 0 and line[i-1] in " \t":
1179 i = i-1
1180 line = line[:i]
1181 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001182
David Scherer7aced172000-08-15 01:13:23 +00001183 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001184 if self.interp.rpcclt:
1185 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001186 try:
1187 sys.last_traceback
1188 except:
1189 tkMessageBox.showerror("No stack trace",
1190 "There is no stack trace yet.\n"
1191 "(sys.last_traceback is not defined)",
1192 master=self.text)
1193 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001194 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001195 sv = StackBrowser(self.root, self.flist)
1196
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001197 def view_restart_mark(self, event=None):
1198 self.text.see("iomark")
1199 self.text.see("restart")
1200
1201 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001202 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001203
David Scherer7aced172000-08-15 01:13:23 +00001204 def showprompt(self):
1205 self.resetoutput()
1206 try:
1207 s = str(sys.ps1)
1208 except:
1209 s = ""
1210 self.console.write(s)
1211 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001212 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001213 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001214
1215 def resetoutput(self):
1216 source = self.text.get("iomark", "end-1c")
1217 if self.history:
1218 self.history.history_store(source)
1219 if self.text.get("end-2c") != "\n":
1220 self.text.insert("end-1c", "\n")
1221 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001222 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001223 sys.stdout.softspace = 0
1224
1225 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001226 try:
1227 self.text.mark_gravity("iomark", "right")
1228 OutputWindow.write(self, s, tags, "iomark")
1229 self.text.mark_gravity("iomark", "left")
1230 except:
1231 pass
David Scherer7aced172000-08-15 01:13:23 +00001232 if self.canceled:
1233 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001234 if not use_subprocess:
1235 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001236
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001237class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001238
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001239 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001240 self.shell = shell
1241 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001242 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001243 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001244
1245 def write(self, s):
1246 self.shell.write(s, self.tags)
1247
Florent Xiclunad630c042010-04-02 07:24:52 +00001248 def writelines(self, lines):
1249 for line in lines:
1250 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001251
1252 def flush(self):
1253 pass
1254
1255 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001256 return True
David Scherer7aced172000-08-15 01:13:23 +00001257
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001258
David Scherer7aced172000-08-15 01:13:23 +00001259usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001260
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001261USAGE: idle [-deins] [-t title] [file]*
1262 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1263 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001264
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001265 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001266 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001267
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001268The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001269
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001270 -e open an edit window
1271 -i open a shell window
1272
1273The following options imply -i and will open a shell:
1274
1275 -c cmd run the command in a shell, or
1276 -r file run script from file
1277
1278 -d enable the debugger
1279 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1280 -t title set title of shell window
1281
1282A default edit window will be bypassed when -c, -r, or - are used.
1283
1284[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1285
1286Examples:
1287
1288idle
1289 Open an edit window or shell depending on IDLE's configuration.
1290
1291idle foo.py foobar.py
1292 Edit the files, also open a shell if configured to start with shell.
1293
1294idle -est "Baz" foo.py
1295 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1296 window with the title "Baz".
1297
1298idle -c "import sys; print sys.argv" "foo"
1299 Open a shell window and run the command, passing "-c" in sys.argv[0]
1300 and "foo" in sys.argv[1].
1301
1302idle -d -s -r foo.py "Hello World"
1303 Open a shell window, run a startup script, enable the debugger, and
1304 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1305 sys.argv[1].
1306
1307echo "import sys; print sys.argv" | idle - "foobar"
1308 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1309 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001310"""
1311
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001312def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001313 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001314
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001315 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001316 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001317 enable_edit = False
1318 debug = False
1319 cmd = None
1320 script = None
1321 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001323 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001324 except getopt.error, msg:
1325 sys.stderr.write("Error: %s\n" % str(msg))
1326 sys.stderr.write(usage_msg)
1327 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001328 for o, a in opts:
1329 if o == '-c':
1330 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001331 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001333 debug = True
1334 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001335 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001336 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001337 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001338 if o == '-h':
1339 sys.stdout.write(usage_msg)
1340 sys.exit()
1341 if o == '-i':
1342 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001343 if o == '-n':
1344 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001345 if o == '-r':
1346 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001347 if os.path.isfile(script):
1348 pass
1349 else:
1350 print "No script file: ", script
1351 sys.exit()
1352 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001353 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001354 startup = True
1355 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001356 if o == '-t':
1357 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001358 enable_shell = True
1359 if args and args[0] == '-':
1360 cmd = sys.stdin.read()
1361 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001362 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001363 for i in range(len(sys.path)):
1364 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001365 if args and args[0] == '-':
1366 sys.argv = [''] + args[1:]
1367 elif cmd:
1368 sys.argv = ['-c'] + args
1369 elif script:
1370 sys.argv = [script] + args
1371 elif args:
1372 enable_edit = True
1373 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001374 for filename in args:
1375 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001376 for dir in pathx:
1377 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001378 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001380 else:
1381 dir = os.getcwd()
1382 if not dir in sys.path:
1383 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001384 # check the IDLE settings configuration (but command line overrides)
1385 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001386 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001388 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001389 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001390
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 fixwordbreaks(root)
1392 root.withdraw()
1393 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001394 macosxSupport.setupApp(root, flist)
1395
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001396 if enable_edit:
1397 if not (cmd or script):
1398 for filename in args:
1399 flist.open(filename)
1400 if not args:
1401 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001402 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001403 shell = flist.open_shell()
1404 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001405 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001406
1407 if macosxSupport.runningAsOSXApp() and flist.dict:
1408 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001409 # IDLE to be launched the shell window will open just in front of
1410 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001411 # there are open files.
1412 shell.top.lower()
1413
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001414 shell = flist.pyshell
1415 # handle remaining options:
1416 if debug:
1417 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001418 if startup:
1419 filename = os.environ.get("IDLESTARTUP") or \
1420 os.environ.get("PYTHONSTARTUP")
1421 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001423 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 shell.interp.runcommand("""if 1:
1425 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001426 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001427 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001428 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001429 if cmd:
1430 shell.interp.execsource(cmd)
1431 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001432 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001434
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001435 root.mainloop()
1436 root.destroy()
1437
David Scherer7aced172000-08-15 01:13:23 +00001438if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001439 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001440 main()